  TITLE 'str-001-mvst.asm: Test MVST Instruction'
*
***********************************************************************
*
*Testcase str-001-mvst
*  Test cases for variations on the MVST (Move String) instruction.
*
***********************************************************************
*
*                        str-001-mvst.asm
*
* Created and placed into public domain 2018-12-27 by Bob Polmanter.
* Remove runtest *Compare dependency on 2022-03-08 by Fish.
*
* The MVST instruction is tested against the definition in the
* z/Architecture Principles of Operation, SA22-7832.
*
* Test data is assembled into this program, and some test data is
* generated by this program. The program itself verifies the resulting
* status of registers and condition codes via simple CLC comparison.
*
*
* Tests performed with MVST (Move String):
*
* 1. Ensure that a non-zero bit in R0 bits 32-55 gives PIC06
* 2. Simple move; no operands cross page boundary
* 3. First byte moved is the termination character
* 4. Operand 1 crosses page boundary
* 5. Operand 2 crosses page boundary
* 6. Both operands cross page boundary, operand 1 is closer to boundary
* 7. Both operands cross page boundary, operand 2 is closer to boundary
* 8  Both operands cross boundary, both operands are the same distance
*       to the page boundary; large multipage move.
*
*
* NOTE - the nature of the string instructions is such that this test
*        case will only validate properly for the string instruction
*        improvement modifications committed in December 2018.  The
*        computation of the CPU determined number of bytes is an
*        unpredictable number on real hardware (at least above the
*        minimum value) and the method used in Hercules prior to
*        instruction improvements calculated it differently than the
*        improved method.  As a result, the operand registers will
*        likely contain different values when compared by the test
*        script due to the different CPU number of bytes
*        determined.  None of the methods are wrong, and failing
*        results in the test script are not necessarily wrong.
*        But this program and the resulting test script comparisons
*        were written for the method used by the improved string
*        instructions (CLST, MVST, SRST).
*
*
***********************************************************************
*
*
*
MVST001  START 0
STRTLABL EQU   *
R0       EQU   0
R1       EQU   1
R2       EQU   2
R3       EQU   3
R4       EQU   4
R5       EQU   5
R6       EQU   6
R7       EQU   7
R8       EQU   8
R9       EQU   9
R10      EQU   10
R11      EQU   11                  **Reserved for z/CMS test rig
R12      EQU   12
R13      EQU   13
R14      EQU   14                  **Return address for z/CMS test rig
R15      EQU   15                  **Base register on z/CMS or Hyperion
*
*
         USING *,R15
*
* Selected z/Arch low core layout
*
         ORG   STRTLABL+X'8C'      Program check interrution code
PGMINTC  DS    F
*
PGMOPSW  EQU   STRTLABL+X'150'     z/Arch Program check old PSW
*
         ORG   STRTLABL+X'1A0'     z/Arch Restart PSW
         DC    X'0000000180000000',A(0,START)
*
         ORG   STRTLABL+X'1D0'     z/Arch Program check new PSW
PGMNPSW  DC    X'0000000180000000',A(0,PROGCHK)
*
* Program check routine.  We are looking for a single specification
* exeception.  Any other program check is not expected to occur and
* results in a hard wait.
*
         ORG   STRTLABL+X'200'
PROGCHK  DS    0H               Program check occured...
         CLI   DIDTHIS,X'00'    First/only time here?
         BNE   FAIL             No?! Then something is wrong!
         CLI   PGMINTC+3,X'06'  Specification Exception?
         BNE   FAIL             No?! Then something is wrong!
         MVI   DIDTHIS,X'FF'    Remember we did this once already
         B     CONTINUE         Continue, as this is expected (once!)
FAIL     LPSWE FAILPSW          Unexpected PIC, disabled wait
DIDTHIS  DC    X'00'            X'FF' == we already did this
         EJECT
***********************************************************************
*
*  Main program.
*
START    DS    0H
*
**********
* TEST 1 * Ensure any non-zero bits in R0 bits 32-55 gives PIC 06
**********
*
         LA    R0,X'400'               Set invalid termination char
         LA    R6,DEST1                -> destination field
         LA    R6,SHORT                -> source field
         MVST  R6,R7                   Attempt a move, should get PIC 6
*
CONTINUE EQU   *
         CLI   DIDTHIS,X'FF'           Did PIC 06 happen?
         BNE   FAIL                    No?! Then something is wrong!
         MVC   PGMNPSW,FAILPSW         All other p checks should halt
*
**********
* TEST 2 * Move a short string; no page boundary crossings
**********
*
         LA    R6,DEST2                -> destination field
         LA    R7,SHORT                -> source field
         BAS   R5,MOVE                 Move the string
         STM   R6,R8,RESULT2           Save test 2 result regs
*
**********
* TEST 3 * Move a single byte, which is the termination character
**********
*
         LA    R6,DEST3                -> destination field
         LA    R7,TERM                 -> String with only the term chr
         BAS   R5,MOVE                 Move the string
         STM   R6,R8,RESULT3           Save test 3 result regs
*
**********
* TEST 4 * Move a string; operand 1 (only) crosses a page boundary
**********
*
*-- First, generate a source string.  319 bytes, all FFs, + 1 $ char
*
         L     R2,ASOURCE4             -> source string area
         L     R3,ALEN4                -> get length we will build
         L     R5,PAD                  Get the pad char
         MVCL  R2,R4                   Fill the area with FFs
         BCTR  R2,0                    -> last byte filled
         MVI   0(R2),C'$'              Plug termination character
*
*-- Move the string to the destination area
*
         L     R6,ADEST4               -> destination field
         L     R7,ASOURCE4             -> String to be moved
         BAS   R5,MOVE                 Move the string
         STM   R6,R8,RESULT4           Save test 4 result regs
*
*-- Finally, verify source and destination match completely
*
         MVC   RESULT4+12(4),FFS       Initialize later result field
         L     R2,ASOURCE4             -> source string area
         L     R3,ALEN4                get length to validate
         L     R4,ADEST4               -> destination area
         LR    R5,R3                   Copy validation length
         CLCL  R2,R4                   Check if the strings match
         IPM   R0                      Get the condition code
         SRL   R0,28                   Adjust CC in register
         ST    R0,RESULT4+12           Put in 4th word of result
*
**********
* TEST 5 * Move a string; operand 2 (only) crosses a page boundary
**********
*
*-- First, generate a source string.  599 bytes, all FFs, + 1 $ char
*
         L     R2,ASOURCE5             -> source string area
         L     R3,ALEN5                -> get length we will build
         L     R5,PAD                  Get the pad char
         MVCL  R2,R4                   Fill the area with FFs
         BCTR  R2,0                    -> last byte filled
         MVI   0(R2),C'$'              Plug termination character
*
*-- Move the string to the destination area
*
         L     R6,ADEST5               -> destination field
         L     R7,ASOURCE5             -> String to be moved
         BAS   R5,MOVE                 Move the string
         STM   R6,R8,RESULT5           Save test 4 result regs
*
*-- Finally, verify source and destination match completely
*
         MVC   RESULT5+12(4),FFS       Initialize later result field
         L     R2,ASOURCE5             -> source string area
         L     R3,ALEN5                get length to validate
         L     R4,ADEST5               -> destination area
         LR    R5,R3                   Copy validation length
         CLCL  R2,R4                   Check if the strings match
         IPM   R0                      Get the condition code
         SRL   R0,28                   Adjust CC in register
         ST    R0,RESULT5+12           Put in 4th word of result
*
**********
* TEST 6 * Move a string; both operands cross page boundary, but
********** operand 1 is closer to the boundary than operand 2.
*
*-- First, generate a source string.  319 bytes, all FFs, + 1 $ char
*
         L     R2,ASOURCE6             -> source string area
         L     R3,ALEN6                -> get length we will build
         L     R5,PAD                  Get the pad char
         MVCL  R2,R4                   Fill the area with FFs
         BCTR  R2,0                    -> last byte filled
         MVI   0(R2),C'$'              Plug termination character
*
*-- Move the string to the destination area
*
         L     R6,ADEST6               -> destination field
         L     R7,ASOURCE6             -> String to be moved
         BAS   R5,MOVE                 Move the string
         STM   R6,R8,RESULT6           Save test 4 result regs
*
*-- Finally, verify source and destination match completely
*
         MVC   RESULT6+12(4),FFS       Initialize later result field
         L     R2,ASOURCE6             -> source string area
         L     R3,ALEN6                get length to validate
         L     R4,ADEST6               -> destination area
         LR    R5,R3                   Copy validation length
         CLCL  R2,R4                   Check if the strings match
         IPM   R0                      Get the condition code
         SRL   R0,28                   Adjust CC in register
         ST    R0,RESULT6+12           Put in 4th word of result
*
**********
* TEST 7 * Move a string; both operands cross page boundary, but
********** operand 2 is closer to the boundary than operand 1.
*
*-- First, generate a source string.  319 bytes, all FFs, + 1 $ char
*
         L     R2,ASOURCE7             -> source string area
         L     R3,ALEN7                -> get length we will build
         L     R5,PAD                  Get the pad char
         MVCL  R2,R4                   Fill the area with FFs
         BCTR  R2,0                    -> last byte filled
         MVI   0(R2),C'$'              Plug termination character
*
*-- Move the string to the destination area
*
         L     R6,ADEST7               -> destination field
         L     R7,ASOURCE7             -> String to be moved
         BAS   R5,MOVE                 Move the string
         STM   R6,R8,RESULT7           Save test 4 result regs
*
*-- Finally, verify source and destination match completely
*
         MVC   RESULT7+12(4),FFS       Initialize later result field
         L     R2,ASOURCE7             -> source string area
         L     R3,ALEN7                get length to validate
         L     R4,ADEST7               -> destination area
         LR    R5,R3                   Copy validation length
         CLCL  R2,R4                   Check if the strings match
         IPM   R0                      Get the condition code
         SRL   R0,28                   Adjust CC in register
         ST    R0,RESULT7+12           Put in 4th word of result
*
********** Move a string; both operands cross page boundary; both
* TEST 8 * operands are the same distance from a page boundary;
********** larger multipage move.
*
*-- First, generate a source string.  12599 bytes, all FFs, + 1 $ char
*
         L     R2,ASOURCE8             -> source string area
         L     R3,ALEN8                -> get length we will build
         L     R5,PAD                  Get the pad char
         MVCL  R2,R4                   Fill the area with FFs
         BCTR  R2,0                    -> last byte filled
         MVI   0(R2),C'$'              Plug termination character
*
*-- Move the string to the destination area
*
         L     R6,ADEST8               -> destination field
         L     R7,ASOURCE8             -> String to be moved
         BAS   R5,MOVE                 Move the string
         STM   R6,R8,RESULT8           Save test 4 result regs
*
*-- Finally, verify source and destination match completely
*
         MVC   RESULT8+12(4),FFS       Initialize later result field
         L     R2,ASOURCE8             -> source string area
         L     R3,ALEN8                get length to validate
         L     R4,ADEST8               -> destination area
         LR    R5,R3                   Copy validation length
         CLCL  R2,R4                   Check if the strings match
         IPM   R0                      Get the condition code
         SRL   R0,28                   Adjust CC in register
         ST    R0,RESULT8+12           Put in 4th word of result
*
**       Verify results...
*
         CLC   GDEST2,DEST2           Expected results?
         BNE   FAIL                   No?! Then something is wrong!
         CLC   GRESLT2,RESULT2        Expected results?
         BNE   FAIL                   No?! Then something is wrong!
         CLC   GDEST3,DEST3           Expected results?
         BNE   FAIL                   No?! Then something is wrong!
         CLC   GRESLT3,RESULT3        Expected results?
         BNE   FAIL                   No?! Then something is wrong!
         CLC   GRESLT4,RESULT4        Expected results?
         BNE   FAIL                   No?! Then something is wrong!
         CLC   GRESLT5,RESULT5        Expected results?
         BNE   FAIL                   No?! Then something is wrong!
         CLC   GRESLT6,RESULT6        Expected results?
         BNE   FAIL                   No?! Then something is wrong!
         CLC   GRESLT7,RESULT7        Expected results?
         BNE   FAIL                   No?! Then something is wrong!
         CLC   GRESLT8,RESULT8        Expected results?
         BNE   FAIL                   No?! Then something is wrong!
*
         LPSWE GOODPSW                load SUCCESS disabled wait PSW
*
*-- MVST routine used by tests
*
MOVE     EQU   *
         LA    R0,C'$'                 Load termination character
         SR    R8,R8                   Init MVST counter
*
INVOKE   EQU   *
         MVST  R6,R7                   Move the string
         LA    R8,1(,R8)               Count executions of MVST
         BC    1,INVOKE                Restart the move
         BCR   4,R5                    Complete if CC=1
*
         IPM   R0                      Load failing CC
         LPSWE BADCC                   Here if invalid CC encountered
*
         DS    0D             Ensure correct alignment for psw
GOODPSW  DC    X'0002000000000000',A(0,0) Normal end - disabled wait
FAILPSW  DC    X'0002000000000000',XL4'00',X'0000DEAD' Abnormal end
BADCC    DC    X'0002000000000000',XL4'00',X'000BADCC' Abnormal end
*
GDEST2   DC    XL16'E2C8D6D9E340E2E3D9C9D5C75B000000'
GRESLT2  DC    XL12'0000081C0000070000000001'
GDEST3   DC    XL4'5B000000'
GRESLT3  DC    XL12'000008300000071000000001'
GRESLT4  DC    XL16'0001204F000012F00000000200000000'
GRESLT5  DC    XL16'00013257000040000000000200000000'
GRESLT6  DC    XL16'0001611F000060000000000300000000'
GRESLT7  DC    XL16'000180CF000080300000000300000000'
GRESLT8  DC    XL16'0001C6F30000C0000000000400000000'
*
         ORG   STRTLABL+X'700'
SHORT    DC    CL16'SHORT STRING$   '  Used by test 1 and 2
TERM     DC    C'$'                    Used by test 3
FFS      DC    15X'FF'                 Program use
PAD      DC    X'FF000000'             MVCL/CLCL pad char
ASOURCE4 DC    X'00001200'   op2       -> source string area (test 4)
ADEST4   DC    X'00011F10'   op1       -> destination area (test 4)
ALEN4    DC    F'320'                  Build len source 4 (incl term)
ASOURCE5 DC    X'00003E02'   op2       -> source string area (test 5)
ADEST5   DC    X'00013000'   op1       -> destination area (test 5)
ALEN5    DC    F'600'                  Build len source 5 (incl term)
ASOURCE6 DC    X'00005F80'   op2       -> source string area (test 6)
ADEST6   DC    X'00015FE0'   op1       -> destination area (test 6)
ALEN6    DC    F'320'                  Build len source 6 (incl term)
ASOURCE7 DC    X'00007FC0'   op2       -> source string area (test 7)
ADEST7   DC    X'00017F90'   op1       -> destination area (test 7)
ALEN7    DC    F'320'                  Build len source 7 (incl term)
ASOURCE8 DC    X'00009620'   op2       -> source string area (test 8)
ADEST8   DC    X'00019620'   op1       -> destination area (test 8)
ALEN8    DC    F'12500'                Build len source 8 (incl term)
*
*  Locations for results
*
* Result fields are kept on 16-byte boundaries to more easily
* track their assembled offsets for use in the .tst script.
*
*                              offset
         ORG   STRTLABL+X'800'   8xx
DEST1    DS    CL16               00   Destination area test 1
DEST2    DS    CL16               10   Destination area test 2
RESULT2  DS    4F                 20   Register results test 2
DEST3    DS    CL16               30   Destination area test 3
RESULT3  DS    4F                 40   Register results test 3
RESULT4  DS    4F                 50   Register results test 4
RESULT5  DS    4F                 60   Register results test 5
RESULT6  DS    4F                 70   Register results test 6
RESULT7  DS    4F                 80   Register results test 7
RESULT8  DS    4F                 90   Register results test 8
*
         END
