Index: hercules/README.S380
diff -c /dev/null hercules/README.S380:1.13
*** /dev/null	Mon Dec 12 18:20:30 2011
--- hercules/README.S380	Thu Mar 11 00:34:48 2010
***************
*** 0 ****
--- 1,43 ----
+ This version of Hercules is a modification by Paul
+ Edwards to standard Hercules 3.07 from:
+ 
+ http://www.hercules-390.org
+ 
+ to support the S/380 architecture.
+ 
+ If you wish to recreate the source code (Unix users
+ must do this), you will need to go there and download 
+ the Hercules 3.07 source code and then apply the patch 
+ provided here (hercules380*.txt) using the Unix "patch" 
+ utility (or equivalent). E.g. if you are in the same
+ directory as this readme file, you would use a command
+ something like this:
+ 
+ patch -p 1 <hercules380...txt
+ 
+ Also see the COPYRIGHT file and go to that HTML page
+ to read the license agreement.
+ 
+ 
+ Tip for people needing source.  The additional source
+ you need can be obtained from here:
+ http://www.pcre.org/
+ http://www.zlib.net/
+ http://www.bzip.org/
+ 
+ Note that as of Hercules/380 3.06 v 6.0, choosing S/370
+ will have no effect - it will be S/380. This is until
+ Fish's Hercgui is updated to recognize S/380. If you
+ require a plain S/370, just run normal Hercules. Obviously
+ you will lose the various enhancements such as extra
+ TDF tape formats if you do that.
+ 
+ Also check this if you are recompiling from source on
+ Windows and don't have access to VC2005:
+ 
+ http://www.softdevlabs.com/Hercules/hercules-msvc-build.html
+ 
+ This version of Hercules/380 only has the extra BSM/BASSM
+ instructions enabled, plus the ones officially designated (by
+ the Hercules team) as being activatable, to provide 
+ a stable development platform.
Index: hercules/assist.c
diff -c hercules/assist.c:1.1.1.2 hercules/assist.c:1.5
*** hercules/assist.c:1.1.1.2	Sat Feb 13 16:08:01 2010
--- hercules/assist.c	Sat Feb 13 17:11:27 2010
***************
*** 483,489 ****
  } /* end function release_cms_lock */
  
  
! #if !defined(FEATURE_TRACING)
  /*-------------------------------------------------------------------*/
  /* E508       - Trace SVC Interruption                         [SSE] */
  /*-------------------------------------------------------------------*/
--- 483,489 ----
  } /* end function release_cms_lock */
  
  
! #if !defined(FEATURE_TRACING) || defined(FEATURE_S380)
  /*-------------------------------------------------------------------*/
  /* E508       - Trace SVC Interruption                         [SSE] */
  /*-------------------------------------------------------------------*/
Index: hercules/bldcfg.c
diff -c hercules/bldcfg.c:1.1.1.3 hercules/bldcfg.c:1.14
*** hercules/bldcfg.c:1.1.1.3	Sat Feb 13 16:08:01 2010
--- hercules/bldcfg.c	Tue Dec 14 23:48:23 2010
***************
*** 204,209 ****
--- 204,218 ----
          delayed_exit(1);
      }
  
+ #if defined(FEATURE_S380) && VSE_UNPATCHED
+     /* force DOS/VS down to 15 MB to avoid a loop */
+     if (sysblk.vse_special && mainsize > 15)
+     {
+         sysblk.vse_real = sysblk.mainsize;
+         sysblk.mainsize = 15 * 1024 * 1024ULL;
+     }
+ #endif
+ 
      /* Initial power-on reset for main storage */
      storage_clear();
  
Index: hercules/codepage.c
diff -c hercules/codepage.c:1.1.1.3 hercules/codepage.c:1.8
*** hercules/codepage.c:1.1.1.3	Sat Feb 13 16:08:10 2010
--- hercules/codepage.c	Sat Feb 13 17:11:28 2010
***************
*** 24,43 ****
  
  static unsigned char
  ascii_to_ebcdic[] = {
!     "\x00\x01\x02\x03\x37\x2D\x2E\x2F\x16\x05\x25\x0B\x0C\x0D\x0E\x0F"
      "\x10\x11\x12\x13\x3C\x3D\x32\x26\x18\x19\x1A\x27\x22\x1D\x35\x1F"
      "\x40\x5A\x7F\x7B\x5B\x6C\x50\x7D\x4D\x5D\x5C\x4E\x6B\x60\x4B\x61"
      "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\x7A\x5E\x4C\x7E\x6E\x6F"
      "\x7C\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xD1\xD2\xD3\xD4\xD5\xD6"
      "\xD7\xD8\xD9\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xAD\xE0\xBD\x5F\x6D"
      "\x79\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96"
!     "\x97\x98\x99\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xC0\x6A\xD0\xA1\x07"
      "\x68\xDC\x51\x42\x43\x44\x47\x48\x52\x53\x54\x57\x56\x58\x63\x67"
      "\x71\x9C\x9E\xCB\xCC\xCD\xDB\xDD\xDF\xEC\xFC\xB0\xB1\xB2\xB3\xB4"
      "\x45\x55\xCE\xDE\x49\x69\x04\x06\xAB\x08\xBA\xB8\xB7\xAA\x8A\x8B"
      "\x09\x0A\x14\xBB\x15\xB5\xB6\x17\x1B\xB9\x1C\x1E\xBC\x20\xBE\xBF"
      "\x21\x23\x24\x28\x29\x2A\x2B\x2C\x30\x31\xCA\x33\x34\x36\x38\xCF"
!     "\x39\x3A\x3B\x3E\x41\x46\x4A\x4F\x59\x62\xDA\x64\x65\x66\x70\x72"
      "\x73\xE1\x74\x75\x76\x77\x78\x80\x8C\x8D\x8E\xEB\x8F\xED\xEE\xEF"
      "\x90\x9A\x9B\x9D\x9F\xA0\xAC\xAE\xAF\xFD\xFE\xFB\x3F\xEA\xFA\xFF"
  };
--- 24,43 ----
  
  static unsigned char
  ascii_to_ebcdic[] = {
!     "\x00\x01\x02\x03\x37\x2D\x2E\x2F\x16\x05\x15\x0B\x0C\x0D\x0E\x0F"
      "\x10\x11\x12\x13\x3C\x3D\x32\x26\x18\x19\x1A\x27\x22\x1D\x35\x1F"
      "\x40\x5A\x7F\x7B\x5B\x6C\x50\x7D\x4D\x5D\x5C\x4E\x6B\x60\x4B\x61"
      "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\x7A\x5E\x4C\x7E\x6E\x6F"
      "\x7C\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xD1\xD2\xD3\xD4\xD5\xD6"
      "\xD7\xD8\xD9\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xAD\xE0\xBD\x5F\x6D"
      "\x79\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96"
!     "\x97\x98\x99\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xC0\x4F\xD0\xA1\x07"
      "\x68\xDC\x51\x42\x43\x44\x47\x48\x52\x53\x54\x57\x56\x58\x63\x67"
      "\x71\x9C\x9E\xCB\xCC\xCD\xDB\xDD\xDF\xEC\xFC\xB0\xB1\xB2\xB3\xB4"
      "\x45\x55\xCE\xDE\x49\x69\x04\x06\xAB\x08\xBA\xB8\xB7\xAA\x8A\x8B"
      "\x09\x0A\x14\xBB\x15\xB5\xB6\x17\x1B\xB9\x1C\x1E\xBC\x20\xBE\xBF"
      "\x21\x23\x24\x28\x29\x2A\x2B\x2C\x30\x31\xCA\x33\x34\x36\x38\xCF"
!     "\x39\x3A\x3B\x3E\x41\x46\x4A\x6A\x59\x62\xDA\x64\x65\x66\x70\x72"
      "\x73\xE1\x74\x75\x76\x77\x78\x80\x8C\x8D\x8E\xEB\x8F\xED\xEE\xEF"
      "\x90\x9A\x9B\x9D\x9F\xA0\xAC\xAE\xAF\xFD\xFE\xFB\x3F\xEA\xFA\xFF"
  };
***************
*** 49,57 ****
      "\x10\x11\x12\x13\xB2\x0A\x08\xB7\x18\x19\x1A\xB8\xBA\x1D\xBB\x1F"
      "\xBD\xC0\x1C\xC1\xC2\x0A\x17\x1B\xC3\xC4\xC5\xC6\xC7\x05\x06\x07"
      "\xC8\xC9\x16\xCB\xCC\x1E\xCD\x04\xCE\xD0\xD1\xD2\x14\x15\xD3\xFC"
!     "\x20\xD4\x83\x84\x85\xA0\xD5\x86\x87\xA4\xD6\x2E\x3C\x28\x2B\xD7"
      "\x26\x82\x88\x89\x8A\xA1\x8C\x8B\x8D\xD8\x21\x24\x2A\x29\x3B\x5E"
!     "\x2D\x2F\xD9\x8E\xDB\xDC\xDD\x8F\x80\xA5\x7C\x2C\x25\x5F\x3E\x3F"
      "\xDE\x90\xDF\xE0\xE2\xE3\xE4\xE5\xE6\x60\x3A\x23\x40\x27\x3D\x22"
      "\xE7\x61\x62\x63\x64\x65\x66\x67\x68\x69\xAE\xAF\xE8\xE9\xEA\xEC"
      "\xF0\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\xF1\xF2\x91\xF3\x92\xF4"
--- 49,57 ----
      "\x10\x11\x12\x13\xB2\x0A\x08\xB7\x18\x19\x1A\xB8\xBA\x1D\xBB\x1F"
      "\xBD\xC0\x1C\xC1\xC2\x0A\x17\x1B\xC3\xC4\xC5\xC6\xC7\x05\x06\x07"
      "\xC8\xC9\x16\xCB\xCC\x1E\xCD\x04\xCE\xD0\xD1\xD2\x14\x15\xD3\xFC"
!     "\x20\xD4\x83\x84\x85\xA0\xD5\x86\x87\xA4\xD6\x2E\x3C\x28\x2B\x7C"
      "\x26\x82\x88\x89\x8A\xA1\x8C\x8B\x8D\xD8\x21\x24\x2A\x29\x3B\x5E"
!     "\x2D\x2F\xD9\x8E\xDB\xDC\xDD\x8F\x80\xA5\xD7\x2C\x25\x5F\x3E\x3F"
      "\xDE\x90\xDF\xE0\xE2\xE3\xE4\xE5\xE6\x60\x3A\x23\x40\x27\x3D\x22"
      "\xE7\x61\x62\x63\x64\x65\x66\x67\x68\x69\xAE\xAF\xE8\xE9\xEA\xEC"
      "\xF0\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\xF1\xF2\x91\xF3\x92\xF4"
***************
*** 584,590 ****
  static unsigned char
  cp_819_to_1047[] = {
   /*          x0  x1  x2  x3  x4  x5  x6  x7  x8  x9  xA  xB  xC  xD  xE  xF */
!  /* 0x */ "\x00\x01\x02\x03\x37\x2D\x2E\x2F\x16\x05\x25\x0B\x0C\x0D\x0E\x0F"
   /* 1x */ "\x10\x11\x12\x13\x3C\x3D\x32\x26\x18\x19\x3F\x27\x1C\x1D\x1E\x1F"
   /* 2x */ "\x40\x5A\x7F\x7B\x5B\x6C\x50\x7D\x4D\x5D\x5C\x4E\x6B\x60\x4B\x61"
   /* 3x */ "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\x7A\x5E\x4C\x7E\x6E\x6F"
--- 584,590 ----
  static unsigned char
  cp_819_to_1047[] = {
   /*          x0  x1  x2  x3  x4  x5  x6  x7  x8  x9  xA  xB  xC  xD  xE  xF */
!  /* 0x */ "\x00\x01\x02\x03\x37\x2D\x2E\x2F\x16\x05\x15\x0B\x0C\x0D\x0E\x0F"
   /* 1x */ "\x10\x11\x12\x13\x3C\x3D\x32\x26\x18\x19\x3F\x27\x1C\x1D\x1E\x1F"
   /* 2x */ "\x40\x5A\x7F\x7B\x5B\x6C\x50\x7D\x4D\x5D\x5C\x4E\x6B\x60\x4B\x61"
   /* 3x */ "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\x7A\x5E\x4C\x7E\x6E\x6F"
***************
*** 592,598 ****
   /* 5x */ "\xD7\xD8\xD9\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xAD\xE0\xBD\x5F\x6D"
   /* 6x */ "\x79\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96"
   /* 7x */ "\x97\x98\x99\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xC0\x4F\xD0\xA1\x07"
!  /* 8x */ "\x20\x21\x22\x23\x24\x15\x06\x17\x28\x29\x2A\x2B\x2C\x09\x0A\x1B"
   /* 9x */ "\x30\x31\x1A\x33\x34\x35\x36\x08\x38\x39\x3A\x3B\x04\x14\x3E\xFF"
   /* Ax */ "\x41\xAA\x4A\xB1\x9F\xB2\x6A\xB5\xBB\xB4\x9A\x8A\xB0\xCA\xAF\xBC"
   /* Bx */ "\x90\x8F\xEA\xFA\xBE\xA0\xB6\xB3\x9D\xDA\x9B\x8B\xB7\xB8\xB9\xAB"
--- 592,598 ----
   /* 5x */ "\xD7\xD8\xD9\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xAD\xE0\xBD\x5F\x6D"
   /* 6x */ "\x79\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96"
   /* 7x */ "\x97\x98\x99\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xC0\x4F\xD0\xA1\x07"
!  /* 8x */ "\x20\x21\x22\x23\x24\x25\x06\x17\x28\x29\x2A\x2B\x2C\x09\x0A\x1B"
   /* 9x */ "\x30\x31\x1A\x33\x34\x35\x36\x08\x38\x39\x3A\x3B\x04\x14\x3E\xFF"
   /* Ax */ "\x41\xAA\x4A\xB1\x9F\xB2\x6A\xB5\xBB\xB4\x9A\x8A\xB0\xCA\xAF\xBC"
   /* Bx */ "\x90\x8F\xEA\xFA\xBE\xA0\xB6\xB3\x9D\xDA\x9B\x8B\xB7\xB8\xB9\xAB"
***************
*** 608,615 ****
  cp_1047_to_819[] = {
   /*          x0  x1  x2  x3  x4  x5  x6  x7  x8  x9  xA  xB  xC  xD  xE  xF */
   /* 0x */ "\x00\x01\x02\x03\x9C\x09\x86\x7F\x97\x8D\x8E\x0B\x0C\x0D\x0E\x0F"
!  /* 1x */ "\x10\x11\x12\x13\x9D\x85\x08\x87\x18\x19\x92\x8F\x1C\x1D\x1E\x1F"
!  /* 2x */ "\x80\x81\x82\x83\x84\x0A\x17\x1B\x88\x89\x8A\x8B\x8C\x05\x06\x07"
   /* 3x */ "\x90\x91\x16\x93\x94\x95\x96\x04\x98\x99\x9A\x9B\x14\x15\x9E\x1A"
   /* 4x */ "\x20\xA0\xE2\xE4\xE0\xE1\xE3\xE5\xE7\xF1\xA2\x2E\x3C\x28\x2B\x7C"
   /* 5x */ "\x26\xE9\xEA\xEB\xE8\xED\xEE\xEF\xEC\xDF\x21\x24\x2A\x29\x3B\x5E"
--- 608,615 ----
  cp_1047_to_819[] = {
   /*          x0  x1  x2  x3  x4  x5  x6  x7  x8  x9  xA  xB  xC  xD  xE  xF */
   /* 0x */ "\x00\x01\x02\x03\x9C\x09\x86\x7F\x97\x8D\x8E\x0B\x0C\x0D\x0E\x0F"
!  /* 1x */ "\x10\x11\x12\x13\x9D\x0A\x08\x87\x18\x19\x92\x8F\x1C\x1D\x1E\x1F"
!  /* 2x */ "\x80\x81\x82\x83\x84\x85\x17\x1B\x88\x89\x8A\x8B\x8C\x05\x06\x07"
   /* 3x */ "\x90\x91\x16\x93\x94\x95\x96\x04\x98\x99\x9A\x9B\x14\x15\x9E\x1A"
   /* 4x */ "\x20\xA0\xE2\xE4\xE0\xE1\xE3\xE5\xE7\xF1\xA2\x2E\x3C\x28\x2B\x7C"
   /* 5x */ "\x26\xE9\xEA\xEB\xE8\xED\xEE\xEF\xEC\xDF\x21\x24\x2A\x29\x3B\x5E"
Index: hercules/configure
diff -c hercules/configure:1.1.1.3 hercules/configure:1.30
*** hercules/configure:1.1.1.3	Thu Mar 11 00:23:21 2010
--- hercules/configure	Mon Dec 12 18:19:29 2011
***************
*** 2314,2320 ****
  
  # Define the identity of the package.
   PACKAGE=hercules
!  VERSION=3.07
  
  
  cat >>confdefs.h <<_ACEOF
--- 2314,2320 ----
  
  # Define the identity of the package.
   PACKAGE=hercules
!  VERSION=3.07:380-4.0
  
  
  cat >>confdefs.h <<_ACEOF
Index: hercules/console.c
diff -c hercules/console.c:1.1.1.3 hercules/console.c:1.8
*** hercules/console.c:1.1.1.3	Sat Feb 13 16:08:12 2010
--- hercules/console.c	Sat Feb 13 17:11:30 2010
***************
*** 1271,1277 ****
--- 1271,1281 ----
  
  /*
  static char *herclogo[]={
+ #ifdef FEATURE_S380
+     " HHH          HHH   The S/370, S/380, ESA/390 and z/Architecture",
+ #else
      " HHH          HHH   The S/370, ESA/390 and z/Architecture",
+ #endif
      " HHH          HHH                 Emulator",
      " HHH          HHH",
      " HHH          HHH  EEEE RRR   CCC U  U L    EEEE  SSS",
***************
*** 1332,1338 ****
--- 1336,1346 ----
  "@ALIGN LEFT",
  "",
  "",
+ #ifdef FEATURE_S380
+ "           HHH          HHH   The S/370, S/380, ESA/390 and z/Architecture",
+ #else
  "           HHH          HHH   The S/370, ESA/390 and z/Architecture",
+ #endif
  "           HHH          HHH                 Emulator",
  "           HHH          HHH",
  "           HHH          HHH  EEEE RRR   CCC U  U L    EEEE  SSS",
***************
*** 1842,1848 ****
          }
  
          /* Close the connection and terminate the thread */
!         SLEEP (5);
          close_socket (csock);
          if (clientip) free(clientip);
          return NULL;
--- 1850,1856 ----
          }
  
          /* Close the connection and terminate the thread */
!         SLEEP (8);
          close_socket (csock);
          if (clientip) free(clientip);
          return NULL;
Index: hercules/cpu.c
diff -c hercules/cpu.c:1.1.1.3 hercules/cpu.c:1.18
*** hercules/cpu.c:1.1.1.3	Sat Feb 13 16:08:13 2010
--- hercules/cpu.c	Sat Feb 13 17:11:30 2010
***************
*** 317,322 ****
--- 317,335 ----
  
          SET_IC_ECMODE_MASK(regs);
  
+ #if defined(FEATURE_S380)
+         /* In case we are running CMS under CP, this LPSW may
+            be wiping out the 31-bit flag. So record the address
+            ready to be restored. */
+         if ( sysblk.s380 
+              && regs->psw.amode 
+              && (regs->psw.s380_bc == 0
+                  || regs->cr[1].F.L.F == 0)) {
+             regs->psw.s380_bc = regs->psw.IA_L;
+             regs->psw.s380_cr1 = regs->cr[1].F.L.F;
+         }
+ #endif
+ 
          /* Processing for EC mode PSW */
          regs->psw.intcode  = 0;
          regs->psw.asc      = (addr[2] & 0xC0);
***************
*** 335,340 ****
--- 348,367 ----
          regs->psw.zerobyte = addr[3];
          regs->psw.amode64  = 0;
          regs->psw.IA       = fetch_fw(addr + 4) & 0x7FFFFFFF;
+ #if defined(FEATURE_S380)
+         /* Because when running CMS under CP there are LPSWs
+            being done in virtual BCMODE that don't know about
+            AMODE 31, we need to restore the app's AMODE
+            status by looking at the address */
+         if (sysblk.s380 
+             && (regs->psw.s380_bc != 0) 
+             && (regs->psw.IA_L == regs->psw.s380_bc)
+             && (regs->cr[1].F.L.F == regs->psw.s380_cr1)) {
+             regs->psw.s380_bc = 0;
+             regs->psw.s380_cr1 = 0;
+             regs->psw.amode = 1;
+         }
+ #endif
          regs->psw.AMASK    = regs->psw.amode ? AMASK31 : AMASK24;
  #endif /*!defined(FEATURE_ESAME)*/
  
***************
*** 1769,1775 ****
          sysblk.regs[cpu] = &regs;
          release_lock(&sysblk.cpulock[cpu]);
          logmsg (_("HHCCP007I CPU%4.4X architecture mode set to %s\n"),
!                 cpu, get_arch_mode_string(&regs));
      }
      else
      {
--- 1796,1806 ----
          sysblk.regs[cpu] = &regs;
          release_lock(&sysblk.cpulock[cpu]);
          logmsg (_("HHCCP007I CPU%4.4X architecture mode set to %s\n"),
!                 cpu, 
! #ifdef FEATURE_S380
!         sysblk.s380 ? "S/380" :
! #endif
!         get_arch_mode_string(&regs));
      }
      else
      {
***************
*** 1779,1785 ****
              return NULL;
  
          logmsg (_("HHCCP003I CPU%4.4X architecture mode %s\n"),
!                 cpu, get_arch_mode_string(&regs));
  
  #ifdef FEATURE_VECTOR_FACILITY
          if (regs->vf->online)
--- 1810,1820 ----
              return NULL;
  
          logmsg (_("HHCCP003I CPU%4.4X architecture mode %s\n"),
!                 cpu,
! #ifdef FEATURE_S380
!        sysblk.s380 ? "S/380" :
! #endif
!        get_arch_mode_string(&regs));
  
  #ifdef FEATURE_VECTOR_FACILITY
          if (regs->vf->online)
Index: hercules/dasdload.c
diff -c hercules/dasdload.c:1.1.1.3 hercules/dasdload.c:1.17
*** hercules/dasdload.c:1.1.1.3	Sat Feb 13 16:08:18 2010
--- hercules/dasdload.c	Mon Dec 12 16:58:25 2011
***************
*** 124,132 ****
  BYTE iplccw1[8] =   {0x06, 0x00, 0x3A, 0x98, 0x60, 0x00, 0x00, 0x60};
  BYTE iplccw2[8] =   {0x08, 0x00, 0x3A, 0x98, 0x00, 0x00, 0x00, 0x00};
  BYTE ipl2data[] =   {0x07, 0x00, 0x3A, 0xB8, 0x40, 0x00, 0x00, 0x06,
                       0x31, 0x00, 0x3A, 0xBE, 0x40, 0x00, 0x00, 0x05,
                       0x08, 0x00, 0x3A, 0xA0, 0x00, 0x00, 0x00, 0x00,
!                      0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x19, 0x60,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*BBCCHH*/
                       0x00, 0x00, 0x00, 0x00, 0x04}; /*CCHHR*/
  BYTE noiplpsw[8] =  {0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F};
--- 124,139 ----
  BYTE iplccw1[8] =   {0x06, 0x00, 0x3A, 0x98, 0x60, 0x00, 0x00, 0x60};
  BYTE iplccw2[8] =   {0x08, 0x00, 0x3A, 0x98, 0x00, 0x00, 0x00, 0x00};
  BYTE ipl2data[] =   {0x07, 0x00, 0x3A, 0xB8, 0x40, 0x00, 0x00, 0x06,
+                      /* 07 ... = go to the track number found at
+                         address 003AB8 */
                       0x31, 0x00, 0x3A, 0xBE, 0x40, 0x00, 0x00, 0x05,
+                      /* 31 ... = search for the key found at
+                         memory address 003BE */
                       0x08, 0x00, 0x3A, 0xA0, 0x00, 0x00, 0x00, 0x00,
!                      /* 08 ... = go back (TIC) to the search until
!                         it is successful */
!                      0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x7f, 0xff,
!                      /* 06 ... = read the data block */
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*BBCCHH*/
                       0x00, 0x00, 0x00, 0x00, 0x04}; /*CCHHR*/
  BYTE noiplpsw[8] =  {0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F};
***************
*** 716,731 ****
  int             datalen;                /* Data length               */
  int             maxtrks = 1;            /* Maximum track count       */
  DATABLK        *datablk;                /* -> data block             */
! BYTE            buf[4096];              /* Buffer for data block     */
  
      /* For 2311 the IPL text will not fit on track 0 record 4,
         so adjust the IPL2 so that it loads from track 1 record 1 */
!     if (devtype == 0x2311)
      {
          memcpy (ipl2data + 32, "\x00\x00\x00\x00\x00\x01", 6);
          memcpy (ipl2data + 38, "\x00\x00\x00\x01\x01", 5);
          maxtrks = 2;
      }
  
      /* Read track 0 */
      rc = read_track (cif, 0, 0);
--- 723,754 ----
  int             datalen;                /* Data length               */
  int             maxtrks = 1;            /* Maximum track count       */
  DATABLK        *datablk;                /* -> data block             */
! static BYTE     buf[32767];           /* Buffer for data block     */
! int             separate = 0;           /* Is load separate file?    */
  
+     if ((iplfnm != NULL) && (strcmp(iplfnm, "separate") == 0))
+     {
+         separate = 1;
+     }
+     
      /* For 2311 the IPL text will not fit on track 0 record 4,
         so adjust the IPL2 so that it loads from track 1 record 1 */
!     /* Ditto for sepearate loaders */
!     if ((devtype == 0x2311) || separate)
      {
          memcpy (ipl2data + 32, "\x00\x00\x00\x00\x00\x01", 6);
          memcpy (ipl2data + 38, "\x00\x00\x00\x01\x01", 5);
          maxtrks = 2;
      }
+     
+     if (separate)
+     {
+         /* large binary files need more room. This will put the
+            CCWs above the 1 MB mark, which is hopefully
+            enough for now. */
+         iplccw1[1] = iplccw2[1] = ipl2data[1] = ipl2data[9] 
+             = ipl2data[17] = 0x10;
+     }
  
      /* Read track 0 */
      rc = read_track (cif, 0, 0);
***************
*** 800,806 ****
      if (rc < 0) return -1;
  
      /* Build the IPL text from the object file */
!     if (iplfnm != NULL)
      {
          memset (buf, 0, sizeof(buf));
          datalen = read_ipl_text (iplfnm, buf+12, sizeof(buf)-12);
--- 823,829 ----
      if (rc < 0) return -1;
  
      /* Build the IPL text from the object file */
!     if (iplfnm != NULL && !separate)
      {
          memset (buf, 0, sizeof(buf));
          datalen = read_ipl_text (iplfnm, buf+12, sizeof(buf)-12);
***************
*** 1023,1029 ****
      f1dscb->ds1volsq[0] = 0;
      f1dscb->ds1volsq[1] = 1;
      f1dscb->ds1credt[0] = tmptr->tm_year;
!     f1dscb->ds1credt[1] = (tmptr->tm_yday >> 8) & 0xFF;
      f1dscb->ds1credt[2] = tmptr->tm_yday & 0xFF;
      f1dscb->ds1expdt[0] = 0;
      f1dscb->ds1expdt[1] = 0;
--- 1046,1052 ----
      f1dscb->ds1volsq[0] = 0;
      f1dscb->ds1volsq[1] = 1;
      f1dscb->ds1credt[0] = tmptr->tm_year;
!     f1dscb->ds1credt[1] = (++tmptr->tm_yday >> 8) & 0xFF;
      f1dscb->ds1credt[2] = tmptr->tm_yday & 0xFF;
      f1dscb->ds1expdt[0] = 0;
      f1dscb->ds1expdt[1] = 0;
***************
*** 3489,3499 ****
          XMERRF ("HHCDL121E SEQ dsorg must be PS or DA: dsorg=0x%2.2x\n",dsorg);
          return -1;
      }
!     if (recfm != RECFM_FORMAT_F && recfm != (RECFM_FORMAT_F|RECFM_BLOCKED))
      {
!         XMERRF ("HHCDL122E SEQ recfm must be F or FB: recfm=0x%2.2x\n",recfm);
          return -1;
      }
      if (blksz == 0) blksz = lrecl;
      if (lrecl == 0) lrecl = blksz;
      if (lrecl == 0 || blksz % lrecl != 0
--- 3512,3526 ----
          XMERRF ("HHCDL121E SEQ dsorg must be PS or DA: dsorg=0x%2.2x\n",dsorg);
          return -1;
      }
!     if (recfm != RECFM_FORMAT_F 
!         && recfm != (RECFM_FORMAT_F|RECFM_BLOCKED)
!         && recfm != RECFM_FORMAT_U)
      {
!         XMERRF ("HHCDL122E SEQ recfm must be F or FB or U: "
!                 "recfm=0x%2.2x\n",recfm);
          return -1;
      }
+     if ((lrecl == 0) && (recfm == RECFM_FORMAT_U)) lrecl = 1;
      if (blksz == 0) blksz = lrecl;
      if (lrecl == 0) lrecl = blksz;
      if (lrecl == 0 || blksz % lrecl != 0
***************
*** 4406,4411 ****
--- 4433,4440 ----
      /* Process optional arguments */
      for ( ; argc > 1 && argv[1][0] == '-'; argv++, argc--)
      {
+         /* a single - can be used for the control file */
+         if (argv[1][1] == '\0') break;
          if (strcmp("0", &argv[1][1]) == 0)
              comp = CCKD_COMPRESS_NONE;
  #ifdef CCKD_COMPRESS_ZLIB
***************
*** 4446,4453 ****
      }
  
      /* Open the control file */
!     hostpath(pathname, cfname, sizeof(pathname));
!     cfp = fopen (pathname, "r");
      if (cfp == NULL)
      {
          XMERRF ("HHCDL001E Cannot open %s: %s\n",
--- 4475,4489 ----
      }
  
      /* Open the control file */
!     if (strcmp(cfname, "-") == 0)
!     {
!         cfp = stdin;
!     }
!     else
!     {
!         hostpath(pathname, cfname, sizeof(pathname));
!         cfp = fopen (pathname, "r");
!     }
      if (cfp == NULL)
      {
          XMERRF ("HHCDL001E Cannot open %s: %s\n",
***************
*** 4564,4570 ****
                          outcyl, outhead);
  
      /* Close files and release buffers */
!     fclose (cfp);
      close_ckd_image (cif);
  
      return rc;
--- 4600,4609 ----
                          outcyl, outhead);
  
      /* Close files and release buffers */
!     if (strcmp(cfname, "-") != 0)
!     {
!         fclose (cfp);
!     }
      close_ckd_image (cif);
  
      return rc;
Index: hercules/dat.h
diff -c hercules/dat.h:1.1.1.3 hercules/dat.h:1.16
*** hercules/dat.h:1.1.1.3	Sat Feb 13 16:08:20 2010
--- hercules/dat.h	Sat Sep  4 14:35:46 2010
***************
*** 878,884 ****
--- 878,890 ----
  /*-----------------------------------*/
  U32     stl;                            /* Segment table length      */
  RADR    ste;                            /* Segment table entry       */
+ #ifdef FEATURE_S380
+ int     seg1m;
+ int     use_xa = 0;
+ RADR    pte;                            /* Page table entry          */
+ #else
  U16     pte;                            /* Page table entry          */
+ #endif
  U32     ptl;                            /* Page table length         */
  
      regs->dat.private = regs->dat.protect = 0;
***************
*** 894,899 ****
--- 900,1006 ----
         ((regs->CR(0) & CR0_SEG_SIZE) != CR0_SEG_SZ_1M)))
         goto tran_spec_excp;
  
+ #ifdef FEATURE_S380
+     /* if CR0.10 signifies XA, then we set XA, and ignore CR13 */
+     if (((regs->CR(0) & CR0_XA) == CR0_XA) && sysblk.s380)
+     {
+         use_xa = 1;
+         seg1m = (regs->CR(0) & CR0_SEG_SIZE) == CR0_SEG_SZ_1M;
+     }
+     
+     /* if the AMODE is 31-bit and CR13 is non-zero and the virtual
+        address is 16 MB or above, then we are operating in split
+        DAT mode, so switch the asd to CR13 and use XA - above the
+        line access is always XA in S/380 */
+     else if ((regs)->psw.amode && sysblk.s380 && ((regs)->CR(13) != 0)
+        && (((vaddr) & 0x7f000000) != 0))
+     {
+         use_xa = 1;
+         regs->dat.asd = regs->CR(13);
+         seg1m = 1;
+     }
+     
+     /* anything done via an XA DAT should not affect the TLB
+        because we don't have that sophistication yet. */
+     if (use_xa)
+     {
+         /* Calculate the real address of the segment table entry */
+         sto = regs->dat.asd & STD_STO;
+         stl = regs->dat.asd & STD_STL;
+         sto += seg1m ?
+             ((vaddr & 0x7FF00000) >> 18) :
+             ((vaddr & 0x7FFF0000) >> 14);
+ 
+         /* Check that virtual address is within the segment table */
+         if ((!seg1m && (vaddr >> 20) > stl) 
+             || (seg1m && (vaddr >> 24) > stl))
+             goto seg_tran_length;
+ 
+         /* Generate addressing exception if outside real storage */
+         if (sto > regs->mainlim)
+             goto address_excp;
+ 
+         /* Fetch segment table entry from real storage.  All bytes
+            must be fetched concurrently as observed by other CPUs */
+         sto = APPLY_PREFIXING (sto, regs->PX);
+         ste = ARCH_DEP(fetch_fullword_absolute) (sto, regs);
+ 
+         /* Generate segment translation exception if segment invalid */
+         if (ste & SEGTAB_INVALID)
+             goto seg_tran_invalid;
+ 
+         /* Check that all the reserved bits in the STE are zero */
+         if (ste & SEGTAB_RESV)
+             goto tran_spec_excp;
+ 
+         /* If the segment table origin register indicates a private
+            address space then STE must not indicate a common segment */
+         if (regs->dat.private && (ste & (SEGTAB_COMMON)))
+             goto tran_spec_excp;
+ 
+         /* Isolate page table origin and length */
+         pto = ste & SEGTAB_PTO;
+         ptl = ste & SEGTAB_PTL;
+ 
+         /* [3.11.3.4] Page table lookup */
+ 
+         /* Calculate the real address of the page table entry */
+         pto += seg1m ?
+             ((vaddr & 0x000FF000) >> 10) :
+             ((vaddr & 0x0000F000) >> 10);
+ 
+         /* Check that the virtual address is within the page table */
+         if (seg1m &&
+            (((vaddr & 0x000F0000) >> 16) > ptl))
+             /* no need to check 64K segments, as every one of
+                the 16 values fits within the 16 minimum */
+             goto page_tran_length;
+ 
+         /* Generate addressing exception if outside real storage */
+         if (pto > regs->mainlim)
+             goto address_excp;
+ 
+         /* Fetch the page table entry from real storage.  All bytes
+            must be fetched concurrently as observed by other CPUs */
+         pto = APPLY_PREFIXING (pto, regs->PX);
+         pte = ARCH_DEP(fetch_fullword_absolute) (pto, regs);
+ 
+         /* Generate page translation exception if page invalid */
+         if (pte & PAGETAB_INVALID)
+             goto page_tran_invalid;
+ 
+         /* Check that all the reserved bits in the PTE are zero */
+         if (pte & PAGETAB_RESV)
+             goto tran_spec_excp;
+ 
+         /* Set the protection indicator if page protection is active */
+         if (pte & PAGETAB_PROT)
+             regs->dat.protect |= 1;
+ 
+     } /* end else if XA DAT */
+     else
+ #endif
+ 
      /* Look up the address in the TLB */
      if (   !(acctype & ACC_NOTLB)
          && ((vaddr & TLBID_PAGEMASK) | regs->tlbID) == regs->tlb.TLB_VADDR(tlbix)
***************
*** 1015,1020 ****
--- 1122,1138 ----
          }
      } /* end if(!TLB) */
  
+ #ifdef FEATURE_S380
+     if (use_xa)
+     {
+     /* [3.11.3.5] Combine the page frame real address with the byte
+        index of the virtual address to form the real address */
+         regs->dat.raddr = (pte & PAGETAB_PFRA) | (vaddr & 0xFFF);
+         regs->dat.rpfra = (pte & PAGETAB_PFRA);
+     }
+     else
+ #endif
+     {
      /* Combine the page frame real address with the byte
         index of the virtual address to form the real address */
      regs->dat.raddr = ((regs->CR(0) & CR0_PAGE_SIZE) == CR0_PAGE_SZ_4K) ?
***************
*** 1025,1030 ****
--- 1143,1151 ----
          (((U32)pte & PAGETAB_PFRA_2K) << 8) | (vaddr & 0x7FF);
  
      regs->dat.rpfra = regs->dat.raddr & PAGEFRAME_PAGEMASK;
+     }
+ 
+ 
  #endif /*!defined(FEATURE_S390_DAT) && !defined(FEATURE_ESAME)*/
  
  #if defined(FEATURE_S390_DAT)
***************
*** 2240,2251 ****
--- 2361,2380 ----
          /* Set the reference bit in the storage key */
          *regs->dat.storkey |= STORKEY_REF;
  
+ #ifdef FEATURE_S380
+         if (!(acctype & ACC_NOTLB))
+         {
+ #endif
          /* Update accelerated lookup TLB fields */
          regs->tlb.storkey[ix]    = regs->dat.storkey;
          regs->tlb.skey[ix]       = *regs->dat.storkey & STORKEY_KEY;
          regs->tlb.acc[ix]        = ACC_READ;
          regs->tlb.main[ix]       = NEW_MAINADDR (regs, addr, apfra);
  
+ #ifdef FEATURE_S380
+         }
+ #endif
+ 
      }
      else
      if (acctype & (ACC_WRITE|ACC_CHECK))
***************
*** 2263,2268 ****
--- 2392,2401 ----
          if (acctype & ACC_WRITE)
              *regs->dat.storkey |= (STORKEY_REF | STORKEY_CHANGE);
  
+ #ifdef FEATURE_S380
+         if (!(acctype & ACC_NOTLB))
+         {
+ #endif
          /* Update accelerated lookup TLB fields */
          regs->tlb.storkey[ix] = regs->dat.storkey;
          regs->tlb.skey[ix]    = *regs->dat.storkey & STORKEY_KEY;
***************
*** 2271,2276 ****
--- 2404,2413 ----
                                :  ACC_READ;
          regs->tlb.main[ix]    = NEW_MAINADDR (regs, addr, apfra);
  
+ #ifdef FEATURE_S380
+         }
+ #endif
+ 
  #if defined(FEATURE_PER)
          if (EN_IC_PER_SA(regs))
          {
Index: hercules/ecpsvm.c
diff -c hercules/ecpsvm.c:1.1.1.2 hercules/ecpsvm.c:1.3
*** hercules/ecpsvm.c:1.1.1.2	Sat Feb 13 16:08:23 2010
--- hercules/ecpsvm.c	Sat Feb 13 17:11:31 2010
***************
*** 871,876 ****
--- 871,877 ----
  
          /* Build REAL PSW */
          INITPSEUDOREGS(rregs);
+         rregs.psw.AMASK = AMASK24;
          /* Copy IAR */
          UPD_PSW_IA(&rregs, wregs.psw.IA);
          /* Copy CC, PSW KEYs and PGM Mask */
Index: hercules/esa390.h
diff -c hercules/esa390.h:1.1.1.4 hercules/esa390.h:1.10
*** hercules/esa390.h:1.1.1.4	Thu Mar 11 00:23:32 2010
--- hercules/esa390.h	Wed Aug 18 08:17:28 2010
***************
*** 87,92 ****
--- 87,96 ----
          DW       ia;                    /* Instruction addrress      */
                                          /*                 (33 - 63) */
                                          /* or (esame)      (64 -127) */
+         U32      s380_bc;               /* last address that was     */
+                                         /* known to be AMODE 31      */
+         U32      s380_cr1;              /* control register 1 when   */
+                                         /* last in AMODE 31          */
          DW       amask;                 /* Address wraparound mask   */
          U16      intcode;               /* Interruption code         */
          BYTE     ilc;                   /* Instruction length count  */
***************
*** 218,224 ****
--- 222,233 ----
  #define CR0_PAGE_SZ_2K  0x00400000      /* ...2K pages               */
  #define CR0_PAGE_SZ_4K  0x00800000      /* ...4K pages               */
  #define CR0_ZPAG_SZ_1M  0x00800000      /* ...1M pages           EDAT*/
+ #ifdef FEATURE_S380
+ #define CR0_SEG_SIZE    0x00180000      /* Segment size for S/370... */
+ #else
  #define CR0_SEG_SIZE    0x00380000      /* Segment size for S/370... */
+ #endif
+ #define CR0_XA          0x00200000      /* XA DAT indicator          */
  #define CR0_SEG_SZ_64K  0x00000000      /* ...64K segments           */
  #define CR0_SEG_SZ_1M   0x00100000      /* ...1M segments            */
  #define CR0_ASN_LX_REUS 0x00080000      /* ASN-and-LX-reuse control  */
Index: hercules/feat370.h
diff -c hercules/feat370.h:1.1.1.3 hercules/feat370.h:1.15
*** hercules/feat370.h:1.1.1.3	Sat Feb 13 16:08:25 2010
--- hercules/feat370.h	Sat Feb 13 17:11:32 2010
***************
*** 30,67 ****
  #define FEATURE_ECPSVM
  #define FEATURE_VM_BLOCKIO
  
  /* The following ESA/390 features can be retrofitted to S/370 and
     may be activated if desired by uncommenting the appropriate
     define statements below and performing a complete rebuild */
! //#define FEATURE_BASIC_FP_EXTENSIONS
! //#define FEATURE_BINARY_FLOATING_POINT
! //#define FEATURE_CHECKSUM_INSTRUCTION
! //#define FEATURE_COMPARE_AND_MOVE_EXTENDED
! //#define FEATURE_COMPRESSION
! //#define FEATURE_EXTENDED_TRANSLATION
! //#define FEATURE_EXTENDED_TRANSLATION_FACILITY_2
! //#define FEATURE_HFP_EXTENSIONS
! //#define FEATURE_HFP_MULTIPLY_ADD_SUBTRACT
! //#define FEATURE_HFP_UNNORMALIZED_EXTENSION
! //#define FEATURE_IMMEDIATE_AND_RELATIVE
! //#define FEATURE_SQUARE_ROOT
! //#define FEATURE_STRING_INSTRUCTION
  
  /* The following ESAME features can be retrofitted to S/370 and
     may be activated if desired by uncommenting the appropriate
     define statements below and performing a complete rebuild */
! //#define FEATURE_ESAME_N3_ESA390
! //#define FEATURE_ETF2_ENHANCEMENT
! //#define FEATURE_ETF3_ENHANCEMENT
! //#define FEATURE_EXECUTE_EXTENSIONS_FACILITY
! //#define FEATURE_EXTENDED_IMMEDIATE
! //#define FEATURE_EXTENDED_TRANSLATION_FACILITY_3
! //#define FEATURE_GENERAL_INSTRUCTIONS_EXTENSION_FACILITY
! //#define FEATURE_LONG_DISPLACEMENT
! //#define FEATURE_MESSAGE_SECURITY_ASSIST
! //#define FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1
! //#define FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_2
! //#define FEATURE_PARSING_ENHANCEMENT_FACILITY
  
  #endif /*defined(OPTION_370_MODE)*/
  /* end of FEAT370.H */
--- 30,71 ----
  #define FEATURE_ECPSVM
  #define FEATURE_VM_BLOCKIO
  
+ #ifdef FEATURE_S380
+ #define FEATURE_BIMODAL_ADDRESSING
+ #endif
+ 
  /* The following ESA/390 features can be retrofitted to S/370 and
     may be activated if desired by uncommenting the appropriate
     define statements below and performing a complete rebuild */
! #define FEATURE_BASIC_FP_EXTENSIONS
! #define FEATURE_BINARY_FLOATING_POINT
! #define FEATURE_CHECKSUM_INSTRUCTION
! #define FEATURE_COMPARE_AND_MOVE_EXTENDED
! #define FEATURE_COMPRESSION
! #define FEATURE_EXTENDED_TRANSLATION
! #define FEATURE_EXTENDED_TRANSLATION_FACILITY_2
! #define FEATURE_HFP_EXTENSIONS
! #define FEATURE_HFP_MULTIPLY_ADD_SUBTRACT
! #define FEATURE_HFP_UNNORMALIZED_EXTENSION
! #define FEATURE_IMMEDIATE_AND_RELATIVE
! #define FEATURE_SQUARE_ROOT
! #define FEATURE_STRING_INSTRUCTION
  
  /* The following ESAME features can be retrofitted to S/370 and
     may be activated if desired by uncommenting the appropriate
     define statements below and performing a complete rebuild */
! #define FEATURE_ESAME_N3_ESA390
! #define FEATURE_ETF2_ENHANCEMENT
! #define FEATURE_ETF3_ENHANCEMENT
! #define FEATURE_EXECUTE_EXTENSIONS_FACILITY
! #define FEATURE_EXTENDED_IMMEDIATE
! #define FEATURE_EXTENDED_TRANSLATION_FACILITY_3
! #define FEATURE_GENERAL_INSTRUCTIONS_EXTENSION_FACILITY
! #define FEATURE_LONG_DISPLACEMENT
! #define FEATURE_MESSAGE_SECURITY_ASSIST
! #define FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1
! #define FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_2
! #define FEATURE_PARSING_ENHANCEMENT_FACILITY
  
  #endif /*defined(OPTION_370_MODE)*/
  /* end of FEAT370.H */
Index: hercules/feature.h
diff -c hercules/feature.h:1.1.1.3 hercules/feature.h:1.38
*** hercules/feature.h:1.1.1.3	Sat Feb 13 16:08:27 2010
--- hercules/feature.h	Tue Dec 14 23:48:24 2010
***************
*** 125,132 ****
--- 125,137 ----
  
  #define AMASK   AMASK_L
  
+ #ifdef FEATURE_S380
+ #define ADDRESS_MAXWRAP(_register_context) \
+     ((_register_context)->psw.AMASK)
+ #else
  #define ADDRESS_MAXWRAP(_register_context) \
      (AMASK24)
+ #endif
  
  #define ADDRESS_MAXWRAP_E(_register_context) \
      (AMASK31)
***************
*** 205,210 ****
--- 210,219 ----
  #define TLBID_BYTEMASK  0x001FFFFF
  #define ASD_PRIVATE   SEGTAB_370_CMN
  
+ #define CR12_BRTRACE    S_CR12_BRTRACE
+ #define CR12_TRACEEA    S_CR12_TRACEEA
+ #define CHM_GPR2_RESV   S_CHM_GPR2_RESV
+ 
  #elif __GEN_ARCH == 390
  
  #define ARCH_MODE   ARCH_390
***************
*** 764,770 ****
   /*
    * Accelerated lookup
    */
! #define MADDR(_addr, _arn, _regs, _acctype, _akey) \
   ( \
         likely((_regs)->aea_ar[(_arn)]) \
     &&  likely( \
--- 773,779 ----
   /*
    * Accelerated lookup
    */
! #define MADDR_STD(_addr, _arn, _regs, _acctype, _akey) \
   ( \
         likely((_regs)->aea_ar[(_arn)]) \
     &&  likely( \
***************
*** 785,790 ****
--- 794,842 ----
       ) \
   )
  
+ 
+ #ifdef FEATURE_S380
+ 
+ #if VSE_UNPATCHED
+ #define VSE_SPECIAL(_addr) \
+     (sysblk.vse_special && (((_addr) & 0x7fffffff) < sysblk.vse_real))
+ #else
+ #define VSE_SPECIAL(_addr) 0
+ #endif
+ 
+ #define MADDR_S380(_addr, _arn, _regs, _acctype, _akey) \
+ (   ((_regs)->psw.amode && sysblk.s380 \
+       && (((_addr) & 0x7f000000) != 0)) \
+     ? \
+  ( ((_regs)->CR(13) == 0) ? \
+  ( \
+     ( \
+       (((_addr) & 0x7fffffff) < sysblk.mainsize || VSE_SPECIAL(_addr)) ? \
+            ((_regs)->dat.storkey = &STORAGE_KEY((_addr) & 0x7fffffff, \
+                                                 (_regs)), \
+             (_regs)->mainstor + ((_addr) & 0x7fffffff)) : \
+            ( \
+             (_regs)->program_interrupt ((_regs), \
+                                         PGM_PROTECTION_EXCEPTION), \
+             (BYTE *)0) \
+     ) \
+  ) : /* if CR13 is set, split DAT is being used, so don't use the TLB */ \
+      ARCH_DEP(logical_to_main) ((_addr), (_arn), (_regs), \
+               ((_acctype) | ACC_NOTLB), (_akey)) \
+  ) \
+     : \
+     MADDR_STD(_addr, _arn, _regs, _acctype, _akey) \
+ )
+ 
+ #endif
+ 
+ #if defined(FEATURE_S380) && !defined(FEATURE_S390_DAT) \
+     && !defined(FEATURE_ESAME)
+ #define MADDR MADDR_S380
+ #else
+ #define MADDR MADDR_STD
+ #endif
+ 
  /*
   * PER Successful Branch
   */
Index: hercules/general1.c
diff -c hercules/general1.c:1.1.1.3 hercules/general1.c:1.10
*** hercules/general1.c:1.1.1.3	Sat Feb 13 16:08:30 2010
--- hercules/general1.c	Sat Feb 13 17:11:32 2010
***************
*** 660,666 ****
--- 660,668 ----
  {
  int     r1, r2;                         /* Values of R fields        */
  VADR    newia;                          /* New instruction address   */
+ #if defined(FEATURE_TRACING)
  int     xmode;                          /* 64 or 31 mode of target   */
+ #endif
  #if defined(FEATURE_ESAME)
  BYTE    *ipsav;                         /* save for ip               */
  #endif /*defined(FEATURE_ESAME)*/
***************
*** 712,718 ****
          regs->GR_L(r1) = PSW_IA24(regs, 2);
  
      /* Set mode and branch to address specified by R2 operand */
!     if ( r2 != 0 )
      {
          SET_ADDRESSING_MODE(regs, newia);
          SUCCESSFUL_BRANCH(regs, newia, 2);
--- 714,727 ----
          regs->GR_L(r1) = PSW_IA24(regs, 2);
  
      /* Set mode and branch to address specified by R2 operand */
!     if ( r2 != 0
! #if defined(FEATURE_S380)
! /* if a S/370 machine, don't allow them to change addressing
!    modes, because that has implications for the memory access
!    routines */
!          && (sysblk.s380 || (regs->arch_mode != ARCH_370))
! #endif
!        )
      {
          SET_ADDRESSING_MODE(regs, newia);
          SUCCESSFUL_BRANCH(regs, newia, 2);
***************
*** 769,775 ****
      }
  
      /* Set mode and branch to address specified by R2 operand */
!     if ( r2 != 0 )
      {
          SET_ADDRESSING_MODE(regs, newia);
          SUCCESSFUL_BRANCH(regs, newia, 2);
--- 778,791 ----
      }
  
      /* Set mode and branch to address specified by R2 operand */
!     if ( r2 != 0
! #if defined(FEATURE_S380)
! /* if a S/370 machine, don't allow them to change addressing
!    modes, because that has implications for the memory access
!    routines */
!          && (sysblk.s380 || (regs->arch_mode != ARCH_370))
! #endif
!        )
      {
          SET_ADDRESSING_MODE(regs, newia);
          SUCCESSFUL_BRANCH(regs, newia, 2);
Index: hercules/general2.c
diff -c hercules/general2.c:1.1.1.3 hercules/general2.c:1.26
*** hercules/general2.c:1.1.1.3	Sat Feb 13 16:08:30 2010
--- hercules/general2.c	Sat Apr 24 12:21:41 2010
***************
*** 116,121 ****
--- 116,122 ----
  #include "opcode.h"
  #include "inline.h"
  #include "clock.h"
+ #include "sllib.h"
  
  
  /*-------------------------------------------------------------------*/
***************
*** 1389,1394 ****
--- 1390,1492 ----
  }
  
  
+ #if 0
+ #ifndef EZAHANDLER_DEFINED
+ #define EZAHANDLER_DEFINED
+ /* If we have received an EZASOKET dummy SVC, then R1 will
+    point to the EZASOKET parameters, and R4 will have an
+    address of a 1000-byte area of addressable memory. This
+    is typically used to store a hostent structure. It is
+    beyond Hercules's scope to know where this memory came
+    from. However, it will be checked to make sure it is
+    writable. Not sure what happens if the buffer crosses
+    a page boundary with one page swapped out, but it probably 
+    won't be pretty. */
+ 
+ static void ezahandler(REGS *regs)
+ {
+     char keywd[50];
+     UINT32 *parms;
+     BYTE   *p;
+     UINT32  new;
+     BYTE   *gstor; /* global storage */
+         
+     /* we have some "global" storage available in R4 */
+     /* I haven't figured out what that "0" means either */
+     gstor = (BYTE *)MADDR (regs->GR_L(4), 0, regs, ACCTYPE_READ, regs->psw.pkey);
+ 
+     /* get parameters from R1 */
+     parms = (UINT32 *)MADDR (regs->GR_L(1), 0, regs, ACCTYPE_READ, regs->psw.pkey);
+ 
+     /* now get parameter 1 to EZASOKET, which is the function required */
+     p = (BYTE *)&parms[0];
+     /* There's bound to be a macro that would do this, but I
+        didn't notice it in hmacros */
+     new = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+     p = MADDR(new, 0, regs, ACCTYPE_READ, regs->psw.pkey);
+ 
+     /* finally we're pointing to the EBCDIC string */
+     /* time to convert to ASCII. Although we could do the */
+     /* comparison in EBCDIC */
+ 
+     strncpy(keywd, p, sizeof keywd);
+     keywd[sizeof keywd - 1] = '\0';
+     sl_etoa(NULL, keywd, strlen(keywd));
+ 
+     /* so far we only support this one function */
+     if (strcmp(keywd, "GETHOSTBYNAME") == 0)
+     {
+         char www[1000];
+         struct hostent *h;
+             
+         /* now we need parameter 3, which is a URL to look up */
+         p = (BYTE *)&parms[2];
+         new = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+         p = MADDR(new, 0, regs, ACCTYPE_READ, regs->psw.pkey);
+ 
+         /* finally we are pointing to the address */
+         /* convert to ASCII then do the proper call */
+ 
+         strncpy(www, p, sizeof www);
+         keywd[sizeof www - 1] = '\0';
+         sl_etoa(NULL, www, strlen(www));
+         h = gethostbyname(www);
+ 
+         /* we use the global storage to store an MVS-style
+            hostent */
+ 
+         /* we are expecting an address to be filled in. If
+            you look at socket.h in tcpip380 (ie *not* in
+            Hercules), you will be able to match up offsets.
+            Copy the data straight in */            
+         memcpy(gstor + 200 + 200 + 2 + 2, h->h_addr, 4);
+            
+         /* now their 4th parameter is an address pointer. They
+            need this filled in to point to that structure which
+            we have just created. So, it's simply to a pointer
+            to the global storage "the system" provided in R4. */
+ 
+         p = (BYTE *)&parms[3];
+         new = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+         p = MADDR(new, 0, regs, ACCTYPE_WRITE, regs->psw.pkey);
+           
+         /* Need to ensure that the address is given in
+            big-endian form. There's probably a macro for this
+            somewhere too. */
+         new = regs->GR_L(4);
+         p[0] = new >> 24;
+         p[1] = (new >> 16) & 0xff;
+         p[2] = (new >> 8) & 0xff;
+         p[3] = new & 0xff;
+             
+         /* and that's a wrap */
+     }
+     return;
+ }
+ #endif
+ #endif
+ 
+ 
  /*-------------------------------------------------------------------*/
  /* 0A   SVC   - Supervisor Call                                 [RR] */
  /*-------------------------------------------------------------------*/
***************
*** 1400,1405 ****
--- 1498,1579 ----
  int     rc;                             /* Return code               */
  
      RR_SVC(inst, regs, i);
+     
+ #if 0
+     /* if we have an SVC and R2 is set to a magic number, then
+        this is actually a request from EZASOKET. */
+     if ((i == 233) && (regs->GR_L(2) == 0xcccccccc))
+     {
+         ezahandler(regs);
+         return;
+     }
+ #endif
+ 
+ #ifdef FEATURE_S380
+     /* If this is DOS/VS (ie VSE/380) then if we are in 31-bit
+        mode, we should handle the ATL memory request and free.
+        Due to the current technical limitation (only one request
+        can be made), we should only do the intercept if at least
+        16 MB was requested - after all, it was going to fail 
+        anyway otherwise. */
+     if (sysblk.vse_special && regs->psw.amode)
+     {
+         /* GETVIS */
+         if (i == 61)
+         {
+             /* if request is at least 16 MB */
+             if (regs->GR_L(0) >= 0x01000000)
+             {
+                 regs->GR_L(1) = 0x04100000;
+                 regs->GR_L(15) = 0;
+                 regs->psw.cc = 0;
+                 return;
+             }
+         }
+         /* FREEVIS */
+         else if (i == 62)
+         {
+             /* see if it is an ATL address */
+             if ((regs->GR_L(1) & 0x7f000000) != 0)
+             {
+                 regs->GR_L(15) = 0;
+                 regs->psw.cc = 0;
+                 return;
+             }
+         }   
+     }
+ 
+     /* If user has requested special MVS intercepts, then we need
+        to obtain ATL storage when they do GETMAIN, and free it
+        with FREEMAIN. For now we have a simple one-request-at-a-time
+        method for handling that. We simply return a pointer to the
+        65 MB location on the assumption that they have allocated
+        sufficient memory prior. */
+     if (sysblk.mvs_special && (i == 120) && regs->psw.amode)
+     {
+         if (regs->GR_L(1) == 0) /* getmain */
+         {
+             if (regs->GR_L(0) >= 0x01000000)
+             {
+                 regs->GR_L(1) = 0x04100000;
+                 regs->GR_L(15) = 0;
+                 regs->psw.cc = 0;
+                 return;
+             }
+         }
+         else /* freemain */
+         {
+             /* see if it is an ATL address */
+             if ((regs->GR_L(1) & 0x7f000000) != 0)
+             {
+                 regs->GR_L(15) = 0;
+                 regs->psw.cc = 0;
+                 return;
+             }
+         }   
+     }
+ #endif
+ 
  #if defined(FEATURE_ECPSVM)
      if(ecpsvm_dosvc(regs,i)==0)
      {
Index: hercules/hetget.c
diff -c hercules/hetget.c:1.1.1.3 hercules/hetget.c:1.16
*** hercules/hetget.c:1.1.1.3	Sat Feb 13 16:08:40 2010
--- hercules/hetget.c	Wed Jan 12 23:29:01 2011
***************
*** 32,41 ****
--- 32,46 ----
  /*
  || Local volatile data
  */
+ #define O_LIST      0x100
  #define O_NL        0x80
  #define O_ASCII     0x40
  #define O_STRIP     0x20
  #define O_UNBLOCK   0x10
+ #define O_NO_NEW    0x08
+ #define O_RDW       0x04
+ #define O_HRCBIN    0x02
+ #define O_HRCTXT    0x01
  struct
  {
      char *ifile;
***************
*** 43,49 ****
      int fileno;
      int lrecl;
      int blksize;
!     unsigned char flags;
      unsigned char recfm;
  }
  opts = 
--- 48,54 ----
      int fileno;
      int lrecl;
      int blksize;
!     unsigned int flags;
      unsigned char recfm;
  }
  opts = 
***************
*** 65,74 ****
      "Usage: %s [options] hetfile outfile fileno [recfm lrecl blksize]\n\n"
      "Options:\n"
      "  -a  convert to ASCII (implies -u)\n"
      "  -h  display usage summary\n"
      "  -n  file is an NL (or BLP like) tape\n"
      "  -u  unblock (removes BDWs and RDWs if RECFM=V)\n"
!     "  -s  strip trailing blanks (requires -a)\n";
  
  /*
  || Valid record formats
--- 70,85 ----
      "Usage: %s [options] hetfile outfile fileno [recfm lrecl blksize]\n\n"
      "Options:\n"
      "  -a  convert to ASCII (implies -u)\n"
+     "  -b  sensible defaults for binary files\n"
      "  -h  display usage summary\n"
+     "  -l  list datasets on SL tape (only needs hetfile)\n"
      "  -n  file is an NL (or BLP like) tape\n"
      "  -u  unblock (removes BDWs and RDWs if RECFM=V)\n"
!     "  -r  add an artificial RDW to anything\n"
!     "  -s  strip trailing blanks (requires -a)\n"
!     "  -t  sensible defaults for text files\n"
!     "  -z  don't add newlines when converting RECFM=U to ASCII\n"
!     "If just hetfile given, extraction will be done\n";
  
  /*
  || Valid record formats
***************
*** 141,147 ****
  || Merge DCB information from HDR2 label
  */
  void
! merge( SLLABEL *lab )
  {
      SLFMT fmt;
      int i;
--- 152,158 ----
  || Merge DCB information from HDR2 label
  */
  void
! merge( SLLABEL *lab, int disp_opt )
  {
      SLFMT fmt;
      int i;
***************
*** 207,217 ****
      /*
      || Print DCB attributes
      */
!     printf( "DCB Attributes used:\n" );
!     printf( "  RECFM=%-4.4s  LRECL=%-5.5d  BLKSIZE=%d\n",
!         valfm[ i ].recfm,
!         opts.lrecl,
!         opts.blksize );
  
      return;
  }
--- 218,236 ----
      /*
      || Print DCB attributes
      */
!     if (disp_opt == 0)
!     {
!         printf( "DCB Attributes used:\n" );
!         printf( "  RECFM=%-4.4s  LRECL=%-5.5d  BLKSIZE=%d\n",
!             valfm[ i ].recfm,
!             opts.lrecl,
!             opts.blksize );
!     }
!     else if (disp_opt == 1)
!     {
!         printf(" %-4.4s %5d %5d\n", 
!                valfm[ i ].recfm, opts.lrecl, opts.blksize);
!     }
  
      return;
  }
***************
*** 285,293 ****
      }
  
      /*
!     || Save the block length (should we use BDW for RECFM=V files???)
      */
      blklen = rc;
  
      return( rc );
  }
--- 304,325 ----
      }
  
      /*
!     || Save the block length, and use BDW for RECFM=V to protect
!        against minimum block sizes (which avoid tape noise).
      */
      blklen = rc;
+     if( (blklen > 4) && (opts.recfm & O_VARIABLE) )
+     {
+         int bdw;
+         
+         bdw = bdw_length( blkptr );
+         if ( (bdw > 4) && (bdw < blklen) )
+         {
+             blklen = bdw;
+         }
+     }
+ 
+     rc = blklen;
  
      return( rc );
  }
***************
*** 403,408 ****
--- 435,809 ----
  }
  
  /*
+ || List files in the tape "archive" (ie think "unzip -v")
+    Only works on SL tapes.
+ */
+ int
+ listfiles( HETB *hetb )
+ {
+     SLFMT fmt;
+     SLLABEL lab;
+     int rc;
+     
+     /*
+     || First block should be a VOL1 record
+     */
+     rc = get_sl( hetb, &lab );
+     if( rc < 0 || !sl_isvol( &lab, 1 ) )
+     {
+         printf( "Expected VOL1 label\n" );
+         return( -1 );
+     }
+         
+     /* process all files on tape */
+     while (rc >= 0)
+     {
+         /*
+         || Get the HDR1 label.
+         */
+         rc = get_sl( hetb, &lab );
+         if( rc < 0 || !sl_ishdr( &lab, 1 ) )
+         {
+             /* quietly return when no more files */
+             return( 0 );
+         }
+ 
+         /*
+         || Make the label more managable
+         */
+         sl_fmtlab( &fmt, &lab );
+         printf("%-17.17s", fmt.slds1.dsid ); 
+     
+         /*
+         || Get the HDR2 label.
+         */
+         rc = get_sl( hetb, &lab );
+         if( rc < 0 || !sl_ishdr( &lab, 2 ) )
+         {
+             printf( "Expected HDR2 label\n" );
+             return( -1 );
+         }
+     
+         /*
+         || Merge the DCB information
+         */
+         merge( &lab, 1 );
+ 
+         /*
+         || Hop over the tapemark
+         */
+         rc = het_fsf( hetb );
+         if( rc < 0 )
+         {
+             printf( "%s while spacing to start of data\n",
+                 het_error( rc ) );
+             return( rc );
+         }
+ 
+         /*
+         || skip data file, if any
+         */
+         rc = het_fsf( hetb );
+         if( rc < 0 )
+         {
+             return( 0 );
+         }
+         /*
+         || skip EOF file, if any
+         */
+         rc = het_fsf( hetb );
+         if( rc < 0 )
+         {
+             return( 0 );
+         }
+ 
+     } /* while */
+     return (0);
+ }
+ 
+ /*
+ || Extract files from the tape "archive" (ie think "unzip")
+    Only works on SL tapes.
+ */
+ int
+ extractfiles( HETB *hetb )
+ {
+     SLFMT fmt;
+     SLLABEL lab;
+     unsigned char *ptr;
+     int rc;
+     FILE *outf;
+     
+     /*
+     || First block should be a VOL1 record
+     */
+     rc = get_sl( hetb, &lab );
+     if( rc < 0 || !sl_isvol( &lab, 1 ) )
+     {
+         printf( "Expected VOL1 label\n" );
+         return( -1 );
+     }
+         
+     /* process all files on tape */
+     while (rc >= 0)
+     {
+         /*
+         || Get the HDR1 label.
+         */
+         rc = get_sl( hetb, &lab );
+         if( rc < 0 || !sl_ishdr( &lab, 1 ) )
+         {
+             /* quietly return when no more files */
+             return( 0 );
+         }
+ 
+         /*
+         || Make the label more managable
+         */
+         sl_fmtlab( &fmt, &lab );
+         printf("%-17.17s", fmt.slds1.dsid ); 
+     
+         /*
+         || Get the HDR2 label.
+         */
+         rc = get_sl( hetb, &lab );
+         if( rc < 0 || !sl_ishdr( &lab, 2 ) )
+         {
+             printf( "Expected HDR2 label\n" );
+             return( -1 );
+         }
+     
+         /*
+         || Merge the DCB information
+         */
+         merge( &lab, 1 );
+ 
+         /*
+         || Hop over the tapemark
+         */
+         rc = het_fsf( hetb );
+         if( rc < 0 )
+         {
+             printf( "%s while spacing to start of data\n",
+                 het_error( rc ) );
+             return( rc );
+         }
+ 
+         /*
+         || process the current file
+         */
+         {
+             /*
+             || Open the output file
+             */
+             char pathname[MAX_PATH];
+             
+             opts.ofile = fmt.slds1.dsid;
+             hostpath(pathname, opts.ofile, sizeof(pathname));
+             outf = fopen( pathname, (opts.flags & O_ASCII) ? "w" : "wb" );
+             if( outf == NULL )
+             {
+                 printf("unable to open %s\n", opts.ofile);
+                 return( -1 );
+             }
+         }
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+     /* this should be in a common block, or at least indented */
+ 
+     /*
+     || Different processing when converting to ASCII
+     */
+     if( opts.flags & ( O_ASCII | O_UNBLOCK | O_RDW ) )
+     {
+         /*
+         || Get a record
+         */
+         while( ( rc = getrecord( hetb ) ) >= 0 )
+         {
+ #ifdef EXTERNALGUI
+             if( extgui )
+             {
+                 /* Report progress every nnnK */
+                 off_t curpos = ftell( hetb->fd );
+                 if( ( curpos & PROGRESS_MASK ) != ( prevpos & PROGRESS_MASK ) )
+                 {
+                     prevpos = curpos;
+                     fprintf( stderr, "IPOS=%" I64_FMT "d\n", (U64)curpos );
+                 }
+             }
+ #endif /*EXTERNALGUI*/
+             /*
+             || Get working copy of record ptr
+             */
+             ptr = recptr;
+ 
+             /*
+             || Only want data portion for RECFM=V records
+             */
+             if( opts.recfm & O_VARIABLE )
+             {
+                 ptr += 4;
+                 rc -= 4;
+             }
+ 
+             /*
+             || Convert record to ASCII
+             */
+             if( opts.flags & O_ASCII )
+             {
+                 sl_etoa( NULL, ptr, rc );
+             }
+ 
+             /*
+             || Strip trailing blanks
+             */
+             if( opts.flags & O_STRIP 
+                 || ((opts.flags & O_HRCTXT)
+                     && (opts.recfm & O_FIXED)
+                    )
+               )
+             {
+                 while( rc > 0 && ptr[ rc - 1 ] == ' ' )
+                 {
+                     rc--;
+                 }
+                 
+                 /* if a text file has been copied, in binary mode,
+                    into a fixed dataset, it will have NUL-padding.
+                    Since we don't want NULs in a text file, we
+                    clean them up too */
+                 if (opts.recfm & O_FIXED)
+                 {
+                     while( rc > 0 && ptr[ rc - 1 ] == '\0' )
+                     {
+                         rc--;
+                     }
+                 }
+             }
+             
+             /*
+             || Write the record out
+             */
+             if ( (opts.flags & O_ASCII)
+                  && rc == 1
+                  && ptr[0] == ' '
+                  && !(opts.flags & O_RDW)
+                  && ( ((opts.recfm & O_UNDEFINED)
+                        && !(opts.flags & O_NO_NEW)
+                       )
+                       || (opts.recfm & O_VARIABLE)
+                     )
+                )
+             {
+                 /* if the dataset is undefined or variable and has a 
+                    single space, then don't write out that space,
+                    because the space most likely exists because it
+                    was artificially inserted to prevent empty
+                    records or blocks rather than because the user
+                    really wants a space. Also, if they are taking
+                    care of newlines themselves for RECFM=U, then
+                    any single space in the last block would be
+                    genuine albeit extremely unlikely. */
+                 rc = 0;
+             }
+             
+             /* write out an artificial RDW */
+             if ((opts.flags & O_RDW)
+                 || ((opts.flags & O_HRCBIN)
+                     && (opts.recfm & O_VARIABLE)
+                    )
+                )
+             {
+                 int havenl = 0;
+ 
+                 /* take into account newline */
+                 if( opts.flags & O_ASCII 
+                     && (!(opts.flags & O_NO_NEW) 
+                         || !(opts.recfm & O_UNDEFINED)
+                        )
+                   )
+                 {
+                     havenl = 1;
+                     rc++;
+                 }
+                 rc += 4;
+                 fputc( (((unsigned int)rc >> 8) & 0xff), outf );
+                 fputc( ((unsigned int)rc & 0xff), outf );
+                 fputc( 0x00, outf );
+                 fputc( 0x00, outf );
+                 rc -= 4;
+                 if (havenl)
+                 {
+                     rc--;
+                 }
+             }
+             fwrite( ptr, rc, 1, outf );
+ 
+             /*
+             || Put out a linefeed when converting
+             */
+             if( opts.flags & O_ASCII 
+                 && (!(opts.flags & O_NO_NEW) 
+                     || !(opts.recfm & O_UNDEFINED)
+                    )
+               )
+             {
+                 fwrite( "\n", 1, 1, outf );
+             }
+         }
+     }
+     else
+     {
+         /*
+         || Get a record
+         */
+         while( ( rc = getblock( hetb ) ) >= 0 )
+         {
+ #ifdef EXTERNALGUI
+             if( extgui )
+             {
+                 /* Report progress every nnnK */
+                 off_t curpos = ftell( hetb->fd );
+                 if( ( curpos & PROGRESS_MASK ) != ( prevpos & PROGRESS_MASK ) )
+                 {
+                     prevpos = curpos;
+                     fprintf( stderr, "IPOS=%" I64_FMT "d\n", (U64)curpos );
+                 }
+             }
+ #endif /*EXTERNALGUI*/
+             /*
+             || Write the record out
+             */
+             fwrite( blkptr, blklen, 1, outf );
+         }
+     }
+ 
+         
+         
+ 
+         fclose(outf); /* finished writing a single file */
+         
+         /*
+         || skip EOF file, if any
+         */
+         rc = het_fsf( hetb );
+         if( rc < 0 )
+         {
+             return( 0 );
+         }
+ 
+     } /* while */
+     return (0);
+ }
+ 
+ /*
  || Extract the file from the tape
  */
  int
***************
*** 506,512 ****
          /*
          || Merge the DCB information
          */
!         merge( &lab );
  
          /*
          || Hop over the tapemark
--- 907,913 ----
          /*
          || Merge the DCB information
          */
!         merge( &lab, 0 );
  
          /*
          || Hop over the tapemark
***************
*** 523,529 ****
      /*
      || Different processing when converting to ASCII
      */
!     if( opts.flags & ( O_ASCII | O_UNBLOCK ) )
      {
          /*
          || Get a record
--- 924,930 ----
      /*
      || Different processing when converting to ASCII
      */
!     if( opts.flags & ( O_ASCII | O_UNBLOCK | O_RDW ) )
      {
          /*
          || Get a record
***************
*** 567,589 ****
              /*
              || Strip trailing blanks
              */
!             if( opts.flags & O_STRIP )
              {
                  while( rc > 0 && ptr[ rc - 1 ] == ' ' )
                  {
                      rc--;
                  }
              }
              
              /*
              || Write the record out
              */
              fwrite( ptr, rc, 1, outf );
  
              /*
              || Put out a linefeed when converting
              */
!             if( opts.flags & O_ASCII )
              {
                  fwrite( "\n", 1, 1, outf );
              }
--- 968,1063 ----
              /*
              || Strip trailing blanks
              */
!             if( opts.flags & O_STRIP 
!                 || ((opts.flags & O_HRCTXT)
!                     && (opts.recfm & O_FIXED)
!                    )
!               )
              {
                  while( rc > 0 && ptr[ rc - 1 ] == ' ' )
                  {
                      rc--;
                  }
+                 
+                 /* if a text file has been copied, in binary mode,
+                    into a fixed dataset, it will have NUL-padding.
+                    Since we don't want NULs in a text file, we
+                    clean them up too */
+                 if (opts.recfm & O_FIXED)
+                 {
+                     while( rc > 0 && ptr[ rc - 1 ] == '\0' )
+                     {
+                         rc--;
+                     }
+                 }
              }
              
              /*
              || Write the record out
              */
+             if ( (opts.flags & O_ASCII)
+                  && rc == 1
+                  && ptr[0] == ' '
+                  && !(opts.flags & O_RDW)
+                  && ( ((opts.recfm & O_UNDEFINED)
+                        && !(opts.flags & O_NO_NEW)
+                       )
+                       || (opts.recfm & O_VARIABLE)
+                     )
+                )
+             {
+                 /* if the dataset is undefined or variable and has a 
+                    single space, then don't write out that space,
+                    because the space most likely exists because it
+                    was artificially inserted to prevent empty
+                    records or blocks rather than because the user
+                    really wants a space. Also, if they are taking
+                    care of newlines themselves for RECFM=U, then
+                    any single space in the last block would be
+                    genuine albeit extremely unlikely. */
+                 rc = 0;
+             }
+             
+             /* write out an artificial RDW */
+             if ((opts.flags & O_RDW)
+                 || ((opts.flags & O_HRCBIN)
+                     && (opts.recfm & O_VARIABLE)
+                    )
+                )
+             {
+                 int havenl = 0;
+ 
+                 /* take into account newline */
+                 if( opts.flags & O_ASCII 
+                     && (!(opts.flags & O_NO_NEW) 
+                         || !(opts.recfm & O_UNDEFINED)
+                        )
+                   )
+                 {
+                     havenl = 1;
+                     rc++;
+                 }
+                 rc += 4;
+                 fputc( (((unsigned int)rc >> 8) & 0xff), outf );
+                 fputc( ((unsigned int)rc & 0xff), outf );
+                 fputc( 0x00, outf );
+                 fputc( 0x00, outf );
+                 rc -= 4;
+                 if (havenl)
+                 {
+                     rc--;
+                 }
+             }
              fwrite( ptr, rc, 1, outf );
  
              /*
              || Put out a linefeed when converting
              */
!             if( opts.flags & O_ASCII 
!                 && (!(opts.flags & O_NO_NEW) 
!                     || !(opts.recfm & O_UNDEFINED)
!                    )
!               )
              {
                  fwrite( "\n", 1, 1, outf );
              }
***************
*** 648,654 ****
      */
      while( TRUE )
      {
!         rc = getopt( argc, argv, "abhnsu" );
          if( rc == -1 )
          {
              break;
--- 1122,1128 ----
      */
      while( TRUE )
      {
!         rc = getopt( argc, argv, "abhlnsturz" );
          if( rc == -1 )
          {
              break;
***************
*** 660,670 ****
--- 1134,1153 ----
                  opts.flags |= O_ASCII;
              break;
  
+             case 'b':
+                 opts.flags |= O_HRCBIN;
+                 opts.flags |= O_UNBLOCK;
+             break;
+ 
              case 'h':
                  usage( argv[ 0 ] );
                  exit( 1 );
              break;
  
+             case 'l':
+                 opts.flags |= O_LIST;
+             break;
+ 
              case 'n':
                  opts.flags |= O_NL;
              break;
***************
*** 673,682 ****
--- 1156,1180 ----
                  opts.flags |= O_STRIP;
              break;
  
+             case 't':                
+                 opts.flags |= O_HRCTXT;
+                 opts.flags |= O_ASCII;
+                 opts.flags |= O_UNBLOCK;
+                 opts.flags |= O_NO_NEW;
+             break;
+ 
              case 'u':
                  opts.flags |= O_UNBLOCK;
              break;
  
+             case 'r':
+                 opts.flags |= O_RDW;
+             break;
+ 
+             case 'z':
+                 opts.flags |= O_NO_NEW;
+             break;
+ 
              default:
                  usage( argv[ 0 ] );
                  exit( 1 );
***************
*** 688,693 ****
--- 1186,1266 ----
      || Calc number of non-switch arguments
      */
      argc -= optind;
+     
+     if (opts.flags & O_LIST)
+     {
+         if( argc != 1 )
+         {
+             printf("list option requires tape name\n");
+             exit( 1 );
+         }
+         opts.ifile = argv[ optind ];
+         /*
+         || Open the tape file
+         */
+         rc = het_open( &hetb, opts.ifile, 0 );
+         if( rc >= 0 )
+         {
+             /*
+             || Get memory for the tape buffer
+             */
+             blkptr = malloc( HETMAX_BLOCKSIZE );
+             if( blkptr != NULL )
+             {
+                 listfiles( hetb );
+                 /*
+                 || Free the buffer memory
+                 */
+                 free( blkptr );
+             }
+             /*
+             || Close the tape file
+             */
+             het_close( &hetb );
+         }
+         return 0;
+     }
+     
+     /*
+     || If we have a single parameter, assume extraction
+     */
+     if( argc == 1 )
+     {
+         /* unless otherwise specified (via a deliberate
+            setting of the text options), assume they want
+            binary with sensible defaults */
+         if (!(opts.flags & O_ASCII))
+         {
+             opts.flags |= O_HRCBIN;
+             opts.flags |= O_UNBLOCK;
+         }
+ 
+         opts.ifile = argv[ optind ];
+         /*
+         || Open the tape file
+         */
+         rc = het_open( &hetb, opts.ifile, 0 );
+         if( rc >= 0 )
+         {
+             /*
+             || Get memory for the tape buffer
+             */
+             blkptr = malloc( HETMAX_BLOCKSIZE );
+             if( blkptr != NULL )
+             {
+                 extractfiles( hetb );
+                 /*
+                 || Free the buffer memory
+                 */
+                 free( blkptr );
+             }
+             /*
+             || Close the tape file
+             */
+             het_close( &hetb );
+         }
+         return 0;
+     }
  
      /*
      || We must have at least the first 3 parms
***************
*** 800,806 ****
              */
              char pathname[MAX_PATH];
              hostpath(pathname, opts.ofile, sizeof(pathname));
!             outf = fopen( pathname, "wb" );
              if( outf != NULL )
              {
                  /*
--- 1373,1379 ----
              */
              char pathname[MAX_PATH];
              hostpath(pathname, opts.ofile, sizeof(pathname));
!             outf = fopen( pathname, (opts.flags & O_ASCII) ? "w" : "wb" );
              if( outf != NULL )
              {
                  /*
Index: hercules/hetinit.c
diff -c hercules/hetinit.c:1.1.1.3 hercules/hetinit.c:1.3
*** hercules/hetinit.c:1.1.1.3	Sat Feb 13 16:08:40 2010
--- hercules/hetinit.c	Sat Dec 25 18:23:40 2010
***************
*** 1,7 ****
  /*
  || ----------------------------------------------------------------------------
  ||
! || HETINIT.C    (c) Copyright Leland Lucius, 2000-2009
  ||              Released under terms of the Q Public License.
  ||
  || Creates IEHINITT or NL format Hercules Emulated Tapes.
--- 1,7 ----
  /*
  || ----------------------------------------------------------------------------
  ||
! || HETINIT.C    (c) Copyright Leland Lucius, 2000-2007
  ||              Released under terms of the Q Public License.
  ||
  || Creates IEHINITT or NL format Hercules Emulated Tapes.
***************
*** 9,20 ****
  || ----------------------------------------------------------------------------
  */
  
! // $Id: hetinit.c 5125 2009-01-23 12:01:44Z bernard $
! //
! // $Log$
! // Revision 1.25  2008/11/04 04:50:46  fish
! // Ensure consistent utility startup
  //
  // Revision 1.24  2007/06/23 00:04:10  ivan
  // Update copyright notices to include current year (2007)
  //
--- 9,17 ----
  || ----------------------------------------------------------------------------
  */
  
! // $Id: hetinit.c,v 1.24 2007/06/23 00:04:10 ivan Exp $
  //
+ // $Log: hetinit.c,v $
  // Revision 1.24  2007/06/23 00:04:10  ivan
  // Update copyright notices to include current year (2007)
  //
***************
*** 77,83 ****
      char *o_owner;
      char *o_volser;
  
!     INITIALIZE_UTILITY("hetinit");
  
      hetb = NULL;
  
--- 74,90 ----
      char *o_owner;
      char *o_volser;
  
!     set_codepage( NULL );
! 
! #ifdef EXTERNALGUI
!     if (argc >= 1 && strncmp(argv[argc-1],"EXTERNALGUI",11) == 0)
!     {
!         extgui = 1;
!         argc--;
!         setvbuf(stderr, NULL, _IONBF, 0);
!         setvbuf(stdout, NULL, _IONBF, 0);
!     }
! #endif /*EXTERNALGUI*/
  
      hetb = NULL;
  
Index: hercules/hetlib.c
diff -c hercules/hetlib.c:1.1.1.3 hercules/hetlib.c:1.2
*** hercules/hetlib.c:1.1.1.3	Sat Feb 13 16:08:41 2010
--- hercules/hetlib.c	Sun Sep 26 08:26:35 2010
***************
*** 771,777 ****
      unsigned long slen;
      int flags1, flags2;
      unsigned long tlen;
!     char tbuf[ HETMAX_BLOCKSIZE ];
  
      /*
      || Initialize
--- 771,777 ----
      unsigned long slen;
      int flags1, flags2;
      unsigned long tlen;
!     char tbuf[ ((((HETMAX_BLOCKSIZE * 1001) + 999) / 1000) + 12) ];
  
      /*
      || Initialize
***************
*** 865,871 ****
          /*
          || Can't be bigger than HETMAX_BLOCKSIZE
          */
!         if( tlen > HETMAX_BLOCKSIZE )
          {
              return( HETE_OVERFLOW );
          }
--- 865,871 ----
          /*
          || Can't be bigger than HETMAX_BLOCKSIZE
          */
!         if( tlen > sizeof tbuf )
          {
              return( HETE_OVERFLOW );
          }
Index: hercules/hmacros.h
diff -c hercules/hmacros.h:1.1.1.3 hercules/hmacros.h:1.8
*** hercules/hmacros.h:1.1.1.3	Sat Feb 13 16:08:44 2010
--- hercules/hmacros.h	Sat Feb 13 17:11:32 2010
***************
*** 276,281 ****
--- 276,282 ----
  typedef void (ATTR_REGPARM(2) *pi_func) (REGS *regs, int pcode);
  
  /* trace_br function */
+ typedef U32  (*s370_trace_br_func) (int amode,  U32 ia, REGS *regs);
  typedef U32  (*s390_trace_br_func) (int amode,  U32 ia, REGS *regs);
  typedef U64  (*z900_trace_br_func) (int amode,  U64 ia, REGS *regs);
  
Index: hercules/hsccmd.c
diff -c hercules/hsccmd.c:1.1.1.4 hercules/hsccmd.c:1.8
*** hercules/hsccmd.c:1.1.1.4	Thu Mar 11 00:23:44 2010
--- hercules/hsccmd.c	Sat Apr 24 12:21:41 2010
***************
*** 4150,4156 ****
--- 4150,4162 ----
      }
      if (strcasecmp (argv[1], "OS/390") == 0)
      {
+ #if defined(FEATURE_S380)
+         /* MVS users may wish to use Herc380 to handle ATL getmains */
+         sysblk.pgminttr = 0;
+         sysblk.mvs_special = 1;
+ #else
          sysblk.pgminttr = OS_OS390;
+ #endif
          return 0;
      }
      if (strcasecmp (argv[1], "+OS/390") == 0)
***************
*** 4180,4186 ****
--- 4186,4198 ----
      }
      if (strcasecmp (argv[1], "VSE") == 0)
      {
+ #if defined(FEATURE_S380)
+         /* DOS/VS requires special processing to avoid a loop at IPL time */
+         sysblk.pgminttr = 0;
+         sysblk.vse_special = 1;
+ #else
          sysblk.pgminttr = OS_VSE;
+ #endif
          return 0;
      }
      if (strcasecmp (argv[1], "+VSE") == 0)
***************
*** 6251,6261 ****
--- 6263,6286 ----
                        "architecture\n") );
              return -1;
          }
+ #ifdef FEATURE_S380
+     if (!strcasecmp (argv[1], "S/380"))
+     {
+         sysblk.arch_mode = ARCH_370;
+         sysblk.maxcpu = sysblk.numcpu;
+         sysblk.s380 = 1;
+     }
+     else
+ #endif
  #if defined(_370)
      if (!strcasecmp (argv[1], arch_name[ARCH_370]))
      {
          sysblk.arch_mode = ARCH_370;
          sysblk.maxcpu = sysblk.numcpu;
+ #ifdef FEATURE_S380
+         /* force s370 to be s380 until Hercgui updated */
+         sysblk.s380 = 1;
+ #endif
      }
      else
  #endif
***************
*** 7262,7268 ****
  
          /* Remove any # comments on the line before processing */
  
!         if ((p = strchr(scrbuf,'#')) && p > scrbuf)
              do *p = 0; while (isspace(*--p) && p >= scrbuf);
  
          if (strncasecmp(scrbuf,"pause",5) == 0)
--- 7287,7293 ----
  
          /* Remove any # comments on the line before processing */
  
!         if ((p = strrchr(scrbuf,'#')) && p > scrbuf)
              do *p = 0; while (isspace(*--p) && p >= scrbuf);
  
          if (strncasecmp(scrbuf,"pause",5) == 0)
Index: hercules/hstdinc.h
diff -c hercules/hstdinc.h:1.1.1.3 hercules/hstdinc.h:1.4
*** hercules/hstdinc.h:1.1.1.3	Sat Feb 13 16:08:48 2010
--- hercules/hstdinc.h	Sat Feb 13 17:11:33 2010
***************
*** 10,15 ****
--- 10,17 ----
  #ifndef _HSTDINC_H
  #define _HSTDINC_H
  
+ #define FEATURE_S380
+ 
  #ifdef HAVE_CONFIG_H
    #include <config.h> // Hercules build configuration options/settings
  #endif
Index: hercules/hstructs.h
diff -c hercules/hstructs.h:1.1.1.3 hercules/hstructs.h:1.20
*** hercules/hstructs.h:1.1.1.3	Sat Feb 13 16:08:49 2010
--- hercules/hstructs.h	Tue Dec 14 23:48:24 2010
***************
*** 263,269 ****
       /* Opcode table pointers                                        */
  
          FUNC    s370_opcode_table[256];
!         FUNC   *s370_opcode_a4xx,
                 *s370_opcode_a5xx,
                 *s370_opcode_a6xx,
   #if defined(MULTI_BYTE_ASSIST)
--- 263,270 ----
       /* Opcode table pointers                                        */
  
          FUNC    s370_opcode_table[256];
!         FUNC   *s370_opcode_01xx,
!                *s370_opcode_a4xx,
                 *s370_opcode_a5xx,
                 *s370_opcode_a6xx,
   #if defined(MULTI_BYTE_ASSIST)
***************
*** 560,565 ****
--- 561,574 ----
          int     pcpu;                   /* Tgt CPU panel cmd & displ */
          int     hercprio;               /* Hercules process priority */
          int     todprio;                /* TOD Clock thread priority */
+ #ifdef FEATURE_S380
+         int     s380;                   /* S/380 architecture        */
+         int     mvs_special;            /* special MVS processing    */
+         int     vse_special;            /* special VSE processing    */
+ #if VSE_UNPATCHED
+         RADR    vse_real;               /* What VSE really has       */
+ #endif
+ #endif
          int     cpuprio;                /* CPU thread priority       */
          int     devprio;                /* Device thread priority    */
          TID     httptid;                /* HTTP listener thread id   */
Index: hercules/omatape.c
diff -c hercules/omatape.c:1.1.1.2 hercules/omatape.c:1.12
*** hercules/omatape.c:1.1.1.2	Sat Feb 13 16:08:58 2010
--- hercules/omatape.c	Sat Feb 13 17:11:33 2010
***************
*** 259,266 ****
          else if (strcasecmp(tdfformat, "TEXT") == 0)
          {
              tdftab[filecount].format = 'T';
          }
!         else if (strcasecmp(tdfformat, "FIXED") == 0)
          {
              /* Check for RECSIZE keyword */
              if (tdfreckwd == NULL
--- 259,294 ----
          else if (strcasecmp(tdfformat, "TEXT") == 0)
          {
              tdftab[filecount].format = 'T';
+             if (strcasecmp(tdfreckwd, "NL") == 0)
+             {
+                 /* indicate that we are preserving newlines */
+                 tdftab[filecount].flags |= OMATAPE_NL;
+             }
+             else if (strcasecmp(tdfreckwd, "V") == 0)
+             {
+                 tdftab[filecount].flags |= OMATAPE_VART;
+             }
+             else if (strcasecmp(tdfreckwd, "F") == 0)
+             {
+                 tdftab[filecount].flags |= OMATAPE_FIXEDT;
+                 /* Check for valid fixed block length */
+                 if (tdfblklen == NULL
+                     || sscanf(tdfblklen, "%u%c", &blklen, &c) != 1
+                     || blklen < 1 || blklen > MAX_BLKLEN)
+                 {
+                     logmsg (_("HHCTA048E Invalid record size %s in "
+                             "line %d of file %s\n"),
+                             tdfblklen, stmt, dev->filename);
+                     free (tdftab);
+                     free (tdfbuf);
+                     return -1;
+                 }
+                 tdftab[filecount].blklen = blklen;
+             }
          }
!         else if ((strcasecmp(tdfformat, "FIXED") == 0)
!                  || (strcasecmp(tdfformat, "RDWFIXN") == 0)
!                  || (strcasecmp(tdfformat, "RDWFIX") == 0))
          {
              /* Check for RECSIZE keyword */
              if (tdfreckwd == NULL
***************
*** 288,296 ****
              }
  
              /* Set format and block length in descriptor array */
!             tdftab[filecount].format = 'F';
              tdftab[filecount].blklen = blklen;
          }
          else
          {
              logmsg (_("HHCTA249E %4.4X: Invalid record format %s in "
--- 316,352 ----
              }
  
              /* Set format and block length in descriptor array */
!             
!             /* Present a RDW file as fixed-length records with
!                NUL-padding */
!             if (strcasecmp(tdfformat, "RDWFIXN") == 0)
!             {
!                 tdftab[filecount].format = 'N';
!             }
!             /* Present a RDW file as fixed-length records with
!                space-padding */
!             else if (strcasecmp(tdfformat, "RDWFIX") == 0)
!             {
!                 tdftab[filecount].format = 'O';
!             }
!             else
!             {
!                 tdftab[filecount].format = 'F';
!             }
              tdftab[filecount].blklen = blklen;
          }
+         /* present a RDW file as "undefined", by stripping
+            off the RDW and presenting the record as a single
+            block */
+         else if (strcasecmp(tdfformat, "RDWUND") == 0)
+         {
+             tdftab[filecount].format = 'P';
+         }
+         /* present a RDW file in its natural form - as a V dataset */
+         else if (strcasecmp(tdfformat, "RDWVAR") == 0)
+         {
+             tdftab[filecount].format = 'Q';
+         }
          else
          {
              logmsg (_("HHCTA249E %4.4X: Invalid record format %s in "
***************
*** 708,716 ****
          /* Ignore carriage return character */
          if (c == '\r') continue;
  
!         /* Exit if newline character */
!         if (c == '\n') break;
! 
          /* Ignore characters in excess of I/O buffer length */
          if (pos >= MAX_BLKLEN) continue;
  
--- 764,803 ----
          /* Ignore carriage return character */
          if (c == '\r') continue;
  
!         /* if we're not passing through newlines, exit now.
!            Unless we've got an empty line, in which case, send
!            through a single space. */
!         if (!(omadesc->flags & OMATAPE_NL))
!         {
!             if (c == '\n')
!             {
!                 if (pos == 0)
!                 {
!                     if (buf != NULL)
!                         buf[pos] = host_to_guest(' ');
!                     pos++;
!                 }
!                 if ((omadesc->flags & OMATAPE_VART)
!                     && (buf != NULL))
!                 {
!                     memmove(buf + 8, buf, pos);
!                     buf[0] = (pos + 8) >> 8;
!                     buf[1] = (pos + 8) & 0xff;
!                     buf[2] = buf[3] = '\0';
!                     buf[4] = (pos + 4) >> 8;
!                     buf[5] = (pos + 4) & 0xff;
!                     buf[6] = buf[7] = '\0';
!                     pos += 8;
!                 }
!                 if ((omadesc->flags & OMATAPE_FIXEDT)
!                     && (buf != NULL))
!                 {
!                     memset(buf + pos, 0x40, omadesc->blklen - pos);
!                     pos = omadesc->blklen;
!                 }
!                 break;
!             }
!         }
          /* Ignore characters in excess of I/O buffer length */
          if (pos >= MAX_BLKLEN) continue;
  
***************
*** 721,726 ****
--- 808,817 ----
          /* Count characters copied or skipped */
          pos++;
  
+         /* if we're passing through newline characters, now is the
+            point at which we will break */
+         if (c == '\n') break;
+ 
      } /* end for(num) */
  
      /* At end of file return zero to indicate tapemark */
***************
*** 780,785 ****
--- 871,1021 ----
  } /* end function read_omatext */
  
  /*-------------------------------------------------------------------*/
+ /* Read a block from an OMA tape file in rdw format                  */
+ /*                                                                   */
+ /* If successful, return value is block length read.                 */
+ /* If a tapemark was read, the file is closed, the current file      */
+ /* number in the device block is incremented so that the next file   */
+ /* will be opened by the next CCW, and the return value is zero.     */
+ /* If error, return value is -1 and unitstat is set to CE+DE+UC      */
+ /* A NULL buf can be provided to skip the data                       */
+ /*-------------------------------------------------------------------*/
+ int read_omardw (DEVBLK *dev, OMATAPE_DESC *omadesc,
+                         BYTE *buf, BYTE *unitstat,BYTE code)
+ {
+ off_t           rcoff;                  /* Return code from lseek()  */
+ int             blklen;                 /* Block length              */
+ long            blkpos;                 /* Offset of block in file   */
+ BYTE            rdw[4];                 /* record descriptor word    */
+ int             rdwlen;                 /* converted to integer      */
+ int             extra = 0;
+ 
+     /* Initialize current block position */
+     blkpos = dev->nxtblkpos;
+ 
+     /* Seek to new current block position */
+     rcoff = lseek (dev->fd, blkpos, SEEK_SET);
+     if (rcoff < 0)
+     {
+         /* Handle seek error condition */
+         logmsg (_("HHCTA058E Error seeking to offset "I32_FMTX" "
+                 "in file %s: %s\n"),
+                 blkpos, omadesc->filename, strerror(errno));
+ 
+         /* Set unit check with equipment check */
+         build_senseX(TAPE_BSENSE_LOCATEERR,dev,unitstat,code);
+         return -1;
+     }
+ 
+     /* Read rdw */
+     blklen = read (dev->fd, rdw, 4);
+ 
+     /* Handle read error condition */
+     if (blklen < 0)
+     {
+         logmsg (_("HHCTA059E Error reading data block "
+                 "at offset "I32_FMTX" in file %s: %s\n"),
+                 blkpos, omadesc->filename,
+                 strerror(errno));
+ 
+         build_senseX(TAPE_BSENSE_READFAIL,dev,unitstat,code);
+         return -1;
+     }
+ 
+     /* At end of file return zero to indicate tapemark */
+     /* Also if we read a file with NUL-padding */
+     if ((blklen < 4) || ((rdw[0] == 0) && (rdw[1] == 0)))
+     {
+         close (dev->fd);
+         dev->fd = -1;
+         dev->curfilen++;
+         dev->nxtblkpos = 0;
+         dev->prvblkpos = -1;
+         return 0;
+     }
+ 
+     rdwlen = (rdw[0] << 8) | rdw[1];
+     
+     /* if record is too long, silently truncate */
+     if ((omadesc->blklen != 0) && (rdwlen > (omadesc->blklen + 4)))
+     {
+         extra = rdwlen - omadesc->blklen - 4;
+         rdwlen = omadesc->blklen + 4;
+     }
+     if (buf != NULL)
+     {
+         blklen = read (dev->fd, buf, rdwlen - 4);
+     }
+     /* if we're not reading data, or we have extra bytes to skip */
+     if ((buf == NULL) || (extra != 0))
+     {
+         /* Seek to new current block position */
+         rcoff = lseek (dev->fd, blkpos + rdwlen, SEEK_SET);
+         if (rcoff < 0)
+         {
+             /* Handle seek error condition */
+             logmsg (_("HHCTA058E Error seeking to offset "I32_FMTX" "
+                     "in file %s: %s\n"),
+                     blkpos, omadesc->filename, strerror(errno));
+ 
+             /* Set unit check with equipment check */
+             build_senseX(TAPE_BSENSE_LOCATEERR,dev,unitstat,code);
+             return -1;
+         }
+         /* assume whole block has been read */        
+         if (extra == 0)
+         {
+             blklen = rdwlen - 4;
+         }
+     }
+ 
+     /* Handle read error condition */
+     if (blklen != (rdwlen - 4))
+     {
+         logmsg (_("HHCTA059E Error reading data block "
+                 "at offset "I32_FMTX" in file %s: %s\n"),
+                 blkpos, omadesc->filename,
+                 strerror(errno));
+ 
+         build_senseX(TAPE_BSENSE_READFAIL,dev,unitstat,code);
+         return -1;
+     }
+ 
+     /* Calculate the offsets of the next and previous blocks */
+     dev->nxtblkpos = blkpos + rdwlen + extra;
+     dev->prvblkpos = blkpos;
+ 
+     if (buf != NULL)
+     {
+         /* note - format 'P' requires no adjustment */
+         if (omadesc->format == 'N')
+         {
+             memset(buf + blklen, '\0', omadesc->blklen - blklen);
+             blklen = omadesc->blklen;
+         }
+         else if (omadesc->format == 'O')
+         {
+             memset(buf + blklen, 0x40, omadesc->blklen - blklen);
+             blklen = omadesc->blklen;
+         }
+         else if (omadesc->format == 'Q')
+         {
+             memmove(buf + 8, buf, blklen);
+             memcpy(buf + 4, rdw, 4);
+             /* insert BDW */
+             buf[0] = (rdwlen + 4) >> 8;
+             buf[1] = (rdwlen + 4) & 0xff;
+             buf[2] = buf[3] = '\0';
+             blklen = rdwlen + 4;
+         }
+     }
+ 
+     /* Return block length, or zero to indicate tapemark */
+     return blklen;
+ 
+ } /* end function read_omardw */
+ 
+ /*-------------------------------------------------------------------*/
  /* Read a block from an OMA - Selection of format done here          */
  /*                                                                   */
  /* If successful, return value is block length read.                 */
***************
*** 811,816 ****
--- 1047,1058 ----
      case 'T':
          len = read_omatext (dev, omadesc, buf, unitstat,code);
          break;
+     case 'N':
+     case 'O':
+     case 'P':
+     case 'Q':
+         len = read_omardw (dev, omadesc, buf, unitstat,code);
+         break;
      case 'X':
          len=0;
          dev->curfilen++;
***************
*** 1002,1007 ****
--- 1244,1255 ----
      case 'T':
          rc = read_omatext (dev, omadesc, NULL, unitstat,code);
          break;
+     case 'N':
+     case 'O':
+     case 'P':
+     case 'Q':
+         rc = read_omardw (dev, omadesc, NULL, unitstat,code);
+         break;
      } /* end switch(omadesc->format) */
  
      if (rc >= 0) dev->blockid++;
Index: hercules/opcode.c
diff -c hercules/opcode.c:1.1.1.3 hercules/opcode.c:1.11
*** hercules/opcode.c:1.1.1.3	Sat Feb 13 16:08:59 2010
--- hercules/opcode.c	Sat Feb 13 17:11:33 2010
***************
*** 845,851 ****
  #endif /*!defined(FEATURE_ESAME_N3_ESA390) && !defined(FEATURE_ESAME)*/
  
  
! #if !defined(FEATURE_ESAME_N3_ESA390) && !defined(_900) && !defined(FEATURE_ESAME)
   UNDEF_INST(store_facility_list);
  #endif /*!defined(FEATURE_ESAME_N3_ESA390) && !defined(_900) && !defined(FEATURE_ESAME)*/
  
--- 845,851 ----
  #endif /*!defined(FEATURE_ESAME_N3_ESA390) && !defined(FEATURE_ESAME)*/
  
  
! #if !defined(FEATURE_ESAME_N3_ESA390) && !defined(_900) && !defined(FEATURE_ESAME) && !defined(FEATURE_S380)
   UNDEF_INST(store_facility_list);
  #endif /*!defined(FEATURE_ESAME_N3_ESA390) && !defined(_900) && !defined(FEATURE_ESAME)*/
  
***************
*** 1018,1024 ****
     as the called routine has the same arguments, and the routine
     exits immediately after the call.                             *JJ */
  
! #if ARCH_MODE != ARCH_370
  DEF_INST(execute_01xx)
  {
      regs->ARCH_DEP(opcode_01xx)[inst[1]](inst, regs);
--- 1018,1024 ----
     as the called routine has the same arguments, and the routine
     exits immediately after the call.                             *JJ */
  
! #if ARCH_MODE != ARCH_370 || defined(FEATURE_S380)
  DEF_INST(execute_01xx)
  {
      regs->ARCH_DEP(opcode_01xx)[inst[1]](inst, regs);
***************
*** 1960,1965 ****
--- 1960,1966 ----
  
  /* Gabor Hoffer (performance option) */
  DLL_EXPORT zz_func s370_opcode_table[256];
+ static zz_func s370_opcode_01xx[256];
  static zz_func s370_opcode_a4xx[256];
  static zz_func s370_opcode_a5xx[256];
  static zz_func s370_opcode_a6xx[256];
***************
*** 2024,2029 ****
--- 2025,2031 ----
      {
  #if defined(_370)
          s370_opcode_table[i] = opcode_table[i][ARCH_370];
+         s370_opcode_01xx [i] = opcode_01xx [i][ARCH_370];
          s370_opcode_a4xx [i] = v_opcode_a4xx [i][ARCH_370];
          s370_opcode_a5xx [i] = v_opcode_a5xx [i][ARCH_370];
          s370_opcode_a6xx [i] = v_opcode_a6xx [i][ARCH_370];
***************
*** 2092,2097 ****
--- 2094,2100 ----
  #if defined(_370)
      memcpy(regs->s370_opcode_table, s370_opcode_table,
             sizeof(s370_opcode_table));
+     regs->s370_opcode_01xx = s370_opcode_01xx;
      regs->s370_opcode_a4xx = s370_opcode_a4xx;
      regs->s370_opcode_a5xx = s370_opcode_a5xx;
      regs->s370_opcode_a6xx = s370_opcode_a6xx;
***************
*** 2211,2218 ****
   /*08*/   GENx370x___x___ (set_storage_key,RR,"SSK"),
   /*09*/   GENx370x___x___ (insert_storage_key,RR,"ISK"),
   /*0A*/   GENx370x390x900 (supervisor_call,RR_SVC,"SVC"),
!  /*0B*/   GENx___x390x900 (branch_and_set_mode,RR,"BSM"),
!  /*0C*/   GENx___x390x900 (branch_and_save_and_set_mode,RR,"BASSM"),
   /*0D*/   GENx370x390x900 (branch_and_save_register,RR,"BASR"),
   /*0E*/   GENx370x390x900 (move_long,RR,"MVCL"),
   /*0F*/   GENx370x390x900 (compare_logical_character_long,RR,"CLCL"),
--- 2214,2221 ----
   /*08*/   GENx370x___x___ (set_storage_key,RR,"SSK"),
   /*09*/   GENx370x___x___ (insert_storage_key,RR,"ISK"),
   /*0A*/   GENx370x390x900 (supervisor_call,RR_SVC,"SVC"),
!  /*0B*/   GENx370x390x900 (branch_and_set_mode,RR,"BSM"),
!  /*0C*/   GENx370x390x900 (branch_and_save_and_set_mode,RR,"BASSM"),
   /*0D*/   GENx370x390x900 (branch_and_save_register,RR,"BASR"),
   /*0E*/   GENx370x390x900 (move_long,RR,"MVCL"),
   /*0F*/   GENx370x390x900 (compare_logical_character_long,RR,"CLCL"),
***************
*** 3080,3086 ****
--- 3083,3093 ----
   /*B238*/ GENx___x390x900 (resume_subchannel,none,"RSCH"),
   /*B239*/ GENx___x390x900 (store_channel_report_word,S,"STCRW"),
   /*B23A*/ GENx___x390x900 (store_channel_path_status,S,"STCPS"),
+ #if 0 /*def FEATURE_S380*/
+  /*B23B*/ GENx___x390x900_real (reset_channel_path,none,"RCHP"),
+ #else
   /*B23B*/ GENx___x390x900 (reset_channel_path,none,"RCHP"),
+ #endif
   /*B23C*/ GENx___x390x900 (set_channel_monitor,none,"SCHM"),
   /*B23D*/ GENx___x390x900 (store_zone_parameter,S,"STZP"),
   /*B23E*/ GENx___x390x900 (set_zone_parameter,S,"SZP"),
Index: hercules/panel.c
diff -c hercules/panel.c:1.1.1.4 hercules/panel.c:1.6
*** hercules/panel.c:1.1.1.4	Thu Mar 11 00:23:54 2010
--- hercules/panel.c	Thu Mar 11 00:29:52 2010
***************
*** 918,923 ****
--- 918,927 ----
      set_pos   (1, 1);
      draw_text ("  Hercules  CPU    :    %");
      fill_text (' ', 30);
+ #ifdef FEATURE_S380
+     if (sysblk.s380) draw_text("S/380");
+     else
+ #endif
      draw_text ((char *)get_arch_mode_string(NULL));
      fill_text (' ', 38);
      set_color (COLOR_LIGHT_GREY, COLOR_BLUE );
Index: hercules/tapedev.h
diff -c hercules/tapedev.h:1.1.1.3 hercules/tapedev.h:1.3
*** hercules/tapedev.h:1.1.1.3	Sat Feb 13 16:09:11 2010
--- hercules/tapedev.h	Sat Feb 13 17:11:34 2010
***************
*** 254,264 ****
      int     fd;                         /* File Descriptor for file  */
      char    filename[256];              /* Filename of data file     */
      char    format;                     /* H=HEADERS,T=TEXT,F=FIXED,X=Tape Mark */
!     BYTE    resv;                       /* Reserved for alignment    */
      U16     blklen;                     /* Fixed block length        */
  }
  OMATAPE_DESC;
  
  /*-------------------------------------------------------------------*/
  /* Structure definition for Flex FakeTape block headers              */
  /*-------------------------------------------------------------------*/
--- 254,276 ----
      int     fd;                         /* File Descriptor for file  */
      char    filename[256];              /* Filename of data file     */
      char    format;                     /* H=HEADERS,T=TEXT,F=FIXED,X=Tape Mark */
!                                         /* U - reserved for undefined */
!                                         /* V - ambiguous, don't use  */
!                                         /* N - RDW converted to F with NUL padding */
!                                         /* O - RDW converted to F    */
!                                         /* P - RDW converted to U    */
!                                         /* Q - RDW converted to V    */
!                                         /* R - ambiguous, don't use  */
!                                         /* S - reserved for spanned  */
!     BYTE    flags;                      /* flags (see below)         */
      U16     blklen;                     /* Fixed block length        */
  }
  OMATAPE_DESC;
  
+ #define OMATAPE_NL                0x80  /* Preserve newlines         */
+ #define OMATAPE_FIXEDT            0x40  /* Fixed text                */
+ #define OMATAPE_VART              0x20  /* Variable text             */
+ 
  /*-------------------------------------------------------------------*/
  /* Structure definition for Flex FakeTape block headers              */
  /*-------------------------------------------------------------------*/
***************
*** 525,530 ****
--- 537,543 ----
  extern int  read_omaheaders    (DEVBLK *dev, OMATAPE_DESC *omadesc, BYTE *buf, BYTE *unitstat, BYTE code);
  extern int  read_omafixed      (DEVBLK *dev, OMATAPE_DESC *omadesc, BYTE *buf, BYTE *unitstat, BYTE code);
  extern int  read_omatext       (DEVBLK *dev, OMATAPE_DESC *omadesc, BYTE *buf, BYTE *unitstat, BYTE code);
+ extern int  read_omardw        (DEVBLK *dev, OMATAPE_DESC *omadesc, BYTE *buf, BYTE *unitstat, BYTE code);
  extern int  read_omatape       (DEVBLK *dev,                        BYTE *buf, BYTE *unitstat, BYTE code);
  extern int  readhdr_omaheaders (DEVBLK *dev, OMATAPE_DESC *omadesc,
                                               long blkpos, S32 *pcurblkl,
Index: hercules/version.c
diff -c hercules/version.c:1.1.1.3 hercules/version.c:1.5
*** hercules/version.c:1.1.1.3	Sat Feb 13 16:09:14 2010
--- hercules/version.c	Sat Feb 13 17:11:35 2010
***************
*** 61,66 ****
--- 61,69 ----
  #if defined(_370)
      " " _ARCH_370_NAME
  #endif
+ #if defined(FEATURE_S380)
+     " S/380"
+ #endif
  #if defined(_390)
      " " _ARCH_390_NAME
  #endif
Index: hercules/msvc.makefile.includes/BZIP2_RULES.msvc
diff -c hercules/msvc.makefile.includes/BZIP2_RULES.msvc:1.1.1.3 hercules/msvc.makefile.includes/BZIP2_RULES.msvc:1.4
*** hercules/msvc.makefile.includes/BZIP2_RULES.msvc:1.1.1.3	Sat Feb 13 16:10:04 2010
--- hercules/msvc.makefile.includes/BZIP2_RULES.msvc	Sat Feb 13 17:11:37 2010
***************
*** 21,27 ****
  !IFDEF BZIP2_DIR
  
  $(X)libbz2.dll:
!     XCOPY "$(BZIP2_DLL)" $(X) /V /C /F /H /R /K /O /X /Y
  
  alllibbz2: allHercules \
      $(X)libbz2.dll
--- 21,27 ----
  !IFDEF BZIP2_DIR
  
  $(X)libbz2.dll:
!     XCOPY "$(BZIP2_DLL)" $(X) /V /C /F /H /R /K /Y
  
  alllibbz2: allHercules \
      $(X)libbz2.dll
Index: hercules/msvc.makefile.includes/PCRE_RULES.msvc
diff -c hercules/msvc.makefile.includes/PCRE_RULES.msvc:1.1.1.3 hercules/msvc.makefile.includes/PCRE_RULES.msvc:1.4
*** hercules/msvc.makefile.includes/PCRE_RULES.msvc:1.1.1.3	Sat Feb 13 16:10:09 2010
--- hercules/msvc.makefile.includes/PCRE_RULES.msvc	Sat Feb 13 17:11:38 2010
***************
*** 21,30 ****
  !IFDEF PCRE_DIR
  
  $(X)$(PCRE_DLLNAME1):
!     XCOPY "$(PCRE_DLLPATH1)" $(X) /V /C /F /H /R /K /O /X /Y
  
  $(X)$(PCRE_DLLNAME2):
!     XCOPY "$(PCRE_DLLPATH2)" $(X) /V /C /F /H /R /K /O /X /Y
  
  allpcre: allHercules \
      $(X)$(PCRE_DLLNAME1) \
--- 21,30 ----
  !IFDEF PCRE_DIR
  
  $(X)$(PCRE_DLLNAME1):
!     XCOPY "$(PCRE_DLLPATH1)" $(X) /V /C /F /H /R /K /Y
  
  $(X)$(PCRE_DLLNAME2):
!     XCOPY "$(PCRE_DLLPATH2)" $(X) /V /C /F /H /R /K /Y
  
  allpcre: allHercules \
      $(X)$(PCRE_DLLNAME1) \
Index: hercules/msvc.makefile.includes/VERSION.msvc
diff -c hercules/msvc.makefile.includes/VERSION.msvc:1.1.1.4 hercules/msvc.makefile.includes/VERSION.msvc:1.34
*** hercules/msvc.makefile.includes/VERSION.msvc:1.1.1.4	Thu Mar 11 00:25:02 2010
--- hercules/msvc.makefile.includes/VERSION.msvc	Mon Dec 12 18:19:29 2011
***************
*** 69,74 ****
--- 69,76 ----
  VERSION = $(VERSION)-svn-$(V4)
  !ENDIF
  
+ VERSION = 3.07:380-4.0
+ 
  !MESSAGE Hercules version number is $(VERSION) ($(V1).$(V2).$(V3).$(V4))
  VERSION = \"$(VERSION)\"
  
Index: hercules/msvc.makefile.includes/ZLIB_RULES.msvc
diff -c hercules/msvc.makefile.includes/ZLIB_RULES.msvc:1.1.1.3 hercules/msvc.makefile.includes/ZLIB_RULES.msvc:1.4
*** hercules/msvc.makefile.includes/ZLIB_RULES.msvc:1.1.1.3	Sat Feb 13 16:10:10 2010
--- hercules/msvc.makefile.includes/ZLIB_RULES.msvc	Sat Feb 13 17:11:38 2010
***************
*** 21,27 ****
  !IFDEF ZLIB_DIR
  
  $(X)zlib1.dll:
!     XCOPY "$(ZLIB_DLL)" $(X) /V /C /F /H /R /K /O /X /Y
  
  allzlib: allHercules \
      $(X)zlib1.dll
--- 21,27 ----
  !IFDEF ZLIB_DIR
  
  $(X)zlib1.dll:
!     XCOPY "$(ZLIB_DLL)" $(X) /V /C /F /H /R /K /Y
  
  allzlib: allHercules \
      $(X)zlib1.dll
