diff --git a/z80/z80.pl b/z80/z80.pl
index 212a502e..d0388833 100755
--- a/z80/z80.pl
+++ b/z80/z80.pl
@@ -1130,8 +1130,15 @@ shift
 	print << "shift";
       {
 	libspectrum_byte opcode2;
+
+	z80_do_m1_mappings( &opcode2, MAPPING_EARLY );
+
 	contend_read( PC, 4 );
-	opcode2 = readbyte_internal( PC ); PC++;
+	opcode2 = readbyte_internal( PC );
+
+	z80_do_m1_mappings( &opcode2, MAPPING_LATE );
+
+	PC++;
 	R++;
 #ifdef HAVE_ENOUGH_MEMORY
 	switch(opcode2) {
diff --git a/z80/z80_checks.h b/z80/z80_checks.h
index 390081ce..cd44bdf5 100644
--- a/z80/z80_checks.h
+++ b/z80/z80_checks.h
@@ -11,9 +11,9 @@ SETUP_CHECK( if1p, if1_available )
 SETUP_CHECK( divide_early, settings_current.divide_enabled )
 SETUP_CHECK( divmmc_early, settings_current.divmmc_enabled )
 SETUP_CHECK( spectranet_page, spectranet_available && !settings_current.spectranet_disable )
-SETUP_NEXT( opcode_delay )
+SETUP_NEXT( early_end )
 SETUP_CHECK( evenm1, even_m1 )
-SETUP_NEXT( run_opcode )
+SETUP_NEXT( evenm1_end )
 SETUP_CHECK( if1u, if1_available )
 SETUP_CHECK( divide_late, settings_current.divide_enabled )
 SETUP_CHECK( divmmc_late, settings_current.divmmc_enabled )
@@ -22,4 +22,4 @@ SETUP_CHECK( spectranet_unpage, spectranet_available )
 SETUP_CHECK( z80_iff2_read, z80.iff2_read )
 SETUP_CHECK( didaktik80snap, didaktik80_snap )
 SETUP_CHECK( svg_capture, svg_capture_active )
-SETUP_NEXT( end_opcode )
+SETUP_NEXT( late_end )
diff --git a/z80/z80_ops.c b/z80/z80_ops.c
index db1d56c8..26fe1f04 100755
--- a/z80/z80_ops.c
+++ b/z80/z80_ops.c
@@ -106,250 +106,288 @@ enum {
 
 #ifndef HAVE_ENOUGH_MEMORY
 static libspectrum_byte opcode = 0x00;
+//static libspectrum_byte opcode2 = 0x00;
 #endif
 
-/* Execute Z80 opcodes until the next event */
+enum ENUM_MAPPING_MODE {
+  MAPPING_INIT = 1,
+  MAPPING_EARLY,
+  MAPPING_EVENM1,
+  MAPPING_LATE
+};
+
 void
-z80_do_opcodes( void )
+z80_do_m1_mappings( libspectrum_byte *opcode, enum ENUM_MAPPING_MODE mode)
 {
-#ifdef HAVE_ENOUGH_MEMORY
-  libspectrum_byte opcode = 0x00;
-#endif
+  static void *cgoto[ numchecks ];
+  size_t next = 0; size_t check = 0;
 
   int even_m1 =
     machine_current->capabilities & LIBSPECTRUM_MACHINE_CAPABILITY_EVEN_M1; 
 
+  switch (mode) {
+    case MAPPING_INIT:
 #ifdef __GNUC__
 
 #undef SETUP_CHECK
 #define SETUP_CHECK( label, condition ) \
-  if( condition ) { cgoto[ next ] = &&label; next = pos_##label + 1; } \
-  check++;
+      if( condition ) { cgoto[ next ] = &&label; next = pos_##label + 1; } \
+      check++;
 
 #undef SETUP_NEXT
 #define SETUP_NEXT( label ) \
-  if( next != check ) { cgoto[ next ] = &&label; } \
-  next = check;
+      if( next != check ) { cgoto[ next ] = &&label; } \
+      next = check;
 
-  void *cgoto[ numchecks ]; size_t next = 0; size_t check = 0;
+      next = 0; check = 0;
 
 #include "z80_checks.h"
 
 #endif				/* #ifdef __GNUC__ */
+      break;
+    case MAPPING_EARLY:
+      /* Profiler */
+      CHECK( profile, profile_active )
 
-  while( tstates < event_next_event ) {
+      profile_map( PC );
 
-    /* Profiler */
-    CHECK( profile, profile_active )
+      END_CHECK
 
-    profile_map( PC );
+      /* If we're due an end of frame from RZX playback, generate one */
+      CHECK( rzx, rzx_playback )
 
-    END_CHECK
+      if( R + rzx_instructions_offset >= rzx_instruction_count ) {
+        event_add( tstates, spectrum_frame_event );
+        break;		/* And break out of the execution loop to let
+                             the interrupt happen */
+      }
 
-    /* If we're due an end of frame from RZX playback, generate one */
-    CHECK( rzx, rzx_playback )
+      END_CHECK
 
-    if( R + rzx_instructions_offset >= rzx_instruction_count ) {
-      event_add( tstates, spectrum_frame_event );
-      break;		/* And break out of the execution loop to let
-			   the interrupt happen */
-    }
+      /* Check if the debugger should become active at this point */
+      CHECK( debugger, debugger_mode != DEBUGGER_MODE_INACTIVE )
 
-    END_CHECK
+      if( debugger_check( DEBUGGER_BREAKPOINT_TYPE_EXECUTE, PC ) )
+        debugger_trap();
 
-    /* Check if the debugger should become active at this point */
-    CHECK( debugger, debugger_mode != DEBUGGER_MODE_INACTIVE )
+      END_CHECK
 
-    if( debugger_check( DEBUGGER_BREAKPOINT_TYPE_EXECUTE, PC ) )
-      debugger_trap();
+      CHECK( beta, beta_available )
 
-    END_CHECK
+#define NOT_128_TYPE_OR_IS_48_TYPE ( !( machine_current->capabilities & \
+              LIBSPECTRUM_MACHINE_CAPABILITY_128_MEMORY ) || \
+              machine_current->ram.current_rom )
+
+      if( beta_active ) {
+        if( NOT_128_TYPE_OR_IS_48_TYPE && PC >= 16384 ) {
+          beta_unpage();
+        }
+      } else if( ( PC & beta_pc_mask ) == beta_pc_value &&
+                 NOT_128_TYPE_OR_IS_48_TYPE ) {
+        beta_page();
+      }
 
-    CHECK( beta, beta_available )
+      END_CHECK
 
-#define NOT_128_TYPE_OR_IS_48_TYPE ( !( machine_current->capabilities & \
-            LIBSPECTRUM_MACHINE_CAPABILITY_128_MEMORY ) || \
-            machine_current->ram.current_rom )
+      CHECK( plusd, plusd_available )
 
-    if( beta_active ) {
-      if( NOT_128_TYPE_OR_IS_48_TYPE && PC >= 16384 ) {
-	beta_unpage();
+      if( PC == 0x0008 || PC == 0x003a || PC == 0x0066 || PC == 0x028e ) {
+        plusd_page();
       }
-    } else if( ( PC & beta_pc_mask ) == beta_pc_value &&
-               NOT_128_TYPE_OR_IS_48_TYPE ) {
-      beta_page();
-    }
 
-    END_CHECK
+      END_CHECK
 
-    CHECK( plusd, plusd_available )
+      CHECK( didaktik80, didaktik80_available )
 
-    if( PC == 0x0008 || PC == 0x003a || PC == 0x0066 || PC == 0x028e ) {
-      plusd_page();
-    }
+      if( PC == 0x0000 || PC == 0x0008 ) {
+        didaktik80_page();
+      } else if( PC == 0x1700 ) {
+        didaktik80_unpage();
+      }
 
-    END_CHECK
+      END_CHECK
 
-    CHECK( didaktik80, didaktik80_available )
+      CHECK( disciple, disciple_available )
 
-    if( PC == 0x0000 || PC == 0x0008 ) {
-      didaktik80_page();
-    } else if( PC == 0x1700 ) {
-      didaktik80_unpage();
-    }
+      if( PC == 0x0001 || PC == 0x0008 || PC == 0x0066 || PC == 0x028e ) {
+        disciple_page();
+      }
 
-    END_CHECK
+      END_CHECK
 
-    CHECK( disciple, disciple_available )
+      CHECK( usource, usource_available )
 
-    if( PC == 0x0001 || PC == 0x0008 || PC == 0x0066 || PC == 0x028e ) {
-      disciple_page();
-    }
+      if( PC == 0x2bae ) {
+        usource_toggle();
+      }
 
-    END_CHECK
+      END_CHECK
 
-    CHECK( usource, usource_available )
+      CHECK( multiface, multiface_activated )
 
-    if( PC == 0x2bae ) {
-      usource_toggle();
-    }
+      if( PC == 0x0066 ) {
+        multiface_setic8();
+      }
 
-    END_CHECK
+      END_CHECK
 
-    CHECK( multiface, multiface_activated )
+      CHECK( if1p, if1_available )
 
-    if( PC == 0x0066 ) {
-      multiface_setic8();
-    }
+      if( PC == 0x0008 || PC == 0x1708 ) {
+        if1_page();
+      }
 
-    END_CHECK
+      END_CHECK
 
-    CHECK( if1p, if1_available )
+      CHECK( divide_early, settings_current.divide_enabled )
 
-    if( PC == 0x0008 || PC == 0x1708 ) {
-      if1_page();
-    }
+      if( ( PC & 0xff00 ) == 0x3d00 ) {
+        divide_set_automap( 1 );
+      }
 
-    END_CHECK
+      END_CHECK
 
-    CHECK( divide_early, settings_current.divide_enabled )
-    
-    if( ( PC & 0xff00 ) == 0x3d00 ) {
-      divide_set_automap( 1 );
-    }
-    
-    END_CHECK
+      CHECK( divmmc_early, settings_current.divmmc_enabled )
 
-    CHECK( divmmc_early, settings_current.divmmc_enabled )
-    
-    if( ( PC & 0xff00 ) == 0x3d00 ) {
-      divmmc_set_automap( 1 );
-    }
-    
-    END_CHECK
+      if( ( PC & 0xff00 ) == 0x3d00 ) {
+        divmmc_set_automap( 1 );
+      }
 
-    CHECK( spectranet_page, spectranet_available && !settings_current.spectranet_disable )
+      END_CHECK
 
-    if( PC == 0x0008 || ((PC & 0xfff8) == 0x3ff8) )
-      spectranet_page( 0 );
+      CHECK( spectranet_page, spectranet_available && !settings_current.spectranet_disable )
 
-    if( PC == spectranet_programmable_trap &&
-      spectranet_programmable_trap_active )
-      event_add( 0, z80_nmi_event );
+      if( PC == 0x0008 || ((PC & 0xfff8) == 0x3ff8) )
+        spectranet_page( 0 );
 
-    END_CHECK
+      if( PC == spectranet_programmable_trap &&
+        spectranet_programmable_trap_active )
+        event_add( 0, z80_nmi_event );
 
-  opcode_delay:
+      END_CHECK
 
-    contend_read( PC, 4 );
+      early_end:
+      break;
 
-    /* Check to see if M1 cycles happen on even tstates */
-    CHECK( evenm1, even_m1 )
+    case MAPPING_EVENM1:
+      /* Check to see if M1 cycles happen on even tstates */
+      CHECK( evenm1, even_m1 )
 
-    if( tstates & 1 ) {
-      if( ++tstates == event_next_event ) {
-	break;
+      if( tstates & 1 ) {
+        if( ++tstates == event_next_event ) {
+          break;
+        }
       }
-    }
 
-    END_CHECK
+      END_CHECK
 
-  run_opcode:
-    /* Do the instruction fetch; readbyte_internal used here to avoid
-       triggering read breakpoints */
-    opcode = readbyte_internal( PC );
+      evenm1_end:
+      break;
 
-    CHECK( if1u, if1_available )
+    case MAPPING_LATE:
+      CHECK( if1u, if1_available )
 
-    if( PC == 0x0700 ) {
-      if1_unpage();
-    }
+      if( PC == 0x0700 ) {
+        if1_unpage();
+      }
 
-    END_CHECK
+      END_CHECK
 
-    CHECK( divide_late, settings_current.divide_enabled )
+      CHECK( divide_late, settings_current.divide_enabled )
 
-    if( ( PC & 0xfff8 ) == 0x1ff8 ) {
-      divide_set_automap( 0 );
-    } else if( (PC == 0x0000) || (PC == 0x0008) || (PC == 0x0038)
-      || (PC == 0x0066) || (PC == 0x04c6) || (PC == 0x0562) ) {
-      divide_set_automap( 1 );
-    }
-    
-    END_CHECK
+      if( ( PC & 0xfff8 ) == 0x1ff8 ) {
+        divide_set_automap( 0 );
+      } else if( (PC == 0x0000) || (PC == 0x0008) || (PC == 0x0038)
+        || (PC == 0x0066) || (PC == 0x04c6) || (PC == 0x0562) ) {
+        divide_set_automap( 1 );
+      }
 
-    CHECK( divmmc_late, settings_current.divmmc_enabled )
+      END_CHECK
 
-    if( ( PC & 0xfff8 ) == 0x1ff8 ) {
-      divmmc_set_automap( 0 );
-    } else if( (PC == 0x0000) || (PC == 0x0008) || (PC == 0x0038)
-      || (PC == 0x0066) || (PC == 0x04c6) || (PC == 0x0562) ) {
-      divmmc_set_automap( 1 );
-    }
-    
-    END_CHECK
+      CHECK( divmmc_late, settings_current.divmmc_enabled )
 
-    CHECK( opus, opus_available )
+      if( ( PC & 0xfff8 ) == 0x1ff8 ) {
+        divmmc_set_automap( 0 );
+      } else if( (PC == 0x0000) || (PC == 0x0008) || (PC == 0x0038)
+        || (PC == 0x0066) || (PC == 0x04c6) || (PC == 0x0562) ) {
+        divmmc_set_automap( 1 );
+      }
+
+      END_CHECK
 
-    if( opus_active ) {
-      if( PC == 0x1748 ) {
-        opus_unpage();
+      CHECK( opus, opus_available )
+
+      if( opus_active ) {
+        if( PC == 0x1748 ) {
+          opus_unpage();
+        }
+      } else if( PC == 0x0008 || PC == 0x0048 || PC == 0x1708 ) {
+        opus_page();
       }
-    } else if( PC == 0x0008 || PC == 0x0048 || PC == 0x1708 ) {
-      opus_page();
-    }
 
-    END_CHECK
+      END_CHECK
 
-    CHECK( spectranet_unpage, spectranet_available )
+      CHECK( spectranet_unpage, spectranet_available )
 
-    if( PC == 0x007c )
-      spectranet_unpage();
+      if( PC == 0x007c )
+        spectranet_unpage();
 
-    END_CHECK
+      END_CHECK
 
-    CHECK( z80_iff2_read, z80.iff2_read )
+      CHECK( z80_iff2_read, z80.iff2_read )
 
-    z80.iff2_read = 0;
-    /* Execute *one* instruction before reevaluating the checks */
-    event_add( tstates, z80_nmos_iff2_event );
+      z80.iff2_read = 0;
+      /* Execute *one* instruction before reevaluating the checks */
+      event_add( tstates, z80_nmos_iff2_event );
 
-    END_CHECK
+      END_CHECK
 
-    CHECK( didaktik80snap, didaktik80_snap )
+      CHECK( didaktik80snap, didaktik80_snap )
 
-    if( PC == 0x0066 && !didaktik80_active ) {
-      opcode = 0xc7;	/* RST 00 */
-      didaktik80_snap = 0; /* FIXME: this should be a time-based reset */
-    }
+      if( PC == 0x0066 && !didaktik80_active ) {
+        *opcode = 0xc7;	/* RST 00 */
+        didaktik80_snap = 0; /* FIXME: this should be a time-based reset */
+      }
+
+      END_CHECK
+
+      CHECK( svg_capture, svg_capture_active )
+
+      svg_capture();
+
+      END_CHECK
+
+      late_end:
+      break;
+  }
+}
 
-    END_CHECK
+/* Execute Z80 opcodes until the next event */
+void
+z80_do_opcodes( void )
+{
+#ifdef HAVE_ENOUGH_MEMORY
+  libspectrum_byte opcode = 0x00;
+//  libspectrum_byte opcode2 = 0x00;
+#endif
 
-    CHECK( svg_capture, svg_capture_active )
+  z80_do_m1_mappings( &opcode, MAPPING_INIT );
 
-    svg_capture();
+  while( tstates < event_next_event ) {
+
+    z80_do_m1_mappings( &opcode, MAPPING_EARLY );
+
+//  opcode_delay:
+    contend_read( PC, 4 );
+
+    z80_do_m1_mappings( &opcode, MAPPING_EVENM1 );
+
+//  run_opcode:
+    /* Do the instruction fetch; readbyte_internal used here to avoid
+       triggering read breakpoints */
+    opcode = readbyte_internal( PC );
 
-    END_CHECK
+    z80_do_m1_mappings( &opcode, MAPPING_LATE );
 
   end_opcode:
     PC++; R++;
