Files
gottfriedleibniz d79382bbfe Run codespell on README, build, and source files. (#824)
* chore: run codespell on source/header files

Fixes most reported typos discovered by codespell (while trying to be
unopinionated about American vs. British English).

* chore: run codespell on build/readme files
2026-04-10 11:01:50 -07:00

8345 lines
255 KiB
C

/* ZVECTOR.C (C) Copyright Jan Jaeger, 1999-2012 */
/* (C) Copyright Roger Bowler, 1999-2012 */
/* z/Arch Vector Operations */
/* */
/* Released under "The Q Public License Version 1" */
/* (http://www.hercules-390.org/herclic.html) as modifications to */
/* Hercules. */
/* Interpretive Execution - (C) Copyright Jan Jaeger, 1999-2012 */
/* z/Architecture support - (C) Copyright Jan Jaeger, 1999-2012 */
#include "hstdinc.h"
#define _ZVECTOR_C_
#define _HENGINE_DLL_
#include "hercules.h"
#include "opcode.h"
#include "inline.h"
#include "zvector.h"
/* ====================================================================== */
/* ZVECTOR_END macro for debugging Vector instructions */
/* Note: block comments are used to avoid gcc */
/* warning: multi-line comment [-Wcomment] */
// To display the results of all Vector instructions, uncomment the
// following three lines:-
/*
#undef ZVECTOR_END
#define ZVECTOR_END(_regs) \
ARCH_DEP(display_inst) (_regs, inst);
*/
// To display the results of specific Vector instructions, uncomment
// and modify the following four lines:-
/*
#undef ZVECTOR_END
#define ZVECTOR_END(_regs) \
if (inst[5] == 0x3E || inst[5] == 0x36) \
ARCH_DEP(display_inst) (_regs, inst);
*/
/* ====================================================================== */
#if defined( FEATURE_129_ZVECTOR_FACILITY )
/*===================================================================*/
/* Architecture Independent Routines */
/*===================================================================*/
#if !defined(_ZVECTOR_ARCH_INDEPENDENT_)
#define _ZVECTOR_ARCH_INDEPENDENT_
/*-------------------------------------------------------------------*/
/* Vector-processing exception. */
/*-------------------------------------------------------------------*/
/* Create the VXC from the VIX and the VIC. */
/* Bits 0-3 of the VXC are the vector index (VIX). */
/* The VIX is the index of the source element that caused */
/* the trapping exception. If trapping conditions exist for */
/* multiple elements, the exception of the lowest-indexed */
/* source element is recognized. */
/* Bits 4-7 of the VXC are the vector interrupt code (VIC). */
/*-------------------------------------------------------------------*/
static void vector_processing_trap( REGS *regs, int vix, U32 vic )
{
U32 vxc;
vxc = ( vix << VXC_VIX_SHIFT ) | vic; /* Build VXC */
regs->dxc = vxc; /* Save VXC in PSA */
regs->fpc &= ~FPC_DXC; /* Clear DXC/VXC in FPC */
regs->fpc |= (vxc << FPC_DXC_SHIFT); /* Insert VXC into FPC */
regs->program_interrupt( regs, PGM_VECTOR_PROCESSING_EXCEPTION );
}
#endif /*!defined(_ZVECTOR_ARCH_INDEPENDENT_)*/
/*===================================================================*/
/* Architecture Dependent Routines / Instructions */
/*===================================================================*/
/*-------------------------------------------------------------------*/
/* E700 VLEB - Vector Load Element (8) [VRX] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_load_element_8 )
{
int v1, m3, x2, b2;
VADR effective_addr2;
VRX( inst, regs, v1, x2, b2, effective_addr2, m3 );
ZVECTOR_CHECK( regs );
PER_ZEROADDR_XCHECK2( regs, x2, b2 );
regs->VR_B( v1, m3 ) = ARCH_DEP( vfetchb )( effective_addr2, b2, regs );
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E701 VLEH - Vector Load Element (16) [VRX] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_load_element_16 )
{
int v1, m3, x2, b2;
VADR effective_addr2;
VRX( inst, regs, v1, x2, b2, effective_addr2, m3 );
ZVECTOR_CHECK( regs );
PER_ZEROADDR_XCHECK2( regs, x2, b2 );
if (m3 > 7) /* M3 > 7 => Specification excp */
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
regs->VR_H( v1, m3 ) = ARCH_DEP( vfetch2 )( effective_addr2, b2, regs );
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E702 VLEG - Vector Load Element (64) [VRX] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_load_element_64 )
{
int v1, m3, x2, b2;
VADR effective_addr2;
VRX( inst, regs, v1, x2, b2, effective_addr2, m3 );
ZVECTOR_CHECK( regs );
PER_ZEROADDR_XCHECK2( regs, x2, b2 );
if (m3 > 1) /* M3 > 1 => Specification excp */
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
regs->VR_D( v1, m3 ) = ARCH_DEP( vfetch8 )( effective_addr2, b2, regs );
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E703 VLEF - Vector Load Element (32) [VRX] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_load_element_32 )
{
int v1, m3, x2, b2;
VADR effective_addr2;
VRX( inst, regs, v1, x2, b2, effective_addr2, m3 );
ZVECTOR_CHECK( regs );
PER_ZEROADDR_XCHECK2( regs, x2, b2 );
if (m3 > 3) /* M3 > 3 => Specification excp */
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
regs->VR_F( v1, m3 ) = ARCH_DEP( vfetch4 )( effective_addr2, b2, regs );
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E704 VLLEZ - Vector Load Logical Element and Zero [VRX] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_load_logical_element_and_zero )
{
int v1, m3, x2, b2;
VADR effective_addr2;
VRX( inst, regs, v1, x2, b2, effective_addr2, m3 );
ZVECTOR_CHECK( regs );
PER_ZEROADDR_XCHECK2( regs, x2, b2 );
#if defined(_M_X64) || defined( __SSE2__ )
regs->VR_Q( v1 ).v = _mm_setzero_si128();
#else
regs->VR_D(v1, 0) = 0x00;
regs->VR_D(v1, 1) = 0x00;
#endif
switch (m3)
{
case 0: regs->VR_B( v1, 7 ) = ARCH_DEP( vfetchb )( effective_addr2, b2, regs ); break;
case 1: regs->VR_H( v1, 3 ) = ARCH_DEP( vfetch2 )( effective_addr2, b2, regs ); break;
case 2: regs->VR_F( v1, 1 ) = ARCH_DEP( vfetch4 )( effective_addr2, b2, regs ); break;
case 3: regs->VR_D( v1, 0 ) = ARCH_DEP( vfetch8 )( effective_addr2, b2, regs ); break;
case 6: regs->VR_F( v1, 0 ) = ARCH_DEP( vfetch4 )( effective_addr2, b2, regs ); break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E705 VLREP - Vector Load and Replicate [VRX] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_load_and_replicate )
{
int v1, m3, x2, b2, i;
VADR effective_addr2;
VRX( inst, regs, v1, x2, b2, effective_addr2, m3 );
ZVECTOR_CHECK( regs );
PER_ZEROADDR_XCHECK2( regs, x2, b2 );
switch (m3)
{
case 0:
regs->VR_B( v1, 0 ) = ARCH_DEP( vfetchb )( effective_addr2, b2, regs );
for (i=1; i < 16; i++)
regs->VR_B( v1, i ) = regs->VR_B( v1, 0 );
break;
case 1:
regs->VR_H( v1, 0 ) = ARCH_DEP( vfetch2 )( effective_addr2, b2, regs );
for (i=1; i < 8; i++)
regs->VR_H( v1, i ) = regs->VR_H( v1, 0 );
break;
case 2:
regs->VR_F( v1, 0 ) = ARCH_DEP( vfetch4 )( effective_addr2, b2, regs );
for (i=1; i < 4; i++)
regs->VR_F( v1, i ) = regs->VR_F( v1, 0 );
break;
case 3:
regs->VR_D( v1, 0 ) = ARCH_DEP( vfetch8 )( effective_addr2, b2, regs );
regs->VR_D( v1, 1 ) = regs->VR_D( v1, 0 );
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E706 VL - Vector Load [VRX] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_load )
{
int v1, m3, x2, b2;
VADR effective_addr2;
VRX( inst, regs, v1, x2, b2, effective_addr2, m3);
/* m3 - Alignment Hint: not used */
UNREFERENCED( m3 );
ZVECTOR_CHECK( regs );
PER_ZEROADDR_XCHECK2( regs, x2, b2 );
regs->VR_Q( v1 ) = ARCH_DEP( vfetch16 )( effective_addr2, b2, regs );
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E707 VLBB - Vector Load To Block Boundary [VRX] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_load_to_block_boundary )
{
int v1, m3, x2, b2;
VADR effective_addr2, boundary_addr;
U64 boundary;
U64 length;
QW temp;
VRX( inst, regs, v1, x2, b2, effective_addr2, m3 );
ZVECTOR_CHECK( regs );
PER_ZEROADDR_XCHECK2( regs, x2, b2 );
if (m3 > 6) /* M3 > 6 => Specification excp */
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
boundary = 64 << m3; /* 0: 64 Byte, 1: 128 Byte, 2: 256 Byte, 3: 512 Byte,
4: 1 K-byte, 5: 2 K-Byte, 6: 4 K-Byte */
boundary_addr = (effective_addr2 + boundary) & ~(boundary - 1);
length = boundary_addr - effective_addr2;
if (length > 16) length = 16;
length--;
memset(&temp, 0x00, sizeof(temp));
ARCH_DEP( vfetchc )( &temp, (U32)length, effective_addr2, b2, regs );
regs->VR_Q( v1 ) = CSWAP128( temp );
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E708 VSTEB - Vector Store Element (8) [VRX] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_store_element_8 )
{
int v1, m3, x2, b2;
VADR effective_addr2;
VRX( inst, regs, v1, x2, b2, effective_addr2, m3 );
ZVECTOR_CHECK( regs );
PER_ZEROADDR_XCHECK2( regs, x2, b2 );
ARCH_DEP( vstoreb )( regs->VR_B( v1, m3 ), effective_addr2, b2, regs );
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E709 VSTEH - Vector Store Element (16) [VRX] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_store_element_16 )
{
int v1, m3, x2, b2;
VADR effective_addr2;
VRX( inst, regs, v1, x2, b2, effective_addr2, m3 );
ZVECTOR_CHECK( regs );
PER_ZEROADDR_XCHECK2( regs, x2, b2 );
if (m3 > 7) /* M3 > 7 => Specification excp */
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
ARCH_DEP( vstore2 )( regs->VR_H( v1, m3 ), effective_addr2, b2, regs );
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E70A VSTEG - Vector Store Element (64) [VRX] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_store_element_64 )
{
int v1, m3, x2, b2;
VADR effective_addr2;
VRX( inst, regs, v1, x2, b2, effective_addr2, m3 );
ZVECTOR_CHECK( regs );
PER_ZEROADDR_XCHECK2( regs, x2, b2 );
if (m3 > 1) /* M3 > 1 => Specification excp */
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
ARCH_DEP( vstore8 )( regs->VR_D( v1, m3 ), effective_addr2, b2, regs );
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E70B VSTEF - Vector Store Element (32) [VRX] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_store_element_32 )
{
int v1, m3, x2, b2;
VADR effective_addr2;
VRX( inst, regs, v1, x2, b2, effective_addr2, m3 );
ZVECTOR_CHECK( regs );
PER_ZEROADDR_XCHECK2( regs, x2, b2 );
if (m3 > 3) /* M3 > 3 => Specification excp */
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
ARCH_DEP( vstore4 )( regs->VR_F( v1, m3 ), effective_addr2, b2, regs );
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E70E VST - Vector Store [VRX] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_store )
{
int v1, m3, x2, b2;
VADR effective_addr2;
VRX( inst, regs, v1, x2, b2, effective_addr2, m3 );
/* m3 - Alignment Hint: not used */
UNREFERENCED( m3 );
ZVECTOR_CHECK( regs );
PER_ZEROADDR_XCHECK2( regs, x2, b2 );
ARCH_DEP( vstore16 )( regs->VR_Q( v1 ), effective_addr2, b2, regs );
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E712 VGEG - Vector Gather Element (64) [VRV] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_gather_element_64 )
{
int v1, v2, b2, d2, m3;
VADR effective_addr2;
VRV( inst, regs, v1, v2, b2, d2, m3 );
ZVECTOR_CHECK( regs );
if (m3 > 1) /* M3 > 3 => Specification excp */
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
effective_addr2 = d2;
if (b2)
effective_addr2 += regs->GR( b2 );
effective_addr2 += regs->VR_D( v2, m3 );
effective_addr2 &= ADDRESS_MAXWRAP( regs );
PER_ZEROADDR_XCHECK( regs, b2 );
regs->VR_D( v1, m3 ) = ARCH_DEP( vfetch8 )( effective_addr2, b2, regs );
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E713 VGEF - Vector Gather Element (32) [VRV] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_gather_element_32 )
{
int v1, v2, b2, d2, m3;
VADR effective_addr2;
VRV( inst, regs, v1, v2, b2, d2, m3 );
ZVECTOR_CHECK( regs );
if (m3 > 3) /* M3 > 3 => Specification excp */
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
effective_addr2 = d2;
if (b2)
effective_addr2 += regs->GR( b2 );
effective_addr2 += regs->VR_F( v2, m3 );
effective_addr2 &= ADDRESS_MAXWRAP( regs );
PER_ZEROADDR_XCHECK( regs, b2 );
regs->VR_F( v1, m3 ) = ARCH_DEP( vfetch4 )( effective_addr2, b2, regs );
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E71A VSCEG - Vector Scatter Element (64) [VRV] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_scatter_element_64 )
{
int v1, v2, b2, d2, m3;
VADR effective_addr2;
VRV( inst, regs, v1, v2, b2, d2, m3 );
ZVECTOR_CHECK( regs );
if (m3 > 1) /* M3 > 3 => Specification excp */
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
effective_addr2 = d2;
if (b2)
effective_addr2 += regs->GR( b2 );
effective_addr2 += regs->VR_D( v2, m3 );
effective_addr2 &= ADDRESS_MAXWRAP( regs );
PER_ZEROADDR_XCHECK( regs, b2 );
ARCH_DEP( vstore8 )( regs->VR_D( v1, m3 ), effective_addr2, b2, regs );
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E71B VSCEF - Vector Scatter Element (32) [VRV] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_scatter_element_32 )
{
int v1, v2, b2, d2, m3;
VADR effective_addr2;
VRV( inst, regs, v1, v2, b2, d2, m3 );
ZVECTOR_CHECK( regs );
if (m3 > 3) /* M3 > 3 => Specification excp */
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
effective_addr2 = d2;
if (b2)
effective_addr2 += regs->GR( b2 );
effective_addr2 += regs->VR_F( v2, m3 );
effective_addr2 &= ADDRESS_MAXWRAP( regs );
PER_ZEROADDR_XCHECK( regs, b2 );
ARCH_DEP( vstore4 )( regs->VR_F( v1, m3 ), effective_addr2, b2, regs );
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E721 VLGV - Vector Load GR from VR Element [VRS-c] */
/*-------------------------------------------------------------------*/
/* */
/* In PoP (SA22-7832-13), for VLGV we can read: */
/* If the index specified by the second-operand address is */
/* greater than the highest numbered element in the third */
/* operand, of the specified element size, the result in the */
/* first operand is unpredictable. */
/* */
/* However, empirical evidence suggests that any index larger than */
/* the highest numbered element is treated as the modulo of the */
/* highest numbered element. This may be model dependant behaviour, */
/* but this implementation will follow a models (z15) behaviour. */
/* */
DEF_INST( vector_load_gr_from_vr_element )
{
int r1, v3, b2, m4;
VADR effective_addr2;
int i;
VRS_C( inst, regs, r1, v3, b2, effective_addr2, m4 );
ZVECTOR_CHECK( regs );
i = effective_addr2 & 0xFFF; // Isolate the element index
switch (m4)
{
case 0: /* Byte */
i %= 16;
regs->GR( r1 ) = regs->VR_B( v3, i );
break;
case 1: /* Halfword */
i %= 8;
regs->GR( r1 ) = regs->VR_H( v3, i );
break;
case 2: /* Word */
i %= 4;
regs->GR( r1 ) = regs->VR_F( v3, i );
break;
case 3: /* Doubleword */
i %= 2;
regs->GR( r1 ) = regs->VR_D( v3, i );
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E722 VLVG - Vector Load VR Element from GR [VRS-b] */
/*-------------------------------------------------------------------*/
/* */
/* In PoP (SA22-7832-13), for VLVG we can read: */
/* If the index, specified by the second-operand address, is */
/* greater than the highest numbered element in the first */
/* operand, of the specified element size, it is unpredictable */
/* which element, if any, is replaced. */
/* */
/* However, empirical evidence suggests that any index larger than */
/* the highest numbered element is treated as the modulo of the */
/* highest numbered element. This may be model dependant behaviour, */
/* but this implementation will follow a models (z15) behaviour. */
/* */
DEF_INST( vector_load_vr_element_from_gr )
{
int v1, r3, b2, m4;
VADR effective_addr2;
int i;
VRS_B( inst, regs, v1, r3, b2, effective_addr2, m4 );
ZVECTOR_CHECK( regs );
i = effective_addr2 & 0xFFF; // Isolate the element index
switch (m4)
{
case 0: /* Byte */
i %= 16;
regs->VR_B( v1, i ) = regs->GR_LHLCL( r3 );
break;
case 1: /* Halfword */
i %= 8;
regs->VR_H( v1, i ) = regs->GR_LHL ( r3 );
break;
case 2: /* Word */
i %= 4;
regs->VR_F( v1, i ) = regs->GR_L ( r3 );
break;
case 3: /* Doubleword */
i %= 2;
regs->VR_D( v1, i ) = regs->GR_G ( r3 );
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E727 LCBB - Load Count To Block Boundary [RXE] */
/*-------------------------------------------------------------------*/
DEF_INST( load_count_to_block_boundary )
{
int r1, x2, b2, m3;
VADR effective_addr2, boundary_addr;
U64 boundary;
U64 length;
RXE_M3( inst, regs, r1, x2, b2, effective_addr2, m3 );
PER_ZEROADDR_XCHECK2( regs, x2, b2 );
if (m3 > 6) /* M3 > 6 => Specification excp */
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
boundary = 64 << m3; /* 0: 64 Byte, 1: 128 Byte, 2: 256 Byte, 3: 512 Byte,
4: 1 K-byte, 5: 2 K-Byte, 6: 4 K-Byte */
boundary_addr = (effective_addr2 + boundary) & ~(boundary - 1);
length = boundary_addr - effective_addr2;
if (length > 16) length = 16;
regs->GR_L( r1 ) = (U32)length;
regs->psw.cc = (length == 16) ? 0 : 3;
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E730 VESL - Vector Element Shift Left [VRS-a] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_element_shift_left )
{
int v1, v3, b2, m4, shift, i;
VADR effective_addr2;
VRS_A( inst, regs, v1, v3, b2, effective_addr2, m4 );
ZVECTOR_CHECK( regs );
shift = effective_addr2 & 0xFFF; // Isolate number of bit positions
switch (m4)
{
case 0:
shift %= 8;
for (i=0; i < 16; i++)
regs->VR_B( v1, i ) = regs->VR_B( v3, i ) << shift;
break;
case 1:
shift %= 16;
for (i=0; i < 8; i++)
regs->VR_H( v1, i ) = regs->VR_H( v3, i ) << shift;
break;
case 2:
shift %= 32;
for (i=0; i < 4; i++)
regs->VR_F( v1, i ) = regs->VR_F( v3, i ) << shift;
break;
case 3:
shift %= 64;
for (i=0; i < 2; i++)
regs->VR_D( v1, i ) = regs->VR_D( v3, i ) << shift;
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E733 VERLL - Vector Element Rotate Left Logical [VRS-a] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_element_rotate_left_logical )
{
int v1, v3, b2, m4, i, rotl, rotr;
VADR effective_addr2;
VRS_A( inst, regs, v1, v3, b2, effective_addr2, m4 );
ZVECTOR_CHECK( regs );
rotl = effective_addr2 & 0xFFF; // Isolate number of bit positions
switch (m4)
{
case 0:
rotl %= 8;
rotr = -rotl & 7;
for (i=0; i < 16; i++)
regs->VR_B( v1, i ) = (regs->VR_B( v3, i ) << rotl) | (regs->VR_B( v3, i ) >> rotr);
break;
case 1:
rotl %= 16;
rotr = -rotl & 15;
for (i=0; i < 8; i++)
regs->VR_H( v1, i ) = (regs->VR_H( v3, i ) << rotl) | (regs->VR_H( v3, i ) >> rotr);
break;
case 2:
rotl %= 32;
rotr = -rotl & 31;
for (i=0; i < 4; i++)
regs->VR_F( v1, i ) = (regs->VR_F( v3, i ) << rotl) | (regs->VR_F( v3, i ) >> rotr);
break;
case 3:
rotl %= 64;
rotr = -rotl & 63;
for (i=0; i < 2; i++)
regs->VR_D( v1, i ) = (regs->VR_D( v3, i ) << rotl) | (regs->VR_D( v3, i ) >> rotr);
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E736 VLM - Vector Load Multiple [VRS-a] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_load_multiple )
{
int v1, v3, b2, m4, i;
VADR effective_addr2;
VRS_A( inst, regs, v1, v3, b2, effective_addr2, m4 );
/* m4 - Alignment Hint: not used */
UNREFERENCED( m4 );
ZVECTOR_CHECK( regs );
PER_ZEROADDR_XCHECK( regs, b2 );
if (v3 < v1 || (v3 - v1 + 1) > 16)
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
for (i=v1; i <= v3; i++)
{
regs->VR_Q( i ) = ARCH_DEP( vfetch16 )( effective_addr2, b2, regs );
effective_addr2 += 16;
effective_addr2 &= ADDRESS_MAXWRAP( regs );
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E737 VLL - Vector Load With Length [VRS-b] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_load_with_length )
{
int v1, r3, b2, m4;
VADR effective_addr2;
U32 length;
QW temp;
VRS_B( inst, regs, v1, r3, b2, effective_addr2, m4 );
/* m4 - Alignment Hint: not used */
UNREFERENCED( m4 );
ZVECTOR_CHECK( regs );
PER_ZEROADDR_XCHECK( regs, b2 );
length = regs->GR_L(r3);
if (length > 15) length = 15;
memset(&temp, 0x00, sizeof(temp));
ARCH_DEP( vfetchc )( &temp, length, effective_addr2, b2, regs );
regs->VR_Q( v1 ) = CSWAP128( temp );
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E738 VESRL - Vector Element Shift Right Logical [VRS-a] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_element_shift_right_logical )
{
int v1, v3, b2, m4, i, shift;
VADR effective_addr2;
VRS_A( inst, regs, v1, v3, b2, effective_addr2, m4 );
ZVECTOR_CHECK( regs );
shift = effective_addr2 & 0xFFF; // Isolate number of bit positions
switch (m4)
{
case 0:
shift %= 8;
for (i=0; i < 16; i++)
regs->VR_B( v1, i ) = regs->VR_B( v3, i ) >> shift;
break;
case 1:
shift %= 16;
for (i=0; i < 8; i++)
regs->VR_H( v1, i ) = regs->VR_H( v3, i ) >> shift;
break;
case 2:
shift %= 32;
for (i=0; i < 4; i++)
regs->VR_F( v1, i ) = regs->VR_F( v3, i ) >> shift;
break;
case 3:
shift %= 64;
for (i=0; i < 2; i++)
regs->VR_D( v1, i ) = regs->VR_D( v3, i ) >> shift;
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E73A VESRA - Vector Element Shift Right Arithmetic [VRS-a] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_element_shift_right_arithmetic )
{
int v1, v3, b2, m4, shift, i;
VADR effective_addr2;
VRS_A( inst, regs, v1, v3, b2, effective_addr2, m4 );
ZVECTOR_CHECK( regs );
shift = effective_addr2 & 0xFFF; // Isolate number of bit positions
switch (m4)
{
case 0:
shift %= 8;
for (i=0; i < 16; i++)
regs->VR_B( v1, i ) = (S8) regs->VR_B( v3, i ) >> shift;
break;
case 1:
shift %= 16;
for (i=0; i < 8; i++)
regs->VR_H( v1, i ) = (S16) regs->VR_H( v3, i ) >> shift;
break;
case 2:
shift %= 32;
for (i=0; i < 4; i++)
regs->VR_F( v1, i ) = (S32) regs->VR_F( v3, i ) >> shift;
break;
case 3:
shift %= 64;
for (i=0; i < 2; i++)
regs->VR_D( v1, i ) = (S64) regs->VR_D( v3, i ) >> shift;
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E73E VSTM - Vector Store Multiple [VRS-a] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_store_multiple )
{
int v1, v3, b2, m4, i;
VADR effective_addr2;
VRS_A( inst, regs, v1, v3, b2, effective_addr2, m4 );
/* m4 - Alignment Hint: not used */
UNREFERENCED( m4 );
ZVECTOR_CHECK( regs );
PER_ZEROADDR_XCHECK( regs, b2 );
if (v3 < v1 || (v3 - v1 + 1) > 16)
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
for (i = v1; i <= v3; i++)
{
ARCH_DEP( vstore16 )( regs->VR_Q( i ), effective_addr2, b2, regs );
effective_addr2 += 16;
effective_addr2 &= ADDRESS_MAXWRAP( regs );
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E73F VSTL - Vector Store With Length [VRS-b] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_store_with_length )
{
int v1, r3, b2, m4;
VADR effective_addr2;
U32 length;
QW temp;
VRS_B( inst, regs, v1, r3, b2, effective_addr2, m4 );
/* m4 is not part of this instruction */
UNREFERENCED( m4 );
ZVECTOR_CHECK( regs );
PER_ZEROADDR_XCHECK( regs, b2 );
length = regs->GR_L(r3);
if (length > 15) length = 15;
temp = CSWAP128( regs->VR_Q( v1 ) );
ARCH_DEP( vstorec )( &temp, length , effective_addr2, b2, regs );
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E740 VLEIB - Vector Load Element Immediate (8) [VRI-a] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_load_element_immediate_8 )
{
int v1, i2, m3;
VRI_A( inst, regs, v1, i2, m3 );
ZVECTOR_CHECK( regs );
if (m3 > 15)
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
regs->VR_B(v1,m3) = i2 & 0xff;
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E741 VLEIH - Vector Load Element Immediate (16) [VRI-a] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_load_element_immediate_16 )
{
int v1, i2, m3;
VRI_A( inst, regs, v1, i2, m3 );
ZVECTOR_CHECK( regs );
if (m3 > 7)
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
regs->VR_H(v1, m3) = i2;
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E742 VLEIG - Vector Load Element Immediate (64) [VRI-a] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_load_element_immediate_64 )
{
int v1, i2, m3;
VRI_A( inst, regs, v1, i2, m3 );
ZVECTOR_CHECK( regs );
if (m3 > 1)
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
if (i2 & 0x8000)
i2 |= 0xFFFF0000;
regs->VR_D(v1, m3) = (S64) i2;
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E743 VLEIF - Vector Load Element Immediate (32) [VRI-a] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_load_element_immediate_32 )
{
int v1, i2, m3;
VRI_A( inst, regs, v1, i2, m3 );
ZVECTOR_CHECK( regs );
if (m3 > 3)
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
if (i2 & 0x8000)
i2 |= 0xFFFF0000;
regs->VR_F(v1, m3) = i2;
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E744 VGBM - Vector Generate Byte Mask [VRI-a] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_generate_byte_mask )
{
int v1, i2, m3, i;
VRI_A( inst, regs, v1, i2, m3 );
/* m3 is not part of this instruction */
UNREFERENCED( m3 );
ZVECTOR_CHECK( regs );
for (i=0; i < 16; i++)
regs->VR_B(v1, i) = (i2 & (0x1 << (15 - i))) ? 0xff : 0x00;
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E745 VREPI - Vector Replicate Immediate [VRI-a] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_replicate_immediate )
{
int v1, i2, m3, i;
VRI_A( inst, regs, v1, i2, m3 );
ZVECTOR_CHECK( regs );
if (i2 & 0x8000)
i2 |= 0xFFFF0000;
switch (m3)
{
case 0:
for (i=0; i < 16; i++)
regs->VR_B(v1, i) = (S8) i2;
break;
case 1:
for (i=0; i < 8; i++)
regs->VR_H(v1, i) = (S16) i2;
break;
case 2:
for (i=0; i < 4; i++)
regs->VR_F(v1, i) = (S32) i2;
break;
case 3:
for (i=0; i < 2; i++)
regs->VR_D(v1, i) = (S64) i2;
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E746 VGM - Vector Generate Mask [VRI-b] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_generate_mask )
{
int v1, i2, i3, m4, i;
U64 bitmask;
VRI_B( inst, regs, v1, i2, i3, m4 );
ZVECTOR_CHECK( regs );
switch (m4)
{
case 0:
i2 &= 7;
i3 &= 7;
if (i2 <= i3) {
if (i2 == 0)
bitmask = 0u - (1u << (7 - i3));
else
bitmask = (1u << (8 - i2)) - (1u << (7 - i3));
} else {
if (i2 == 0)
bitmask = 0xFFu - (1u << (7 - i3));
else
bitmask = 0xFFu - (1u << (7 - i3)) + (1u << (8 - i2));
}
for (i=0; i < 16; i++)
regs->VR_B(v1, i) = bitmask;
break;
case 1:
i2 &= 15;
i3 &= 15;
if (i2 <= i3) {
if (i2 == 0)
bitmask = 0u - (1u << (15 - i3));
else
bitmask = (1u << (16 - i2)) - (1u << (15 - i3));
} else {
if (i2 == 0)
bitmask = 0xFFFFu - (1u << (15 - i3));
else
bitmask = 0xFFFFu - (1u << (15 - i3)) + (1u << (16 - i2));
}
for (i=0; i < 8; i++)
regs->VR_H(v1, i) = bitmask;
break;
case 2:
i2 &= 31;
i3 &= 31;
if (i2 <= i3) {
if (i2 == 0)
bitmask = 0u - (1u << (31 - i3));
else
bitmask = (1u << (32 - i2)) - (1u << (31 - i3));
} else {
if (i2 == 0)
bitmask = 0xFFFFFFFFu - (1u << (31 - i3));
else
bitmask = 0xFFFFFFFFu - (1u << (31 - i3)) + (1u << (32 - i2));
}
for (i=0; i < 4; i++)
regs->VR_F(v1, i) = bitmask;
break;
case 3:
i2 &= 63;
i3 &= 63;
if (i2 <= i3) {
if (i2 == 0)
bitmask = 0ull - (1ull << (63 - i3));
else
bitmask = (1ull << (64 - i2)) - (1ull << (63 - i3));
} else {
if (i2 == 0)
bitmask = 0xFFFFFFFFFFFFFFFFull - (1ull << (63 - i3));
else
bitmask = 0xFFFFFFFFFFFFFFFFull - (1ull << (63 - i3)) + (1ull << (64 - i2));
}
for (i=0; i < 2; i++)
regs->VR_D(v1, i) = bitmask;
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E74D VREP - Vector Replicate [VRI-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_replicate )
{
int v1, v3, i2, m4, i;
VRI_C( inst, regs, v1, v3, i2, m4 );
ZVECTOR_CHECK( regs );
if (i2 >= (16 >> m4))
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m4)
{
case 0:
for (i=0; i < 16; i++)
regs->VR_B(v1, i) = regs->VR_B(v3, i2);
break;
case 1:
for (i=0; i < 8; i++)
regs->VR_H(v1, i) = regs->VR_H(v3, i2);
break;
case 2:
for (i=0; i < 4; i++)
regs->VR_F(v1, i) = regs->VR_F(v3, i2);
break;
case 3:
for (i=0; i < 2; i++)
regs->VR_D(v1, i) = regs->VR_D(v3, i2);
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E750 VPOPCT - Vector Population Count [VRR-a] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_population_count )
{
static const BYTE OneBitsInByte[256] =
/* -0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -A -B -C -D -E -F */
/* 0- */ { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
/* 1- */ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
/* 2- */ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
/* 3- */ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
/* 4- */ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
/* 5- */ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
/* 6- */ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
/* 7- */ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
/* 8- */ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
/* 9- */ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
/* A- */ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
/* B- */ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
/* C- */ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
/* D- */ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
/* E- */ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
/* F- */ 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 };
int v1, v2, m3, m4, m5;
int i, j, count;
VRR_A( inst, regs, v1, v2, m3, m4, m5 );
/* m4, m5 are not part of this instruction */
UNREFERENCED( m4 );
UNREFERENCED( m5 );
ZVECTOR_CHECK( regs );
if ( !FACILITY_ENABLED( 135_ZVECTOR_ENH_1, regs ) )
{
if ( m3 > 1 )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
}
switch (m3)
{
case 0: /* Byte */
for (i=0; i < 16; i++)
{
count = OneBitsInByte[regs->VR_B(v2, i)];
regs->VR_B(v1, i) = count;
}
break;
case 1: /* Halfword */
for (i=0; i < 8; i++)
{
count = 0;
for (j=i*2; j < (i*2)+2; j++)
{
count += OneBitsInByte[regs->VR_B(v2, j)];
}
regs->VR_H(v1, i) = count;
}
break;
case 2: /* Word */
for (i=0; i < 4; i++)
{
count = 0;
for (j=i*4; j < (i*4)+4; j++)
{
count += OneBitsInByte[regs->VR_B(v2, j)];
}
regs->VR_F(v1, i) = count;
}
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++)
{
count = 0;
for (j=i*8; j < (i*8)+8; j++)
{
count += OneBitsInByte[regs->VR_B(v2, j)];
}
regs->VR_D(v1, i) = count;
}
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E752 VCTZ - Vector Count Trailing Zeros [VRR-a] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_count_trailing_zeros )
{
static const BYTE TrailingZerosInByte[256] =
/* -0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -A -B -C -D -E -F */
/* 0- */ { 8, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
/* 1- */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
/* 2- */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
/* 3- */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
/* 4- */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
/* 5- */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
/* 6- */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
/* 7- */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
/* 8- */ 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
/* 9- */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
/* A- */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
/* B- */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
/* C- */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
/* D- */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
/* E- */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
/* F- */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 };
int v1, v2, m3, m4, m5;
int i, j, k, count;
VRR_A( inst, regs, v1, v2, m3, m4, m5 );
/* m4, m5 are not part of this instruction */
UNREFERENCED( m4 );
UNREFERENCED( m5 );
ZVECTOR_CHECK( regs );
if ( m3 == 4 && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m3)
{
case 0: /* Byte */
for (i=0; i < 16; i++)
{
count = TrailingZerosInByte[regs->VR_B(v2, i)];
regs->VR_B(v1, i) = count;
}
break;
case 1: /* Halfword */
for (i=0; i < 8; i++)
{
count = 0;
for (j=(i*2)+1; j >= i*2; j--)
{
k = TrailingZerosInByte[regs->VR_B(v2, j)];
count += k;
if (k != 8) break;
}
regs->VR_H(v1, i) = count;
}
break;
case 2: /* Word */
for (i=0; i < 4; i++)
{
count = 0;
for (j=(i*4)+3; j >= i*4; j--)
{
k = TrailingZerosInByte[regs->VR_B(v2, j)];
count += k;
if (k != 8) break;
}
regs->VR_F(v1, i) = count;
}
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++)
{
count = 0;
for (j=(i*8)+7; j >= i*8; j--)
{
k = TrailingZerosInByte[regs->VR_B(v2, j)];
count += k;
if (k != 8) break;
}
regs->VR_D(v1, i) = count;
}
break;
case 4: /* Quadword */
count = 0;
for (j=15; j >= 0; j--)
{
k = TrailingZerosInByte[regs->VR_B(v2, j)];
count += k;
if (k != 8) break;
}
regs->VR_D(v1, 0) = 0;
regs->VR_D(v1, 1) = count;
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E753 VCLZ - Vector Count Leading Zeros [VRR-a] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_count_leading_zeros )
{
static const BYTE LeadingZerosInByte[256] =
/* -0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -A -B -C -D -E -F */
/* 0- */ { 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
/* 1- */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
/* 2- */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* 3- */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* 4- */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* 5- */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* 6- */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* 7- */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* 8- */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 9- */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* A- */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* B- */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* C- */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* D- */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* E- */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* F- */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int v1, v2, m3, m4, m5;
int i, j, k, count;
VRR_A( inst, regs, v1, v2, m3, m4, m5 );
/* m4, m5 are not part of this instruction */
UNREFERENCED( m4 );
UNREFERENCED( m5 );
ZVECTOR_CHECK( regs );
if ( m3 == 4 && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m3)
{
case 0: /* Byte */
for (i=0; i < 16; i++)
{
count = LeadingZerosInByte[regs->VR_B(v2, i)];
regs->VR_B(v1, i) = count;
}
break;
case 1: /* Halfword */
for (i=0; i < 8; i++)
{
count = 0;
for (j=i*2; j < (i*2)+2; j++)
{
k = LeadingZerosInByte[regs->VR_B(v2, j)];
count += k;
if (k != 8) break;
}
regs->VR_H(v1, i) = count;
}
break;
case 2: /* Word */
for (i=0; i < 4; i++)
{
count = 0;
for (j=i*4; j < (i*4)+4; j++)
{
k = LeadingZerosInByte[regs->VR_B(v2, j)];
count += k;
if (k != 8) break;
}
regs->VR_F(v1, i) = count;
}
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++)
{
count = 0;
for (j=i*8; j < (i*8)+8; j++)
{
k = LeadingZerosInByte[regs->VR_B(v2, j)];
count += k;
if (k != 8) break;
}
regs->VR_D(v1, i) = count;
}
break;
case 4: /* Quadword */
count = 0;
for (j=0; j < 16; j++)
{
k = LeadingZerosInByte[regs->VR_B(v2, j)];
count += k;
if (k != 8) break;
}
regs->VR_D(v1, 0) = 0;
regs->VR_D(v1, 1) = count;
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
#if defined( FEATURE_198_VECTOR_ENH_FACILITY_3 )
/*-------------------------------------------------------------------*/
/* E754 VGEM - Vector Generate Element Masks [VRR-a] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_generate_element_masks )
{
int v1, v2, m3, m4, m5;
int i;
U32 mask;
VRR_A( inst, regs, v1, v2, m3, m4, m5 );
/* m4, m5 are not part of this instruction */
UNREFERENCED( m4 );
UNREFERENCED( m5 );
ZVECTOR_CHECK( regs );
mask = regs->VR_F(v2, 0);
switch (m3)
{
case 0: /* Byte */
for (i=0; i < 16; i++)
{
if (mask & 0x80000000)
regs->VR_B(v1, i) = 0xFF;
else
regs->VR_B(v1, i) = 0x00;
mask <<= 1;
}
break;
case 1: /* Halfword */
for (i=0; i < 8; i++)
{
if (mask & 0x80000000)
regs->VR_H(v1, i) = 0xFFFF;
else
regs->VR_H(v1, i) = 0x0000;
mask <<= 1;
}
break;
case 2: /* Word */
for (i=0; i < 4; i++)
{
if (mask & 0x80000000)
regs->VR_F(v1, i) = 0xFFFFFFFF;
else
regs->VR_F(v1, i) = 0x00000000;
mask <<= 1;
}
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++)
{
if (mask & 0x80000000)
regs->VR_D(v1, i) = 0xFFFFFFFFFFFFFFFFull;
else
regs->VR_D(v1, i) = 0x0000000000000000ull;
mask <<= 1;
}
break;
case 4: /* Quadword */
if (mask & 0x80000000)
{
regs->VR_D(v1, 0) = 0xFFFFFFFFFFFFFFFFull;
regs->VR_D(v1, 1) = 0xFFFFFFFFFFFFFFFFull;
}
else
{
regs->VR_D(v1, 0) = 0x0000000000000000ull;
regs->VR_D(v1, 1) = 0x0000000000000000ull;
}
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
#endif /* defined( FEATURE_198_VECTOR_ENH_FACILITY_3 ) */
/*-------------------------------------------------------------------*/
/* E756 VLR - Vector Load Vector [VRR-a] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_load_vector )
{
int v1, v2, m3, m4, m5;
VRR_A( inst, regs, v1, v2, m3, m4, m5 );
/* m3, m4, m5 are not part of this instruction */
UNREFERENCED( m3 );
UNREFERENCED( m4 );
UNREFERENCED( m5 );
ZVECTOR_CHECK( regs );
regs->VR_Q( v1 ) = regs->VR_Q( v2 );
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E75C VISTR - Vector Isolate String [VRR-a] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_isolate_string )
{
int v1, v2, m3, m4, m5;
int i;
BYTE newcc = 3;
VRR_A( inst, regs, v1, v2, m3, m4, m5 );
/* m4 is not part of this instruction */
UNREFERENCED( m4 );
ZVECTOR_CHECK( regs );
#define M5_CS ((m5 & 0x1) != 0) // Condition Code Set
switch (m3)
{
case 0: /* Byte */
for (i=0; i < 16; i++)
{
if (regs->VR_B(v2, i) != 0)
{
regs->VR_B(v1, i) = regs->VR_B(v2, i);
}
else
{
newcc = 0;
for (; i < 16; i++)
{
regs->VR_B(v1, i) = 0;
}
break;
}
}
break;
case 1: /* Halfword */
for (i=0; i < 8; i++)
{
if (regs->VR_H(v2, i) != 0)
{
regs->VR_H(v1, i) = regs->VR_H(v2, i);
}
else
{
newcc = 0;
for (; i < 8; i++)
{
regs->VR_H(v1, i) = 0;
}
break;
}
}
break;
case 2: /* Word */
for (i=0; i < 4; i++)
{
if (regs->VR_F(v2, i) != 0)
{
regs->VR_F(v1, i) = regs->VR_F(v2, i);
}
else
{
newcc = 0;
for (; i < 4; i++)
{
regs->VR_F(v1, i) = 0;
}
break;
}
}
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
if (M5_CS) // if M5_CS (Condition Code Set)
regs->psw.cc = newcc;
#undef M5_CS
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E75F VSEG - Vector Sign Extend To Doubleword [VRR-a] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_sign_extend_to_doubleword )
{
int v1, v2, m3, m4, m5;
U64 element;
VRR_A( inst, regs, v1, v2, m3, m4, m5 );
/* m4, m5 are not part of this instruction */
UNREFERENCED( m4 );
UNREFERENCED( m5 );
ZVECTOR_CHECK( regs );
switch (m3)
{
case 0: /* Byte */
element = regs->VR_B(v2, 7);
if (element & 0x0000000000000080ull)
element |= 0xFFFFFFFFFFFFFF00ull;
regs->VR_D(v1, 0) = element;
element = regs->VR_B(v2, 15);
if (element & 0x0000000000000080ull)
element |= 0xFFFFFFFFFFFFFF00ull;
regs->VR_D(v1, 1) = element;
break;
case 1: /* Halfword */
element = regs->VR_H(v2, 3);
if (element & 0x0000000000008000ull)
element |= 0xFFFFFFFFFFFF0000ull;
regs->VR_D(v1, 0) = element;
element = regs->VR_H(v2, 7);
if (element & 0x0000000000008000ull)
element |= 0xFFFFFFFFFFFF0000ull;
regs->VR_D(v1, 1) = element;
break;
case 2: /* Word */
element = regs->VR_F(v2, 1);
if (element & 0x0000000080000000ull)
element |= 0xFFFFFFFF00000000ull;
regs->VR_D(v1, 0) = element;
element = regs->VR_F(v2, 3);
if (element & 0x0000000080000000ull)
element |= 0xFFFFFFFF00000000ull;
regs->VR_D(v1, 1) = element;
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E760 VMRL - Vector Merge Low [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_merge_low )
{
int v1, v2, v3, m4, m5, m6;
int i, j;
SV temp;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m5, m6 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
switch (m4)
{
case 0: /* Byte */
for ( i=0, j=8; i<16; i+=2, j++ )
{
SV_B( temp, i ) = regs->VR_B( v2, j );
SV_B( temp, i+1 ) = regs->VR_B( v3, j );
}
break;
case 1: /* Halfword */
for ( i=0, j=4; i<8; i+=2, j++ )
{
SV_H( temp, i ) = regs->VR_H( v2, j );
SV_H( temp, i+1 ) = regs->VR_H( v3, j );
}
break;
case 2: /* Word */
for ( i=0, j=2; i<4; i+=2, j++ )
{
SV_F( temp, i ) = regs->VR_F( v2, j );
SV_F( temp, i+1 ) = regs->VR_F( v3, j );
}
break;
case 3: /* Doubleword */
SV_D( temp, 0 ) = regs->VR_D( v2, 1 );
SV_D( temp, 1 ) = regs->VR_D( v3, 1 );
break;
default:
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
break;
}
regs->VR_D( v1, 0 ) = SV_D( temp, 0 );
regs->VR_D( v1, 1 ) = SV_D( temp, 1 );
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E761 VMRH - Vector Merge High [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_merge_high )
{
int v1, v2, v3, m4, m5, m6;
int i, j;
SV temp;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m5, m6 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
switch (m4)
{
case 0: /* Byte */
for ( i=0, j=0; i<16; i+=2, j++ )
{
SV_B( temp, i ) = regs->VR_B( v2, j );
SV_B( temp, i+1 ) = regs->VR_B( v3, j );
}
break;
case 1: /* Halfword */
for ( i=0, j=0; i<8; i+=2, j++ )
{
SV_H( temp, i ) = regs->VR_H( v2, j );
SV_H( temp, i+1 ) = regs->VR_H( v3, j );
}
break;
case 2: /* Word */
for ( i=0, j=0; i<4; i+=2, j++ )
{
SV_F( temp, i ) = regs->VR_F( v2, j );
SV_F( temp, i+1 ) = regs->VR_F( v3, j );
}
break;
case 3: /* Doubleword */
SV_D( temp, 0 ) = regs->VR_D( v2, 0 );
SV_D( temp, 1 ) = regs->VR_D( v3, 0 );
break;
default:
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
break;
}
regs->VR_D( v1, 0 ) = SV_D( temp, 0 );
regs->VR_D( v1, 1 ) = SV_D( temp, 1 );
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E762 VLVGP - Vector Load VR from GRs Disjoint [VRR-f] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_load_vr_from_grs_disjoint )
{
int v1, r2, r3;
VRR_F( inst, regs, v1, r2, r3 );
ZVECTOR_CHECK( regs );
regs->VR_D(v1, 0) = regs->GR(r2);
regs->VR_D(v1, 1) = regs->GR(r3);
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E764 VSUM - Vector Sum Across Word [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_sum_across_word )
{
int v1, v2, v3, m4, m5, m6;
int i, j;
U32 sum[4];
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m5, m6 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
switch (m4)
{
case 0: /* Byte */
for (i = 0, j = 0; i < 4; i++, j+=4)
{
sum[i] = 0;
sum[i] += regs->VR_B(v2, j+0);
sum[i] += regs->VR_B(v2, j+1);
sum[i] += regs->VR_B(v2, j+2);
sum[i] += regs->VR_B(v2, j+3);
sum[i] += regs->VR_B(v3, j+3);
}
break;
case 1: /* Halfword */
for (i = 0, j = 0; i < 4; i++, j+=2)
{
sum[i] = 0;
sum[i] += regs->VR_H(v2, j+0);
sum[i] += regs->VR_H(v2, j+1);
sum[i] += regs->VR_H(v3, j+1);
}
break;
default:
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
break;
}
regs->VR_F(v1, 0) = sum[0];
regs->VR_F(v1, 1) = sum[1];
regs->VR_F(v1, 2) = sum[2];
regs->VR_F(v1, 3) = sum[3];
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E765 VSUMG - Vector Sum Across Doubleword [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_sum_across_doubleword )
{
int v1, v2, v3, m4, m5, m6;
int i, j;
U64 sum[2];
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m5, m6 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
switch (m4)
{
case 1: /* Halfword */
for (i = 0, j = 0; i < 2; i++, j+=4)
{
sum[i] = 0;
sum[i] += regs->VR_H(v2, j+0);
sum[i] += regs->VR_H(v2, j+1);
sum[i] += regs->VR_H(v2, j+2);
sum[i] += regs->VR_H(v2, j+3);
sum[i] += regs->VR_H(v3, j+3);
}
break;
case 2: /* Word */
for (i = 0, j = 0; i < 2; i++, j+=2)
{
sum[i] = 0;
sum[i] += regs->VR_F(v2, j+0);
sum[i] += regs->VR_F(v2, j+1);
sum[i] += regs->VR_F(v3, j+1);
}
break;
default:
/* remove initialization warning */
sum[0] = 0;
sum[1] = 0;
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
break;
}
regs->VR_D(v1, 0) = sum[0];
regs->VR_D(v1, 1) = sum[1];
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E766 VCKSM - Vector Checksum [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_checksum )
{
int v1, v2, v3, m4, m5, m6;
U64 ksum;
U32 carry[2];
int i;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m4, m5, m6 are not part of this instruction */
UNREFERENCED( m4 );
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
ksum = 0;
carry[0] = carry[1] = 0;
for (i = 0; i < 4; i++)
{
ksum += regs->VR_F(v2, i);
carry[1] = ksum >> 32;
if (carry[0] != carry[1])
ksum += 1;
carry[0] = carry[1];
}
ksum += regs->VR_F(v3, 1);
carry[1] = ksum >> 32;
if (carry[0] != carry[1])
ksum += 1;
regs->VR_F(v1, 0) = 0;
regs->VR_F(v1, 1) = ksum;
regs->VR_D(v1, 1) = 0;
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E767 VSUMQ - Vector Sum Across Quadword [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_sum_across_quadword )
{
int v1, v2, v3, m4, m5, m6;
U64 high, low, add;
int i;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m5, m6 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
high = low = add = 0;
switch (m4)
{
case 2: /* Word */
for (i = 0; i < 4; i++)
{
add += regs->VR_F(v2, i);
}
add += regs->VR_F(v3, 3);
break;
case 3: /* Doubleword */
low = regs->VR_D(v2, 0);
add = low + regs->VR_D(v2, 1);
if (add < low) high++;
low = add;
add = low + regs->VR_D(v3, 1);
if (add < low) high++;
break;
default:
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
break;
}
regs->VR_D(v1, 0) = high;
regs->VR_D(v1, 1) = add;
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E768 VN - Vector AND [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_and )
{
int v1, v2, v3, m4, m5, m6;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m4, m5, m6 are not part of this instruction */
UNREFERENCED( m4 );
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
regs->VR_D(v1, 0) = regs->VR_D(v2, 0) & regs->VR_D(v3, 0);
regs->VR_D(v1, 1) = regs->VR_D(v2, 1) & regs->VR_D(v3, 1);
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E769 VNC - Vector AND with Complement [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_and_with_complement )
{
int v1, v2, v3, m4, m5, m6;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m4, m5, m6 are not part of this instruction */
UNREFERENCED( m4 );
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
regs->VR_D(v1, 0) = regs->VR_D(v2, 0) & ~regs->VR_D(v3, 0);
regs->VR_D(v1, 1) = regs->VR_D(v2, 1) & ~regs->VR_D(v3, 1);
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E76A VO - Vector OR [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_or )
{
int v1, v2, v3, m4, m5, m6;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m4, m5, m6 are not part of this instruction */
UNREFERENCED( m4 );
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
regs->VR_D(v1, 0) = regs->VR_D(v2, 0) | regs->VR_D(v3, 0);
regs->VR_D(v1, 1) = regs->VR_D(v2, 1) | regs->VR_D(v3, 1);
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E76B VNO - Vector NOR [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_nor )
{
int v1, v2, v3, m4, m5, m6;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m4, m5, m6 are not part of this instruction */
UNREFERENCED( m4 );
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
regs->VR_D(v1, 0) = ~(regs->VR_D(v2, 0) | regs->VR_D(v3, 0));
regs->VR_D(v1, 1) = ~(regs->VR_D(v2, 1) | regs->VR_D(v3, 1));
ZVECTOR_END( regs );
}
#if defined( FEATURE_135_ZVECTOR_ENH_FACILITY_1 )
/*-------------------------------------------------------------------*/
/* E76C VNX - Vector Not Exclusive OR [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_not_exclusive_or )
{
int v1, v2, v3, m4, m5, m6;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m4, m5, m6 are not part of this instruction */
UNREFERENCED( m4 );
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
regs->VR_D(v1, 0) = ~(regs->VR_D(v2, 0) ^ regs->VR_D(v3, 0));
regs->VR_D(v1, 1) = ~(regs->VR_D(v2, 1) ^ regs->VR_D(v3, 1));
ZVECTOR_END( regs );
}
#endif /* defined( FEATURE_135_ZVECTOR_ENH_FACILITY_1 ) */
/*-------------------------------------------------------------------*/
/* E76D VX - Vector Exclusive OR [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_exclusive_or )
{
int v1, v2, v3, m4, m5, m6;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m4, m5, m6 are not part of this instruction */
UNREFERENCED( m4 );
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
regs->VR_D(v1, 0) = regs->VR_D(v2, 0) ^ regs->VR_D(v3, 0);
regs->VR_D(v1, 1) = regs->VR_D(v2, 1) ^ regs->VR_D(v3, 1);
ZVECTOR_END( regs );
}
#if defined( FEATURE_135_ZVECTOR_ENH_FACILITY_1 )
/*-------------------------------------------------------------------*/
/* E76E VNN - Vector NAND [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_nand )
{
int v1, v2, v3, m4, m5, m6;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m4, m5, m6 are not part of this instruction */
UNREFERENCED( m4 );
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
regs->VR_D(v1, 0) = ~(regs->VR_D(v2, 0) & regs->VR_D(v3, 0));
regs->VR_D(v1, 1) = ~(regs->VR_D(v2, 1) & regs->VR_D(v3, 1));
ZVECTOR_END( regs );
}
#endif /* defined( FEATURE_135_ZVECTOR_ENH_FACILITY_1 ) */
#if defined( FEATURE_135_ZVECTOR_ENH_FACILITY_1 )
/*-------------------------------------------------------------------*/
/* E76F VOC - Vector OR with Complement [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_or_with_complement )
{
int v1, v2, v3, m4, m5, m6;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m4, m5, m6 are not part of this instruction */
UNREFERENCED( m4 );
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
regs->VR_D(v1, 0) = regs->VR_D(v2, 0) | ~regs->VR_D(v3, 0);
regs->VR_D(v1, 1) = regs->VR_D(v2, 1) | ~regs->VR_D(v3, 1);
ZVECTOR_END( regs );
}
#endif /* defined( FEATURE_135_ZVECTOR_ENH_FACILITY_1 ) */
/*-------------------------------------------------------------------*/
/* E770 VESLV - Vector Element Shift Left Vector [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_element_shift_left_vector )
{
int v1, v2, v3, m4, m5, m6, i;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m5, m6 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
switch (m4)
{
case 0:
for (i=0; i < 16; i++)
regs->VR_B(v1, i) = regs->VR_B(v2, i) << (regs->VR_B(v3, i) % 8);
break;
case 1:
for (i=0; i < 8; i++)
regs->VR_H(v1, i) = regs->VR_H(v2, i) << (regs->VR_H(v3, i) % 16);
break;
case 2:
for (i=0; i < 4; i++)
regs->VR_F(v1, i) = regs->VR_F(v2, i) << (regs->VR_F(v3, i) % 32);
break;
case 3:
for (i=0; i < 2; i++)
regs->VR_D(v1, i) = regs->VR_D(v2, i) << (regs->VR_D(v3, i) % 64);
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E772 VERIM - Vector Element Rotate and Insert Under Mask [VRI-d] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_element_rotate_and_insert_under_mask )
{
int v1, v2, v3, i4, m5;
int sl, sr;
union { U64 d[2]; U32 f[2]; U16 h[2]; BYTE b[2]; } temp;
int i;
VRI_D( inst, regs, v1, v2, v3, i4, m5 );
ZVECTOR_CHECK( regs );
switch (m5)
{
case 0: /* Byte */
for (i=0; i < 16; i++)
{
sl = i4 % 8;
sr = 8 - sl;
temp.b[1] = ((regs->VR_B( v2, i ) << sl) | (regs->VR_B( v2, i ) >> sr)) & regs->VR_B( v3, i );
temp.b[0] = regs->VR_B( v1, i ) & (~regs->VR_B( v3, i ));
regs->VR_B( v1, i ) = temp.b[0] | temp.b[1];
}
break;
case 1: /* Halfword */
for (i=0; i < 8; i++)
{
sl = i4 % 16;
sr = 16 - sl;
temp.h[1] = ((regs->VR_H( v2, i ) << sl) | (regs->VR_H( v2, i ) >> sr)) & regs->VR_H( v3, i );
temp.h[0] = regs->VR_H( v1, i ) & (~regs->VR_H( v3, i ));
regs->VR_H( v1, i ) = temp.h[0] | temp.h[1];
}
break;
case 2: /* Word */
for (i=0; i < 4; i++)
{
sl = i4 % 32;
sr = 32 - sl;
temp.f[1] = ((regs->VR_F( v2, i ) << sl) | (regs->VR_F( v2, i ) >> sr)) & regs->VR_F( v3, i );
temp.f[0] = regs->VR_F( v1, i ) & (~regs->VR_F( v3, i ));
regs->VR_F( v1, i ) = temp.f[0] | temp.f[1];
}
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++)
{
sl = i4 % 64;
sr = 64 - sl;
temp.d[1] = ((regs->VR_D( v2, i ) << sl) | (regs->VR_D( v2, i ) >> sr)) & regs->VR_D( v3, i );
temp.d[0] = regs->VR_D( v1, i ) & (~regs->VR_D( v3, i ));
regs->VR_D( v1, i ) = temp.d[0] | temp.d[1];
}
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E773 VERLLV - Vector Element Rotate Left Logical Vector [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_element_rotate_left_logical_vector )
{
int v1, v2, v3, m4, m5, m6;
int sl, sr, i;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m5, m6 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
switch (m4)
{
case 0: /* Byte */
for (i=0; i < 16; i++)
{
sl = regs->VR_B( v3, i ) % 8;
sr = 8 - sl;
regs->VR_B( v1, i ) = (regs->VR_B( v2, i ) << sl) | (regs->VR_B( v2, i ) >> sr);
}
break;
case 1: /* Halfword */
for (i=0; i < 8; i++)
{
sl = regs->VR_H( v3, i ) % 16;
sr = 16 - sl;
regs->VR_H( v1, i ) = (regs->VR_H( v2, i ) << sl) | (regs->VR_H( v2, i ) >> sr);
}
break;
case 2: /* Word */
for (i=0; i < 4; i++)
{
sl = regs->VR_F( v3, i ) % 32;
sr = 32 - sl;
regs->VR_F( v1, i ) = (regs->VR_F( v2, i ) << sl) | (regs->VR_F( v2, i ) >> sr);
}
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++)
{
sl = regs->VR_D( v3, i ) % 64;
sr = 64 - sl;
regs->VR_D( v1, i ) = (regs->VR_D( v2, i ) << sl) | (regs->VR_D( v2, i ) >> sr);
}
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E774 VSL - Vector Shift Left [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_shift_left )
{
int v1, v2, v3, m4, m5, m6;
int sl, sr, i;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m4, m5, m6 are not part of this instruction */
UNREFERENCED( m4 );
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
for (i = 0 ; ; i++)
{
sl = regs->VR_B( v3, i ) & 0x07;
if (i == 15)
{
regs->VR_B( v1, i ) = regs->VR_B( v2, i ) << sl;
break;
}
sr = 8 - sl;
regs->VR_B( v1, i ) = (regs->VR_B( v2, i ) << sl) | (regs->VR_B( v2, i+1 ) >> sr);
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E775 VSLB - Vector Shift Left By Byte [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_shift_left_by_byte )
{
int v1, v2, v3, m4, m5, m6;
int i, j;
SV temp;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m4, m5, m6 are not part of this instruction */
UNREFERENCED( m4 );
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
SV_D( temp, 0 ) = regs->VR_D( v2, 0 );
SV_D( temp, 1 ) = regs->VR_D( v2, 1 );
SV_D( temp, 2 ) = 0;
SV_D( temp, 3 ) = 0;
j = (regs->VR_B( v3, 7 ) & 0x78) >> 3;
for (i = 0; i < 16; i++, j++)
regs->VR_B(v1, i) = SV_B( temp, j );
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E777 VSLDB - Vector Shift Left Double By Byte [VRI-d] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_shift_left_double_by_byte )
{
int v1, v2, v3, i4, m5;
int i, j;
SV temp;
VRI_D( inst, regs, v1, v2, v3, i4, m5 );
/* m5 is not part of this instruction */
UNREFERENCED( m5 );
ZVECTOR_CHECK( regs );
SV_D( temp, 0 ) = regs->VR_D( v2, 0 );
SV_D( temp, 1 ) = regs->VR_D( v2, 1 );
SV_D( temp, 2 ) = regs->VR_D( v3, 0 );
SV_D( temp, 3 ) = regs->VR_D( v3, 1 );
for (i = 0, j = i4; i < 16; i++, j++)
regs->VR_B(v1, i) = SV_B( temp, j );
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E778 VESRLV - Vector Element Shift Right Logical Vector [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_element_shift_right_logical_vector )
{
int v1, v2, v3, m4, m5, m6;
int shift, i;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m5, m6 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
switch (m4)
{
case 0: /* Byte */
for (i=0; i < 16; i++)
{
shift = regs->VR_B( v3, i ) % 8;
regs->VR_B( v1, i ) = regs->VR_B( v2, i ) >> shift;
}
break;
case 1: /* Halfword */
for (i=0; i < 8; i++)
{
shift = regs->VR_H( v3, i ) % 16;
regs->VR_H( v1, i ) = regs->VR_H( v2, i ) >> shift;
}
break;
case 2: /* Word */
for (i=0; i < 4; i++)
{
shift = regs->VR_F( v3, i ) % 32;
regs->VR_F( v1, i ) = regs->VR_F( v2, i ) >> shift;
}
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++)
{
shift = regs->VR_D( v3, i ) % 64;
regs->VR_D( v1, i ) = regs->VR_D( v2, i ) >> shift;
}
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E77A VESRAV - Vector Element Shift Right Arithmetic Vector[VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_element_shift_right_arithmetic_vector )
{
int v1, v2, v3, m4, m5, m6;
int shift, i;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m5, m6 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
switch (m4)
{
case 0: /* Byte */
for (i=0; i < 16; i++)
{
shift = regs->VR_B( v3, i ) % 8;
regs->VR_B( v1, i ) = (S8) regs->VR_B( v2, i ) >> shift;
}
break;
case 1: /* Halfword */
for (i=0; i < 8; i++)
{
shift = regs->VR_H( v3, i ) % 16;
regs->VR_H( v1, i ) = (S16) regs->VR_H( v2, i ) >> shift;
}
break;
case 2: /* Word */
for (i=0; i < 4; i++)
{
shift = regs->VR_F( v3, i ) % 32;
regs->VR_F( v1, i ) = (S32) regs->VR_F( v2, i ) >> shift;
}
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++)
{
shift = regs->VR_D( v3, i ) % 64;
regs->VR_D( v1, i ) = (S64) regs->VR_D( v2, i ) >> shift;
}
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E77C VSRL - Vector Shift Right Logical [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_shift_right_logical )
{
int v1, v2, v3, m4, m5, m6;
int sr, sl, i;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m4, m5, m6 are not part of this instruction */
UNREFERENCED( m4 );
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
for (i = 15 ; ; i--)
{
sr = regs->VR_B( v3, i ) & 0x07;
if (i == 0)
{
regs->VR_B( v1, i ) = regs->VR_B( v2, i ) >> sr;
break;
}
sl = 8 - sr;
regs->VR_B( v1, i ) = (regs->VR_B( v2, i ) >> sr) | (regs->VR_B( v2, i-1 ) << sl);
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E77D VSRLB - Vector Shift Right Logical By Byte [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_shift_right_logical_by_byte )
{
int v1, v2, v3, m4, m5, m6;
int i, j;
SV temp;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m4, m5, m6 are not part of this instruction */
UNREFERENCED( m4 );
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
SV_D( temp, 0 ) = 0;
SV_D( temp, 1 ) = 0;
SV_D( temp, 2 ) = regs->VR_D( v2, 0 );
SV_D( temp, 3 ) = regs->VR_D( v2, 1 );
j = 16 - ((regs->VR_B( v3, 7 ) & 0x78) >> 3);
for (i = 0; i < 16; i++, j++)
regs->VR_B(v1, i) = SV_B( temp, j );
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E77E VSRA - Vector Shift Right Arithmetic [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_shift_right_arithmetic )
{
int v1, v2, v3, m4, m5, m6;
int sr, sl, i;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m4, m5, m6 are not part of this instruction */
UNREFERENCED( m4 );
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
for (i = 15 ; ; i--)
{
sr = regs->VR_B( v3, i ) & 0x07;
if (i == 0)
{
regs->VR_B( v1, i ) = (S8)regs->VR_B( v2, i ) >> sr;
break;
}
sl = 8 - sr;
regs->VR_B( v1, i ) = (regs->VR_B( v2, i ) >> sr) | (regs->VR_B( v2, i-1 ) << sl);
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E77F VSRAB - Vector Shift Right Arithmetic By Byte [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_shift_right_arithmetic_by_byte )
{
int v1, v2, v3, m4, m5, m6;
int i, j;
SV temp;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m4, m5, m6 are not part of this instruction */
UNREFERENCED( m4 );
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
if (regs->VR_B( v2, 0 ) & 0x80)
{
SV_D( temp, 0 ) = 0xFFFFFFFFFFFFFFFFull;
SV_D( temp, 1 ) = 0xFFFFFFFFFFFFFFFFull;
}
else
{
SV_D( temp, 0 ) = 0;
SV_D( temp, 1 ) = 0;
}
SV_D( temp, 2 ) = regs->VR_D( v2, 0 );
SV_D( temp, 3 ) = regs->VR_D( v2, 1 );
j = 16 - ((regs->VR_B( v3, 7 ) & 0x78) >> 3);
for (i = 0; i < 16; i++, j++)
regs->VR_B(v1, i) = SV_B( temp, j );
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E780 VFEE - Vector Find Element Equal [VRR-b] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_find_element_equal )
{
int v1, v2, v3, m4, m5;
int ef, ei, zf, zi, i;
BYTE newcc;
VRR_B( inst, regs, v1, v2, v3, m4, m5 );
ZVECTOR_CHECK( regs );
#define M5_RE ((m5 & 0xc) != 0) // Reserved
#define M5_ZS ((m5 & 0x2) != 0) // Zero Search
#define M5_CS ((m5 & 0x1) != 0) // Condition Code Set
if (m4 > 2 || M5_RE)
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
zf = ef = FALSE;
zi = ei = 16; // Number of bytes in vector
switch (m4)
{
case 0: /* Byte */
for (i=0; i<16; i++)
{
if (regs->VR_B(v2,i) == regs->VR_B(v3,i))
{
ef = TRUE;
ei = i; // Element index in bytes
break;
}
}
if (M5_ZS)
{
for (i=0; i<16; i++)
{
if (regs->VR_B(v2,i) == 0)
{
zf = TRUE;
zi = i; // Zero element index in bytes
break;
}
}
}
break;
case 1: /* Halfword */
for (i=0; i<8; i++)
{
if (regs->VR_H(v2,i) == regs->VR_H(v3,i))
{
ef = TRUE;
ei = i * 2; // Element index in bytes
break;
}
}
if (M5_ZS)
{
for (i=0; i<8; i++)
{
if (regs->VR_H(v2,i) == 0)
{
zf = TRUE;
zi = i * 2; // Zero element index in bytes
break;
}
}
}
break;
case 2: /* Word */
for (i=0; i<4; i++)
{
if (regs->VR_F(v2,i) == regs->VR_F(v3,i))
{
ef = TRUE;
ei = i * 4; // Element index in bytes
break;
}
}
if (M5_ZS)
{
for (i=0; i<4; i++)
{
if (regs->VR_F(v2,i) == 0)
{
zf = TRUE;
zi = i * 4; // Zero element index in bytes
break;
}
}
}
break;
}
if (ef == TRUE)
{
if (zf == TRUE)
{
if (zi <= ei)
{
newcc = 0; // Equal element follows zero element, or equal element is zero element
ei = zi; // Element index in bytes
}
else
{
newcc = 2; // Equal element before zero element
}
}
else /* zf == FALSE */
{
newcc = 1; // Equal element and, if M5_ZS, no zero element
}
}
else /* ef == FALSE */
{
if (zf == TRUE)
{
newcc = 0; // No equal element and a zero element
ei = zi; // Element index in bytes
}
else /* zf == FALSE */
{
newcc = 3; // No equal element and, if M5_ZS, no zero element
}
}
regs->VR_D(v1, 0) = ei;
regs->VR_D(v1, 1) = 0;
if (M5_CS)
regs->psw.cc = newcc;
#undef M5_RE
#undef M5_ZS
#undef M5_CS
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E781 VFENE - Vector Find Element Not Equal [VRR-b] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_find_element_not_equal )
{
int v1, v2, v3, m4, m5;
int nef, nei, zf, zi, i;
BYTE newcc;
VRR_B( inst, regs, v1, v2, v3, m4, m5 );
ZVECTOR_CHECK( regs );
#define M5_RE ((m5 & 0xc) != 0) // Reserved
#define M5_ZS ((m5 & 0x2) != 0) // Zero Search
#define M5_CS ((m5 & 0x1) != 0) // Condition Code Set
if (m4 > 2 || M5_RE)
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
zf = nef = FALSE;
zi = nei = 16; // Number of bytes in vector
newcc = 3; // All equal, no zero
switch (m4)
{
case 0: /* Byte */
for (i=0; i<16; i++)
{
if (regs->VR_B(v2,i) != regs->VR_B(v3,i))
{
nef = TRUE;
nei = i; // Element index in bytes
newcc = (regs->VR_B(v2,i) < regs->VR_B(v3,i)) ? 1 : 2;
break;
}
}
if (M5_ZS)
{
for (i=0; i<16; i++)
{
if (regs->VR_B(v2,i) == 0)
{
zf = TRUE;
zi = i; // Zero element index in bytes
break;
}
}
}
break;
case 1: /* Halfword */
for (i=0; i<8; i++)
{
if (regs->VR_H(v2,i) != regs->VR_H(v3,i))
{
nef = TRUE;
nei = i * 2; // Element index in bytes
newcc = (regs->VR_H(v2,i) < regs->VR_H(v3,i)) ? 1 : 2;
break;
}
}
if (M5_ZS)
{
for (i=0; i<8; i++)
{
if (regs->VR_H(v2,i) == 0)
{
zf = TRUE;
zi = i * 2; // Zero element index in bytes
break;
}
}
}
break;
case 2: /* Word */
for (i=0; i<4; i++)
{
if (regs->VR_F(v2,i) != regs->VR_F(v3,i))
{
nef = TRUE;
nei = i * 4; // Element index in bytes
newcc = (regs->VR_F(v2,i) < regs->VR_F(v3,i)) ? 1 : 2;
break;
}
}
if (M5_ZS)
{
for (i=0; i<4; i++)
{
if (regs->VR_F(v2,i) == 0)
{
zf = TRUE;
zi = i * 4; // Zero element index in bytes
break;
}
}
}
break;
}
if (nef == TRUE)
{
if (zf == TRUE)
{
if (zi < nei)
{
newcc = 0; // Not equal element follows zero element
nei = zi; // Element index in bytes
}
else
{
/* newcc = 1 or 2; */ // Not equal element before zero element, or not equal element is zero element
}
}
else /* zf == FALSE */
{
/* newcc = 1 or 2; */ // Not equal element and, if M5_ZS, no zero element
}
}
else /* nef == FALSE */
{
if (zf == TRUE)
{
newcc = 0; // No not equal (i.e. all equal) element and a zero element
nei = zi; // Element index in bytes
}
else /* zf == FALSE */
{
/* newcc = 3; */ // No not equal (i.e. all equal) element and, if M5_ZS, no zero element
}
}
regs->VR_D(v1, 0) = nei;
regs->VR_D(v1, 1) = 0;
if (M5_CS)
regs->psw.cc = newcc;
#undef M5_RE
#undef M5_ZS
#undef M5_CS
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E782 VFAE - Vector Find Any Element Equal [VRR-b] */
/*-------------------------------------------------------------------*/
/* In PoP (SA22-7832-13), for VFAE & VFEE we can read:
"Programming Notes:
1. If the RT flag is zero, a byte index is always
stored into the first operand for any element size.
For example, if the specified element size is halfword
and the 2nd indexed halfword compared
equal, a byte index of 4 would be stored."
But I think that 4 would be a 2.
The 2nd Half = 1 (index byte) x 2 (length of H) = 2.
After 35 years, I must say this is the first typo I found in POP.
Sent to IBM, they will reformulate the sentence.
salva - 2023, feb,27.
*/
DEF_INST( vector_find_any_element_equal )
{
int v1, v2, v3, m4, m5;
int i, j;
int lxt1, lxt2; // Lowest indexed true
int mxt; // Maximum indexed true
BYTE irt1[16], irt2[16]; // First and second intermediate results
VRR_B( inst, regs, v1, v2, v3, m4, m5 );
ZVECTOR_CHECK( regs );
#define M5_IN ((m5 & 0x8) != 0) // Invert Result
#define M5_RT ((m5 & 0x4) != 0) // Result Type
#define M5_ZS ((m5 & 0x2) != 0) // Zero Search
#define M5_CS ((m5 & 0x1) != 0) // Condition Code Set
for (i=0; i<16; i++)
{
irt1[i] = irt2[i] = FALSE;
}
switch (m4)
{
case 0: /* Byte */
for (i=0; i<16; i++)
{
// Compare the element of the second with the elements of the third operands
for (j=0; j<16; j++)
{
if (regs->VR_B(v2,i) == regs->VR_B(v3,j))
{
irt1[i] = TRUE;
break;
}
}
// Invert the result if required
if (M5_IN) irt1[i] ^= TRUE;
// Compare the element of the second operand with zero
if (M5_ZS && regs->VR_B(v2,i) == 0) irt2[i] = TRUE;
}
if (M5_RT) // if M5_RT (Result Type)
{
for (i=0; i<16; i++)
{
regs->VR_B(v1, i) = (irt1[i] == TRUE) ? 0xFF : 0x00;
}
}
else // else !M5_RT
{
lxt1 = lxt2 = 16;
for (i=0; i<16; i++)
{
if (irt1[i] == TRUE && lxt1 == 16)
lxt1 = i;
if (irt2[i] == TRUE && lxt2 == 16)
lxt2 = i;
}
regs->VR_D(v1, 0) = min(lxt1, lxt2);
regs->VR_D(v1, 1) = 0;
}
break;
case 1: /* Halfword */
for (i=0; i<8; i++)
{
// Compare the element of the second with the elements of the third operands
for (j=0; j<8; j++)
{
if (regs->VR_H(v2,i) == regs->VR_H(v3,j))
{
irt1[i] = TRUE;
break;
}
}
// Invert the result if required
if (M5_IN) irt1[i] ^= TRUE;
// Compare the element of the second operand with zero
if (M5_ZS && regs->VR_H(v2,i) == 0) irt2[i] = TRUE;
}
if (M5_RT) // if M5_RT (Result Type)
{
for (i=0; i<8; i++)
{
regs->VR_H(v1, i) = (irt1[i] == TRUE) ? 0xFFFF : 0x0000;
}
}
else // else !M5_RT
{
lxt1 = lxt2 = 16;
for (i=0; i<8; i++)
{
if (irt1[i] == TRUE && lxt1 == 16)
lxt1 = i * 2;
if (irt2[i] == TRUE && lxt2 == 16)
lxt2 = i * 2;
}
regs->VR_D(v1, 0) = min(lxt1, lxt2);
regs->VR_D(v1, 1) = 0;
}
break;
case 2: /* Word */
for (i=0; i<4; i++)
{
// Compare the element of the second with the elements of the third operands
for (j=0; j<4; j++)
{
if (regs->VR_F(v2,i) == regs->VR_F(v3,j))
{
irt1[i] = TRUE;
break;
}
}
// Invert the result if required
if (M5_IN) irt1[i] ^= TRUE;
// Compare the element of the second operand with zero
if (M5_ZS && regs->VR_F(v2,i) == 0) irt2[i] = TRUE;
}
if (M5_RT) // if M5_RT (Result Type)
{
for (i=0; i<4; i++)
{
regs->VR_F(v1, i) = (irt1[i] == TRUE) ? 0xFFFFFFFF : 0x00000000;
}
}
else // else !M5_RT
{
lxt1 = lxt2 = 16;
for (i=0; i<4; i++)
{
if (irt1[i] == TRUE && lxt1 == 16)
lxt1 = i * 4;
if (irt2[i] == TRUE && lxt2 == 16)
lxt2 = i * 4;
}
regs->VR_D(v1, 0) = min(lxt1, lxt2);
regs->VR_D(v1, 1) = 0;
}
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
if (M5_CS) // if M5_CS (Condition Code Set)
{
switch (m4)
{
case 0: /* Byte */
lxt1 = lxt2 = mxt = 16;
break;
case 1: /* Halfword */
lxt1 = lxt2 = mxt = 8;
break;
case 2: /* Word */
lxt1 = lxt2 = mxt = 4;
break;
default: // Prevent erroneous "may be used uninitialized" warnings
lxt1 = lxt2 = mxt = 0;
break;
}
for (i = 0; i < mxt; i++)
{
if (irt1[i] == TRUE && lxt1 == mxt)
lxt1 = i;
if (M5_ZS) // if M5_ZS (Zero Search)
{
if (irt2[i] == TRUE && lxt2 == mxt)
lxt2 = i;
}
}
// cc 1 and 3 are possible when M5_ZS is 0 or 1.
if (lxt1 == mxt && lxt2 == mxt)
regs->psw.cc = 3;
else if (lxt1 < mxt && lxt2 == mxt )
regs->psw.cc = 1;
// cc 0 and 2 are only possible when M5_ZS is 1.
else if (lxt1 < lxt2)
regs->psw.cc = 2;
else
regs->psw.cc = 0;
}
#undef M5_IN
#undef M5_RT
#undef M5_ZS
#undef M5_CS
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E784 VPDI - Vector Permute Doubleword Immediate [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_permute_doubleword_immediate )
{
int v1, v2, v3, m4, m5, m6;
SV temp;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m5, m6 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
#define M4_SO ((m4 & 0x4) != 0) // Second operand index
#define M4_TO ((m4 & 0x1) != 0) // Third operand index
SV_D( temp, 0 ) = regs->VR_D( v2, M4_SO );
SV_D( temp, 1 ) = regs->VR_D( v3, M4_TO );
regs->VR_D( v1, 0 ) = SV_D( temp, 0 );
regs->VR_D( v1, 1 ) = SV_D( temp, 1 );
#undef M4_SO
#undef M4_TO
ZVECTOR_END( regs );
}
#if defined( FEATURE_135_ZVECTOR_ENH_FACILITY_1 )
/*-------------------------------------------------------------------*/
/* E785 VBPERM - Vector Bit Permute [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_bit_permute )
{
int v1, v2, v3, m4, m5, m6;
int i, j, k;
U16 wanted, result = 0;
SV temp;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m4, m5, m6 are not part of this instruction */
UNREFERENCED( m4 );
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
SV_D( temp, 0 ) = regs->VR_D( v2, 0 );
SV_D( temp, 1 ) = regs->VR_D( v2, 1 );
SV_D( temp, 2 ) = 0;
SV_D( temp, 3 ) = 0;
// Each of the sixteen 1-byte elements in vector register v3
// contains the bit number (0 to 255) of a bit in the source
// vector.
// 1. Calculate the number of the byte (0 to 31) in the source
// vector that contains the wanted bit number.
// 2. Calculate the number of the bit (0 to 7) in the byte
// that is the wanted bit.
// 3. Calculate the value (0 or 1) of the wanted bit, and
// 4. If the wanted bit has a value of 1, place the bit in
// the result.
// The bit value of the bit number in the first element of v3
// becomes result bit 0, the bit value of the bit number in the
// second element of v3 becomes result bit 1, and so on until
// the bit value of the bit number in the sixteenth element of
// v3 becomes result bit 15.
for (i = 0; i < 16; i++)
{
j = regs->VR_B( v3, i ) / 8;
k = regs->VR_B( v3, i ) % 8;
wanted = SV_B( temp, j ) & ( 0x80 >> k );
if (wanted)
{
result |= ( 0x0001 << ( 15 - i ) );
}
}
regs->VR_D( v1, 0 ) = result;
regs->VR_D( v1, 1 ) = 0;
ZVECTOR_END( regs );
}
#endif /* defined( FEATURE_135_ZVECTOR_ENH_FACILITY_1 ) */
/*-------------------------------------------------------------------*/
/* E786 VSLD - Vector Shift Left Double By Bit [VRI-d] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_shift_left_double_by_bit )
{
int v1, v2, v3, i4, m5;
int i;
U64 j, k;
SV temp;
VRI_D( inst, regs, v1, v2, v3, i4, m5 );
/* m5 is not part of this instruction */
UNREFERENCED( m5 );
ZVECTOR_CHECK( regs );
if (i4 & 0xF8)
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
SV_D( temp, 0 ) = regs->VR_D( v2, 0 );
SV_D( temp, 1 ) = regs->VR_D( v2, 1 );
SV_D( temp, 2 ) = regs->VR_D( v3, 0 );
SV_D( temp, 3 ) = regs->VR_D( v3, 1 );
if ( i4 > 0 )
for (i = 0; i < 3; i++) {
j = SV_D( temp, i ) << i4;
k = SV_D( temp, i+1 ) >> ( 64 - i4 );
SV_D( temp, i ) = j | k;
}
regs->VR_D( v1, 0 ) = SV_D( temp, 0 );
regs->VR_D( v1, 1 ) = SV_D( temp, 1 );
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E787 VSRD - Vector Shift Right Double By Bit [VRI-d] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_shift_right_double_by_bit )
{
int v1, v2, v3, i4, m5;
int i;
U64 j, k;
SV temp;
VRI_D( inst, regs, v1, v2, v3, i4, m5 );
/* m5 is not part of this instruction */
UNREFERENCED( m5 );
ZVECTOR_CHECK( regs );
if (i4 & 0xF8)
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
SV_D( temp, 0 ) = regs->VR_D( v2, 0 );
SV_D( temp, 1 ) = regs->VR_D( v2, 1 );
SV_D( temp, 2 ) = regs->VR_D( v3, 0 );
SV_D( temp, 3 ) = regs->VR_D( v3, 1 );
if ( i4 > 0 )
for (i = 3; i > 0; i--) {
j = SV_D( temp, i-1 ) << ( 64 - i4 );
k = SV_D( temp, i ) >> i4;
SV_D( temp, i ) = j | k;
}
regs->VR_D( v1, 0 ) = SV_D( temp, 2 );
regs->VR_D( v1, 1 ) = SV_D( temp, 3 );
ZVECTOR_END( regs );
}
#if defined( FEATURE_198_VECTOR_ENH_FACILITY_3 )
/*-------------------------------------------------------------------*/
/* E788 VEVAL - Vector Evaluate [VRI-k] */
/*-------------------------------------------------------------------*/
/* VEVAL implements the boolean operations defined in Principles of */
/* Operation SA22-7832-14, Figure 22-3 Parts 1 and 2. The majority */
/* of the entries in Figure 22-3 are marked as either "a duplicate */
/* function of an existing vector instruction" or "a duplicate of */
/* another entry in the table for a boolean operation with a */
/* different order of A, B, C". Fortunately, the Intel VPTERNLOGQ */
/* instruction is the equivalent of VEVAL, and the VPTERNLOGQ */
/* instructions table of boolean logic operations is complete. */
/* As the known entries in VEVAL's big endian table match the */
/* equivalent entries in VPTERNLOGQ's little endian table, it is */
/* assumed that the duplicate entries in VEVAL's table also match */
/* the equivalent entries in VPTERNLOGQ's table. */
/* The comments following the case statements contain bit values in */
/* the format "bbbbb bbb". The first group of five match bits 0-4 */
/* of the i5 value, and the second group of three match bits 5-7 of */
/* the i5 value. The bit values match the row and column headers in */
/* Figure 22-3. */
/*-------------------------------------------------------------------*/
DEF_INST( vector_evaluate )
{
int v1, v2, v3, v4, i5;
U128 temp, tempA, tempB, tempC;
VRI_K( inst, regs, v1, v2, v3, v4, i5 );
ZVECTOR_CHECK( regs );
tempA.Q = regs->VR_Q(v2);
tempB.Q = regs->VR_Q(v3);
tempC.Q = regs->VR_Q(v4);
switch (i5)
{
case 0: /* 00000 000 FALSE */
temp = U128_zero();
break;
case 1: /* 00000 001 AND(A,B,C) */
temp = U128_and3(tempA, tempB, tempC);
break;
case 2: /* 00000 010 NOR(C,NAND(B,A)) */
temp = U128_nor(tempC, U128_nand(tempB, tempA));
break;
case 3: /* 00000 011 AND(B,A) */
temp = U128_and(tempB, tempA);
break;
case 4: /* 00000 100 NOR(B,NAND(A,C)) */
temp = U128_nor(tempB, U128_nand(tempA, tempC));
break;
case 5: /* 00000 101 AND(C,A) */
temp = U128_and(tempC, tempA);
break;
case 6: /* 00000 110 AND(A,XOR(B,C)) */
temp = U128_and(tempA, U128_xor(tempB, tempC));
break;
case 7: /* 00000 111 AND(A,OR(B,C)) */
temp = U128_and(tempA, U128_or(tempB, tempC));
break;
case 8: /* 00001 000 AND(A,NOR(B,C)) */
temp = U128_and(tempA, U128_nor(tempB, tempC));
break;
case 9: /* 00001 001 AND(A,NXOR(B,C)) */
temp = U128_and(tempA, U128_nxor(tempB, tempC));
break;
case 10: /* 00001 010 AND(A,NOT(C)) */
temp = U128_and(tempA, U128_not(tempC));
break;
case 11: /* 00001 011 SEL(C,AND(B,A),A) */
temp = U128_select(tempC, U128_and(tempB, tempA), tempA);
break;
case 12: /* 00001 100 AND(A,NOT(B)) */
temp = U128_and(tempA, U128_not(tempB));
break;
case 13: /* 00001 101 SEL(B,AND(A,C),A) */
temp = U128_select(tempB, U128_and(tempA, tempC), tempA);
break;
case 14: /* 00001 110 AND(A,NAND(B,C)) */
temp = U128_and(tempA, U128_nand(tempB, tempC));
break;
case 15: /* 00001 111 A */
temp = tempA;
break;
case 16: /* 00010 000 NOR(A,NAND(B,C)) */
temp = U128_nor(tempA, U128_nand(tempB, tempC));
break;
case 17: /* 00010 001 AND(C,B) */
temp = U128_and(tempC, tempB);
break;
case 18: /* 00010 010 AND(B,XOR(A,C)) */
temp = U128_and(tempB, U128_xor(tempA, tempC));
break;
case 19: /* 00010 011 AND(B,OR(A,C)) */
temp = U128_and(tempB, U128_or(tempA, tempC));
break;
case 20: /* 00010 100 AND(C,XOR(B,A)) */
temp = U128_and(tempC, U128_xor(tempB, tempA));
break;
case 21: /* 00010 101 AND(C,OR(A,B)) */
temp = U128_and(tempC, U128_or(tempA, tempB));
break;
case 22: /* 00010 110 SEL(A,XOR(B,C),AND(B,C)) */
temp = U128_select(tempA, U128_xor(tempB, tempC), U128_and(tempB, tempC));
break;
case 23: /* 00010 111 MAJOR(A,B,C) */
temp = U128_major(tempA, tempB, tempC);
break;
case 24: /* 00011 000 SEL(A,NOR(B,C),AND(B,C)) */
temp = U128_select(tempA, U128_nor(tempB, tempC), U128_and(tempB, tempC));
break;
case 25: /* 00011 001 SEL(A,NXOR(B,C),AND(B,C)) */
temp = U128_select(tempA, U128_nxor(tempB, tempC), U128_and(tempB, tempC));
break;
case 26: /* 00011 010 SEL(A,NOT(C),AND(B,C)) */
temp = U128_select(tempA, U128_not(tempC), U128_and(tempB, tempC));
break;
case 27: /* 00011 011 SEL(C,B,A) */
temp = U128_select(tempC, tempB, tempA);
break;
case 28: /* 00011 100 SEL(A,NOT(B),AND(B,C)) */
temp = U128_select(tempA, U128_not(tempB), U128_and(tempB, tempC));
break;
case 29: /* 00011 101 SEL(B,C,A) */
temp = U128_select(tempB, tempC, tempA);
break;
case 30: /* 00011 110 XOR(A,AND(B,C)) */
temp = U128_xor(tempA, U128_and(tempB, tempC));
break;
case 31: /* 00011 111 OR(A,AND(B,C)) */
temp = U128_or(tempA, U128_and(tempB, tempC));
break;
case 32: /* 00100 000 AND(B,NOR(A,C)) */
temp = U128_and(tempB, U128_nor(tempA, tempC));
break;
case 33: /* 00100 001 AND(B,NXOR(A,C)) */
temp = U128_and(tempB, U128_nxor(tempA, tempC));
break;
case 34: /* 00100 010 AND(B,NOT(C)) */
temp = U128_and(tempB, U128_not(tempC));
break;
case 35: /* 00100 011 SEL(C,AND(B,A),B) */
temp = U128_select(tempC, U128_and(tempB, tempA), tempB);
break;
case 36: /* 00100 100 SEL(B,NOR(A,C),AND(A,C)) */
temp = U128_select(tempB, U128_nor(tempA, tempC), U128_and(tempA, tempC));
break;
case 37: /* 00100 101 SEL(B,NXOR(A,C),AND(A,C)) */
temp = U128_select(tempB, U128_nxor(tempA, tempC), U128_and(tempA, tempC));
break;
case 38: /* 00100 110 SEL(B,NOT(C),AND(A,C)) */
temp = U128_select(tempB, U128_not(tempC), U128_and(tempA, tempC));
break;
case 39: /* 00100 111 SEL(C,A,B) */
temp = U128_select(tempC, tempA, tempB);
break;
case 40: /* 00101 000 NOR(C,NXOR(B,A)) */
temp = U128_nor(tempC, U128_nxor(tempB, tempA));
break;
case 41: /* 00101 001 SEL(C,AND(B,A),XOR(B,A)) */
temp = U128_select(tempC, U128_and(tempB, tempA), U128_xor(tempB, tempA));
break;
case 42: /* 00101 010 NOR(C,NOR(B,A)) */
temp = U128_nor(tempC, U128_nor(tempB, tempA));
break;
case 43: /* 00101 011 SEL(C,AND(B,A),OR(B,A)) */
temp = U128_select(tempC, U128_and(tempB, tempA), U128_or(tempB, tempA));
break;
case 44: /* 00101 100 SEL(B,NOR(A,C),A)) */
temp = U128_select(tempB, U128_nor(tempA, tempC), tempA);
break;
case 45: /* 00101 101 SEL(B,NXOR(A,C),A) */
temp = U128_select(tempB, U128_nxor(tempA, tempC), tempA);
break;
case 46: /* 00101 110 SEL(B,NOT(C),A) */
temp = U128_select(tempB, U128_not(tempC), tempA);
break;
case 47: /* 00101 111 SEL(C,A,OR(B,A)) */
temp = U128_select(tempC, tempA, U128_or(tempB, tempA));
break;
case 48: /* 00110 000 AND(B,NOT(A)) */
temp = U128_and(tempB, U128_not(tempA));
break;
case 49: /* 00110 001 SEL(A,AND(B,C),B) */
temp = U128_select(tempA, U128_and(tempB, tempC), tempB);
break;
case 50: /* 00110 010 AND(B,NAND(A,C)) */
temp = U128_and(tempB, U128_nand(tempA, tempC));
break;
case 51: /* 00110 011 B */
temp = tempB;
break;
case 52: /* 00110 100 SEL(B,NOT(A),AND(A,C)) */
temp = U128_select(tempB, U128_not(tempA), U128_and(tempA, tempC));
break;
case 53: /* 00110 101 SEL(A,C,B) */
temp = U128_select(tempA, tempC, tempB);
break;
case 54: /* 00110 110 XOR(B,AND(A,C)) */
temp = U128_xor(tempB, U128_and(tempA, tempC));
break;
case 55: /* 00110 111 OR(B,AND(A,C)) */
temp = U128_or(tempB, U128_and(tempA, tempC));
break;
case 56: /* 00111 000 SEL(A,NOR(B,C),B)) */
temp = U128_select(tempA, U128_nor(tempB, tempC), tempB);
break;
case 57: /* 00111 001 SEL(A,NXOR(B,C),B) */
temp = U128_select(tempA, U128_nxor(tempB, tempC), tempB);
break;
case 58: /* 00111 010 SEL(A,NOT(C),B) */
temp = U128_select(tempA, U128_not(tempC), tempB);
break;
case 59: /* 00111 011 SEL(C,B,OR(B,A)) */
temp = U128_select(tempC, tempB, U128_or(tempB, tempA));
break;
case 60: /* 00111 100 XOR(B,A) */
temp = U128_xor(tempB, tempA);
break;
case 61: /* 00111 101 SEL(C,OR(B,A),XOR(B,A)) */
temp = U128_select(tempC, U128_or(tempB, tempA), U128_xor(tempB, tempA));
break;
case 62: /* 00111 110 SEL(A,NAND(B,C),B) */
temp = U128_select(tempA, U128_nand(tempB, tempC), tempB);
break;
case 63: /* 00111 111 OR(B,A) */
temp = U128_or(tempB, tempA);
break;
case 64: /* 01000 000 AND(C,NOR(B,A)) */
temp = U128_and(tempC, U128_nor(tempB, tempA));
break;
case 65: /* 01000 001 AND(C,NXOR(B,A)) */
temp = U128_and(tempC, U128_nxor(tempB, tempA));
break;
case 66: /* 01000 010 SEL(C,NOR(B,A),AND(B,A)) */
temp = U128_select(tempC, U128_nor(tempB, tempA), U128_and(tempB, tempA));
break;
case 67: /* 01000 011 SEL(C,NXOR(B,A),AND(B,A)) */
temp = U128_select(tempC, U128_nxor(tempB, tempA), U128_and(tempB, tempA));
break;
case 68: /* 01000 100 AND(C,NOT(B)) */
temp = U128_and(tempC, U128_not(tempB));
break;
case 69: /* 01000 101 SEL(B,AND(A,C),C) */
temp = U128_select(tempB, U128_and(tempA, tempC), tempC);
break;
case 70: /* 01000 110 SEL(C,NOT(B),AND(B,A)) */
temp = U128_select(tempC, U128_not(tempB), U128_and(tempB, tempA));
break;
case 71: /* 01000 111 SEL(B,A,C) */
temp = U128_select(tempB, tempA, tempC);
break;
case 72: /* 01001 000 NOR(B,NXOR(A,C)) */
temp = U128_nor(tempB, U128_nxor(tempA, tempC));
break;
case 73: /* 01001 001 SEL(B,AND(A,C),XOR(A,C)) */
temp = U128_select(tempB, U128_and(tempA, tempC), U128_xor(tempA, tempC));
break;
case 74: /* 01001 010 SEL(C,NOR(B,A),A)) */
temp = U128_select(tempC, U128_nor(tempB, tempA), tempA);
break;
case 75: /* 01001 011 SEL(B,A,XOR(A,C)) */
temp = U128_select(tempB, tempA, U128_xor(tempA, tempC));
break;
case 76: /* 01001 100 NOR(B,NOR(A,C)) */
temp = U128_nor(tempB, U128_nor(tempA, tempC));
break;
case 77: /* 01001 101 SEL(B,AND(A,C),OR(A,C)) */
temp = U128_select(tempB, U128_and(tempA, tempC), U128_or(tempA, tempC));
break;
case 78: /* 01001 110 SEL(C,NOT(B),A)) */
temp = U128_select(tempC, U128_not(tempB), tempA);
break;
case 79: /* 01001 111 SEL(B,A,OR(A,C)) */
temp = U128_select(tempB, tempA, U128_or(tempA, tempC));
break;
case 80: /* 01010 000 AND(C,NOT(A)) */
temp = U128_and(tempC, U128_not(tempA));
break;
case 81: /* 01010 001 SEL(A,AND(B,C),C) */
temp = U128_select(tempA, U128_and(tempB, tempC), tempC);
break;
case 82: /* 01010 010 SEL(C,NOT(A),AND(B,A)) */
temp = U128_select(tempC, U128_not(tempA), U128_and(tempB, tempA));
break;
case 83: /* 01010 011 SEL(A,B,C) */
temp = U128_select(tempA, tempB, tempC);
break;
case 84: /* 01010 100 AND(C,NAND(B,A)) */
temp = U128_and(tempC, U128_nand(tempB, tempA));
break;
case 85: /* 01010 101 C */
temp = tempC;
break;
case 86: /* 01010 110 XOR(C,AND(B,A)) */
temp = U128_xor(tempC, U128_and(tempB, tempA));
break;
case 87: /* 01010 111 OR(C,AND(B,A)) */
temp = U128_or(tempC, U128_and(tempB, tempA));
break;
case 88: /* 01011 000 SEL(A,NOR(B,C),C) */
temp = U128_select(tempA, U128_nor(tempB, tempC), tempC);
break;
case 89: /* 01011 001 SEL(A,NXOR(B,C),C) */
temp = U128_select(tempA, U128_nxor(tempB, tempC), tempC);
break;
case 90: /* 01011 010 XOR(C,A) */
temp = U128_xor(tempC, tempA);
break;
case 91: /* 01011 011 SEL(B,OR(A,C),XOR(A,C)) */
temp = U128_select(tempB, U128_or(tempA, tempC), U128_xor(tempA, tempC));
break;
case 92: /* 01011 100 SEL(A,NOT(B),C) */
temp = U128_select(tempA, U128_not(tempB), tempC);
break;
case 93: /* 01011 101 SEL(B,C,OR(A,C)) */
temp = U128_select(tempB, tempC, U128_or(tempA, tempC));
break;
case 94: /* 01011 110 SEL(A,NAND(B,C),C) */
temp = U128_select(tempA, U128_nand(tempB, tempC), tempC);
break;
case 95: /* 01011 111 OR(C,A) */
temp = U128_or(tempC, tempA);
break;
case 96: /* 01100 000 NOR(A,NXOR(B,C)) */
temp = U128_nor(tempA, U128_nxor(tempB, tempC));
break;
case 97: /* 01100 001 SEL(A,AND(B,C),XOR(B,C)) */
temp = U128_select(tempA, U128_and(tempB, tempC), U128_xor(tempB, tempC));
break;
case 98: /* 01100 010 SEL(C,NOR(B,A),B)) */
temp = U128_select(tempC, U128_nor(tempB, tempA), tempB);
break;
case 99: /* 01100 011 SEL(A,B,XOR(B,C)) */
temp = U128_select(tempA, tempB, U128_xor(tempB, tempC));
break;
case 100: /* 01100 100 SEL(B,NOR(A,C),C)) */
temp = U128_select(tempB, U128_nor(tempA, tempC), tempC);
break;
case 101: /* 01100 101 SEL(A,C,XOR(B,C)) */
temp = U128_select(tempA, tempC, U128_xor(tempB, tempC));
break;
case 102: /* 01100 110 XOR(C,B) */
temp = U128_xor(tempC, tempB);
break;
case 103: /* 01100 111 SEL(A,OR(B,C),XOR(B,C)) */
temp = U128_select(tempA, U128_or(tempB, tempC), U128_xor(tempB, tempC));
break;
case 104: /* 01101 000 SEL(A,NOR(B,C),XOR(B,C)) */
temp = U128_select(tempA, U128_nor(tempB, tempC), U128_xor(tempB, tempC));
break;
case 105: /* 01101 001 XOR(A,B,C) */
temp = U128_xor3(tempA, tempB, tempC);
break;
case 106: /* 01101 010 XOR(C,OR(B,A)) */
temp = U128_xor(tempC, U128_or(tempB, tempA));
break;
case 107: /* 01101 011 SEL(C,NXOR(B,A),OR(B,A)) */
temp = U128_select(tempC, U128_nxor(tempB, tempA), U128_or(tempB, tempA));
break;
case 108: /* 01101 100 XOR(B,OR(A,C)) */
temp = U128_xor(tempB, U128_or(tempA, tempC));
break;
case 109: /* 01101 101 SEL(B,NXOR(A,C),OR(A,C)) */
temp = U128_select(tempB, U128_nxor(tempA, tempC), U128_or(tempA, tempC));
break;
case 110: /* 01101 110 SEL(B,NOT(C),OR(A,C)) */
temp = U128_select(tempB, U128_not(tempC), U128_or(tempA, tempC));
break;
case 111: /* 01101 111 OR(A,XOR(B,C)) */
temp = U128_or(tempA, U128_xor(tempB, tempC));
break;
case 112: /* 01110 000 NOR(A,NOR(B,C)) */
temp = U128_nor(tempA, U128_nor(tempB, tempC));
break;
case 113: /* 01110 001 SEL(A,AND(B,C),OR(B,C)) */
temp = U128_select(tempA, U128_and(tempB, tempC), U128_or(tempB, tempC));
break;
case 114: /* 01110 010 SEL(C,NOT(A),B)) */
temp = U128_select(tempC, U128_not(tempA), tempB);
break;
case 115: /* 01110 011 SEL(A,B,OR(B,C)) */
temp = U128_select(tempA, tempB, U128_or(tempB, tempC));
break;
case 116: /* 01110 100 SEL(B,NOT(A),C) */
temp = U128_select(tempB, U128_not(tempA), tempC);
break;
case 117: /* 01110 101 SEL(A,C,OR(B,C)) */
temp = U128_select(tempA, tempC, U128_or(tempB, tempC));
break;
case 118: /* 01110 110 SEL(B,NAND(A,C),C) */
temp = U128_select(tempB, U128_nand(tempA, tempC), tempC);
break;
case 119: /* 01110 111 OR(C,B) */
temp = U128_or(tempC, tempB);
break;
case 120: /* 01111 000 XOR(A,OR(B,C)) */
temp = U128_xor(tempA, U128_or(tempB, tempC));
break;
case 121: /* 01111 001 SEL(A,NXOR(B,C),OR(B,C)) */
temp = U128_select(tempA, U128_nxor(tempB, tempC), U128_or(tempB, tempC));
break;
case 122: /* 01111 010 SEL(A,NOT(C),OR(B,C)) */
temp = U128_select(tempA, U128_not(tempC), U128_or(tempB, tempC));
break;
case 123: /* 01111 011 OR(B,XOR(A,C)) */
temp = U128_or(tempB, U128_xor(tempA, tempC));
break;
case 124: /* 01111 100 SEL(A,NOT(B),OR(B,C)) */
temp = U128_select(tempA, U128_not(tempB), U128_or(tempB, tempC));
break;
case 125: /* 01111 101 OR(C,XOR(B,A)) */
temp = U128_or(tempC, U128_xor(tempB, tempA));
break;
case 126: /* 01111 110 SEL(A,NAND(B,C),OR(B,C)) */
temp = U128_select(tempA, U128_nand(tempB, tempC), U128_or(tempB, tempC));
break;
case 127: /* 01111 111 OR(A,B,C) */
temp = U128_or3(tempA, tempB, tempC);
break;
case 128: /* 10000 000 NOR(A,B,C) */
temp = U128_nor3(tempA, tempB, tempC);
break;
case 129: /* 10000 001 SEL(A,AND(B,C),NOR(B,C)) */
temp = U128_select(tempA, U128_and(tempB, tempC), U128_nor(tempB, tempC));
break;
case 130: /* 10000 000 NOR(C,XOR(B,A)) */
temp = U128_nor(tempC, U128_xor(tempB, tempA));
break;
case 131: /* 10000 011 SEL(A,B,NOR(B,C)) */
temp = U128_select(tempA, tempB, U128_nor(tempB, tempC));
break;
case 132: /* 10000 100 NOR(B,XOR(A,C)) */
temp = U128_nor(tempB, U128_xor(tempA, tempC));
break;
case 133: /* 10000 101 SEL(A,C,NOR(B,C)) */
temp = U128_select(tempA, tempC, U128_nor(tempB, tempC));
break;
case 134: /* 10000 110 SEL(A,XOR(B,C),NOR(B,C)) */
temp = U128_select(tempA, U128_xor(tempB, tempC), U128_nor(tempB, tempC));
break;
case 135: /* 10000 111 NXOR(A,OR(B,C)) */
temp = U128_nxor(tempA, U128_or(tempB, tempC));
break;
case 136: /* 10001 000 NOR(C,B) */
temp = U128_nor(tempC, tempB);
break;
case 137: /* 10001 001 SEL(B,AND(A,C),NOT(C)) */
temp = U128_select(tempB, U128_and(tempA, tempC), U128_not(tempC));
break;
case 138: /* 10001 010 SEL(A,NOT(C),NOR(B,C)) */
temp = U128_select(tempA, U128_not(tempC), U128_nor(tempB, tempC));
break;
case 139: /* 10001 011 SEL(B,A,NOT(C)) */
temp = U128_select(tempB, tempA, U128_not(tempC));
break;
case 140: /* 10001 100 SEL(A,NOT(B),NOR(B,C)) */
temp = U128_select(tempA, U128_not(tempB), U128_nor(tempB, tempC));
break;
case 141: /* 10001 101 SEL(C,A,NOT(B)) */
temp = U128_select(tempC, tempA, U128_not(tempB));
break;
case 142: /* 10001 110 SEL(A,NAND(B,C),NOR(B,C)) */
temp = U128_select(tempA, U128_nand(tempB, tempC), U128_nor(tempB, tempC));
break;
case 143: /* 10001 111 OR(A,NOR(B,C)) */
temp = U128_or(tempA, U128_nor(tempB, tempC));
break;
case 144: /* 10010 000 NOR(A,XOR(B,C)) */
temp = U128_nor(tempA, U128_xor(tempB, tempC));
break;
case 145: /* 10010 001 SEL(B,C,NOR(A,C)) */
temp = U128_select(tempB, tempC, U128_nor(tempA, tempC));
break;
case 146: /* 10010 010 SEL(B,XOR(A,C),NOR(A,C)) */
temp = U128_select(tempB, U128_xor(tempA, tempC), U128_nor(tempA, tempC));
break;
case 147: /* 10010 011 NXOR(B,OR(A,C)) */
temp = U128_nxor(tempB, U128_or(tempA, tempC));
break;
case 148: /* 10010 100 SEL(C,XOR(B,A),NOR(B,A)) */
temp = U128_select(tempC, U128_xor(tempB, tempA), U128_nor(tempB, tempA));
break;
case 149: /* 10010 101 NXOR(C,OR(B,A)) */
temp = U128_nxor(tempC, U128_or(tempB, tempA));
break;
case 150: /* 10010 110 NXOR(A,B,C) */
temp = U128_nxor3(tempA, tempB, tempC);
break;
case 151: /* 10010 111 SEL(A,OR(B,C),NXOR(B,C)) */
temp = U128_select(tempA, U128_or(tempB, tempC), U128_nxor(tempB, tempC));
break;
case 152: /* 10011 000 SEL(A,NOR(B,C),NXOR(B,C)) */
temp = U128_select(tempA, U128_nor(tempB, tempC), U128_nxor(tempB, tempC));
break;
case 153: /* 10011 001 NXOR(C,B) */
temp = U128_nxor(tempC, tempB);
break;
case 154: /* 10011 010 SEL(A,NOT(C),NXOR(B,C)) */
temp = U128_select(tempA, U128_not(tempC), U128_nxor(tempB, tempC));
break;
case 155: /* 10011 011 SEL(B,OR(A,C),NOT(C)) */
temp = U128_select(tempB, U128_or(tempA, tempC), U128_not(tempC));
break;
case 156: /* 10011 100 SEL(A,NOT(B),NXOR(B,C)) */
temp = U128_select(tempA, U128_not(tempB), U128_nxor(tempB, tempC));
break;
case 157: /* 10011 101 SEL(C,OR(B,A),NOT(B)) */
temp = U128_select(tempC, U128_or(tempB, tempA), U128_not(tempB));
break;
case 158: /* 10011 110 SEL(A,NAND(B,C),NXOR(B,C)) */
temp = U128_select(tempA, U128_nand(tempB, tempC), U128_nxor(tempB, tempC));
break;
case 159: /* 10011 111 OR(A,NXOR(B,C)) */
temp = U128_or(tempA, U128_nxor(tempB, tempC));
break;
case 160: /* 10100 000 NOR(C,A) */
temp = U128_nor(tempC, tempA);
break;
case 161: /* 10100 001 SEL(A,AND(B,C),NOT(C)) */
temp = U128_select(tempA, U128_and(tempB, tempC), U128_not(tempC));
break;
case 162: /* 10100 010 SEL(B,NOT(C),NOR(A,C)) */
temp = U128_select(tempB, U128_not(tempC), U128_nor(tempA, tempC));
break;
case 163: /* 10100 011 SEL(A,B,NOT(C)) */
temp = U128_select(tempA, tempB, U128_not(tempC));
break;
case 164: /* 10100 100 SEL(B,NOR(A,C),NXOR(A,C)) */
temp = U128_select(tempB, U128_nor(tempA, tempC), U128_nxor(tempA, tempC));
break;
case 165: /* 10100 101 NXOR(C,A) */
temp = U128_nxor(tempC, tempA);
break;
case 166: /* 10100 110 SEL(A,XOR(B,C),NOT(C) */
temp = U128_select(tempA, U128_xor(tempB, tempC), U128_not(tempC));
break;
case 167: /* 10100 111 SEL(A,OR(B,C),NOT(C)) */
temp = U128_select(tempA, U128_or(tempB, tempC), U128_not(tempC));
break;
case 168: /* 10101 000 NOR(C,AND(B,A)) */
temp = U128_nor(tempC, U128_and(tempB, tempA));
break;
case 169: /* 10101 001 NXOR(C,AND(B,A)) */
temp = U128_nxor(tempC, U128_and(tempB, tempA));
break;
case 170: /* 10101 010 NOT(C) */
temp = U128_not(tempC);
break;
case 171: /* 10101 011 NAND(C,NAND(B,A)) */
temp = U128_nand(tempC, U128_nand(tempB, tempA));
break;
case 172: /* 10101 100 SEL(A,NOT(B),NOT(C)) */
temp = U128_select(tempA, U128_not(tempB), U128_not(tempC));
break;
case 173: /* 10101 101 SEL(C,A,NAND(B,A)) */
temp = U128_select(tempC, tempA, U128_nand(tempB, tempA));
break;
case 174: /* 10101 110 SEL(A,NAND(B,C),NOT(C)) */
temp = U128_select(tempA, U128_nand(tempB, tempC), U128_not(tempC));
break;
case 175: /* 10101 111 OR(A,NOT(C)) */
temp = U128_or(tempA, U128_not(tempC));
break;
case 176: /* 10110 000 SEL(B,NOT(A),NOR(A,C)) */
temp = U128_select(tempB, U128_not(tempA), U128_nor(tempA, tempC));
break;
case 177: /* 10110 001 SEL(C,B,NOT(A) */
temp = U128_select(tempC, tempB, U128_not(tempA));
break;
case 178: /* 10110 010 SEL(B,NAND(A,C),NOR(A,C)) */
temp = U128_select(tempB, U128_nand(tempA, tempC), U128_nor(tempA, tempC));
break;
case 179: /* 10110 011 OR(B,NOR(A,C)) */
temp = U128_or(tempB, U128_nor(tempA, tempC));
break;
case 180: /* 10110 100 SEL(B,NOT(A),NXOR(A,C)) */
temp = U128_select(tempB, U128_not(tempA), U128_nxor(tempA, tempC));
break;
case 181: /* 10110 101 SEL(C,OR(B,A),NOT(A)) */
temp = U128_select(tempC, U128_or(tempB, tempA), U128_not(tempA));
break;
case 182: /* 10110 110 SEL(B,NAND(A,C),NXOR(A,C)) */
temp = U128_select(tempB, U128_nand(tempA, tempC), U128_nxor(tempA, tempC));
break;
case 183: /* 10110 111 OR(B,NXOR(A,C)) */
temp = U128_or(tempB, U128_nxor(tempA, tempC));
break;
case 184: /* 10111 000 SEL(B,NOT(A),NOT(C)) */
temp = U128_select(tempB, U128_not(tempA), U128_not(tempC));
break;
case 185: /* 10111 001 SEL(C,B,NAND(B,A)) */
temp = U128_select(tempC, tempB, U128_nand(tempB, tempA));
break;
case 186: /* 10111 010 SEL(B,NAND(A,C),NOT(C)) */
temp = U128_select(tempB, U128_nand(tempA, tempC), U128_not(tempC));
break;
case 187: /* 10111 011 OR(B,NOT(C)) */
temp = U128_or(tempB, U128_not(tempC));
break;
case 188: /* 10111 100 SEL(C,XOR(B,A),NAND(B,A)) */
temp = U128_select(tempC, U128_xor(tempB, tempA), U128_nand(tempB, tempA));
break;
case 189: /* 10111 101 SEL(C,OR(B,A),NAND(B,A)) */
temp = U128_select(tempC, U128_or(tempB, tempA), U128_nand(tempB, tempA));
break;
case 190: /* 10111 110 NAND(C,NXOR(B,A)) */
temp = U128_nand(tempC, U128_nxor(tempB, tempA));
break;
case 191: /* 10111 111 NAND(C,NOR(B,A)) */
temp = U128_nand(tempC, U128_nor(tempB, tempA));
break;
case 192: /* 11000 000 NOR(B,A) */
temp = U128_nor(tempB, tempA);
break;
case 193: /* 11000 001 SEL(A,AND(B,C),NOT(B)) */
temp = U128_select(tempA, U128_and(tempB, tempC), U128_not(tempB));
break;
case 194: /* 11000 010 SEL(C,NOR(B,A),NXOR(B,A)) */
temp = U128_select(tempC, U128_nor(tempB, tempA), U128_nxor(tempB, tempA));
break;
case 195: /* 11000 011 NXOR(B,A) */
temp = U128_nxor(tempB, tempA);
break;
case 196: /* 11000 100 SEL(C,NOT(B),NOR(B,A)) */
temp = U128_select(tempC, U128_not(tempB), U128_nor(tempB, tempA));
break;
case 197: /* 11000 101 SEL(A,C,NOT(B)) */
temp = U128_select(tempA, tempC, U128_not(tempB));
break;
case 198: /* 11000 110 SEL(A,XOR(B,C),NOT(B) */
temp = U128_select(tempA, U128_xor(tempB, tempC), U128_not(tempB));
break;
case 199: /* 11000 111 SEL(A,OR(B,C),NOT(B)) */
temp = U128_select(tempA, U128_or(tempB, tempC), U128_not(tempB));
break;
case 200: /* 11001 000 NOR(B,AND(A,C)) */
temp = U128_nor(tempB, U128_and(tempA, tempC));
break;
case 201: /* 11001 001 NXOR(B,AND(A,C)) */
temp = U128_nxor(tempB, U128_and(tempA, tempC));
break;
case 202: /* 11001 010 SEL(A,NOT(C),NOT(B)) */
temp = U128_select(tempA, U128_not(tempC), U128_not(tempB));
break;
case 203: /* 11001 011 SEL(B,A,NAND(A,C)) */
temp = U128_select(tempB, tempA, U128_nand(tempA, tempC));
break;
case 204: /* 11001 100 NOT(B) */
temp = U128_not(tempB);
break;
case 205: /* 11001 101 NAND(B,NAND(A,C)) */
temp = U128_nand(tempB, U128_nand(tempA, tempC));
break;
case 206: /* 11001 110 SEL(A,NAND(B,C),NOT(B)) */
temp = U128_select(tempA, U128_nand(tempB, tempC), U128_not(tempB));
break;
case 207: /* 11001 111 OR(A,NOT(B)) */
temp = U128_or(tempA, U128_not(tempB));
break;
case 208: /* 11010 000 SEL(C,NOT(A),NOR(B,A)) */
temp = U128_select(tempC, U128_not(tempA), U128_nor(tempB, tempA));
break;
case 209: /* 11010 001 SEL(B,C,NOT(A)) */
temp = U128_select(tempB, tempC, U128_not(tempA));
break;
case 210: /* 11010 010 SEL(B,XOR(A,C),NOT(A) */
temp = U128_select(tempB, U128_xor(tempA, tempC), U128_not(tempA));
break;
case 211: /* 11010 011 SEL(B,OR(A,C),NOT(A)) */
temp = U128_select(tempB, U128_or(tempA, tempC), U128_not(tempA));
break;
case 212: /* 11010 100 SEL(C,NAND(B,A),NOR(B,A)) */
temp = U128_select(tempC, U128_nand(tempB, tempA), U128_nor(tempB, tempA));
break;
case 213: /* 11010 101 OR(C,NOR(B,A)) */
temp = U128_or(tempC, U128_nor(tempB, tempA));
break;
case 214: /* 11010 110 SEL(C,NAND(B,A),NXOR(B,A)) */
temp = U128_select(tempC, U128_nand(tempB, tempA), U128_nxor(tempB, tempA));
break;
case 215: /* 11010 111 OR(C,NXOR(B,A)) */
temp = U128_or(tempC, U128_nxor(tempB, tempA));
break;
case 216: /* 11011 000 SEL(C,NOT(A),NOT(B)) */
temp = U128_select(tempC, U128_not(tempA), U128_not(tempB));
break;
case 217: /* 11011 001 SEL(B,C,NAND(A,C)) */
temp = U128_select(tempB, tempC, U128_nand(tempA, tempC));
break;
case 218: /* 11011 010 SEL(B,XOR(A,C),NAND(A,C)) */
temp = U128_select(tempB, U128_xor(tempA, tempC), U128_nand(tempA, tempC));
break;
case 219: /* 11011 011 SEL(B,OR(A,C),NAND(A,C)) */
temp = U128_select(tempB, U128_or(tempA, tempC), U128_nand(tempA, tempC));
break;
case 220: /* 11011 100 SEL(C,NAND(B,A),NOT(B)) */
temp = U128_select(tempC, U128_nand(tempB, tempA), U128_not(tempB));
break;
case 221: /* 11011 101 OR(C,NOT(B)) */
temp = U128_or(tempC, U128_not(tempB));
break;
case 222: /* 11011 110 NAND(B,NXOR(A,C)) */
temp = U128_nand(tempB, U128_nxor(tempA, tempC));
break;
case 223: /* 11011 111 NAND(B,NOR(A,C)) */
temp = U128_nand(tempB, U128_nor(tempA, tempC));
break;
case 224: /* 11100 000 NOR(A,AND(B,C)) */
temp = U128_nor(tempA, U128_and(tempB, tempC));
break;
case 225: /* 11100 001 NXOR(A,AND(B,C)) */
temp = U128_nxor(tempA, U128_and(tempB, tempC));
break;
case 226: /* 11100 010 SEL(B,NOT(C),NOT(A)) */
temp = U128_select(tempB, U128_not(tempC), U128_not(tempA));
break;
case 227: /* 11100 011 SEL(A,B,NAND(B,C)) */
temp = U128_select(tempA, tempB, U128_nand(tempB, tempC));
break;
case 228: /* 11100 100 SEL(C,NOT(B),NOT(A)) */
temp = U128_select(tempC, U128_not(tempB), U128_not(tempA));
break;
case 229: /* 11100 101 SEL(A,C,NAND(B,C)) */
temp = U128_select(tempA, tempC, U128_nand(tempB, tempC));
break;
case 230: /* 11100 110 SEL(A,XOR(B,C),NAND(B,C)) */
temp = U128_select(tempA, U128_xor(tempB, tempC), U128_nand(tempB, tempC));
break;
case 231: /* 11100 111 SEL(A,OR(B,C),NAND(B,C)) */
temp = U128_select(tempA, U128_or(tempB, tempC), U128_nand(tempB, tempC));
break;
case 232: /* 11101 000 MINOR(A,B,C) */
temp = U128_minor(tempA, tempB, tempC);
break;
case 233: /* 11101 001 SEL(A,NXOR(B,C),NAND(B,C)) */
temp = U128_select(tempA, U128_nxor(tempB, tempC), U128_nand(tempB, tempC));
break;
case 234: /* 11101 010 NAND(C,OR(B,A)) */
temp = U128_nand(tempC, U128_or(tempB, tempA));
break;
case 235: /* 11011 011 NAND(C,XOR(B,A)) */
temp = U128_nand(tempC, U128_xor(tempB, tempA));
break;
case 236: /* 11101 100 NAND(B,OR(A,C)) */
temp = U128_nand(tempB, U128_or(tempA, tempC));
break;
case 237: /* 11101 101 NAND(B,XOR(A,C)) */
temp = U128_nand(tempB, U128_xor(tempA, tempC));
break;
case 238: /* 11101 110 NAND(C,B) */
temp = U128_nand(tempC, tempB);
break;
case 239: /* 11101 111 OR(A,NAND(B,C)) */
temp = U128_or(tempA, U128_nand(tempB, tempC));
break;
case 240: /* 11110 000 NOT(A) */
temp = U128_not(tempA);
break;
case 241: /* 11110 001 NAND(A,NAND(B,C)) */
temp = U128_nand(tempA, U128_nand(tempB, tempC));
break;
case 242: /* 11110 010 SEL(B,NAND(A,C),NOT(A)) */
temp = U128_select(tempB, U128_nand(tempA, tempC), U128_not(tempA));
break;
case 243: /* 11110 011 OR(B,NOT(A)) */
temp = U128_or(tempB, U128_not(tempA));
break;
case 244: /* 11110 100 SEL(C,NAND(B,A),NOT(A)) */
temp = U128_select(tempC, U128_nand(tempB, tempA), U128_not(tempA));
break;
case 245: /* 11110 101 OR(C,NOT(A)) */
temp = U128_or(tempC, U128_not(tempA));
break;
case 246: /* 11110 110 NAND(A,NXOR(B,C)) */
temp = U128_nand(tempA, U128_nxor(tempB, tempC));
break;
case 247: /* 11110 111 NAND(A,NOR(B,C)) */
temp = U128_nand(tempA, U128_nor(tempB, tempC));
break;
case 248: /* 11111 000 NAND(A,OR(B,C)) */
temp = U128_nand(tempA, U128_or(tempB, tempC));
break;
case 249: /* 11111 001 NAND(A,XOR(B,C)) */
temp = U128_nand(tempA, U128_xor(tempB, tempC));
break;
case 250: /* 11111 010 NAND(C,A) */
temp = U128_nand(tempC, tempA);
break;
case 251: /* 11111 011 OR(B,NAND(A,C)) */
temp = U128_or(tempB, U128_nand(tempA, tempC));
break;
case 252: /* 11111 100 NAND(B,A) */
temp = U128_nand(tempB, tempA);
break;
case 253: /* 11111 101 OR(C,NAND(B,A)) */
temp = U128_or(tempC, U128_nand(tempB, tempA));
break;
case 254: /* 11111 110 NAND(A,B,C) */
temp = U128_nand3(tempA, tempB, tempC);
break;
case 255: /* 11111 111 TRUE */
temp = U128_minus_one();
break;
default: /* Should not occur! */
UNREACHABLE_CODE(temp = U128_zero());
}
regs->VR_Q(v1) = temp.Q;
ZVECTOR_END( regs );
}
#endif /* defined( FEATURE_198_VECTOR_ENH_FACILITY_3 ) */
#if defined( FEATURE_198_VECTOR_ENH_FACILITY_3 )
/*-------------------------------------------------------------------*/
/* E789 VBLEND - Vector Blend [VRR-d] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_blend )
{
int v1, v2, v3, v4, m5, m6;
int i;
VRR_D( inst, regs, v1, v2, v3, v4, m5, m6 );
/* m6 is not part of this instruction */
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
switch (m5)
{
case 0: /* Byte */
for (i=0; i<16; i++)
{
if (regs->VR_B(v4, i) & 0x80)
regs->VR_B(v1, i) = regs->VR_B(v2, i);
else
regs->VR_B(v1, i) = regs->VR_B(v3, i);
}
break;
case 1: /* Halfword */
for (i=0; i<8; i++)
{
if (regs->VR_H(v4, i) & 0x8000)
regs->VR_H(v1, i) = regs->VR_H(v2, i);
else
regs->VR_H(v1, i) = regs->VR_H(v3, i);
}
break;
case 2: /* Word */
for (i=0; i<4; i++)
{
if (regs->VR_F(v4, i) & 0x80000000)
regs->VR_F(v1, i) = regs->VR_F(v2, i);
else
regs->VR_F(v1, i) = regs->VR_F(v3, i);
}
break;
case 3: /* Doublword */
for (i=0; i<2; i++)
{
if (regs->VR_D(v4, i) & 0x8000000000000000ull )
regs->VR_D(v1, i) = regs->VR_D(v2, i);
else
regs->VR_D(v1, i) = regs->VR_D(v3, i);
}
break;
case 4: /* Quadword */
if (regs->VR_D(v4, 0) & 0x8000000000000000ull )
{
regs->VR_D(v1, 0) = regs->VR_D(v2, 0);
regs->VR_D(v1, 1) = regs->VR_D(v2, 1);
}
else
{
regs->VR_D(v1, 0) = regs->VR_D(v3, 0);
regs->VR_D(v1, 1) = regs->VR_D(v3, 1);
}
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
#endif /* defined( FEATURE_198_VECTOR_ENH_FACILITY_3 ) */
/*-------------------------------------------------------------------*/
/* E78A VSTRC - Vector String Range Compare [VRR-d] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_string_range_compare )
{
int v1, v2, v3, v4, m5, m6;
int i, j;
int lxt1, lxt2; // Lowest indexed true
int mxt; // Maximum indexed true
BYTE irt1[16], irt2[16]; // First and second intermediate results
BYTE erc, orc; // Even and Odd range comparison results
VRR_D( inst, regs, v1, v2, v3, v4, m5, m6 );
ZVECTOR_CHECK( regs );
#define M6_IN ((m6 & 0x8) != 0) // Invert Result
#define M6_RT ((m6 & 0x4) != 0) // Result Type
#define M6_ZS ((m6 & 0x2) != 0) // Zero Search
#define M6_CS ((m6 & 0x1) != 0) // Condition Code Set
for (i=0; i<16; i++)
{
irt1[i] = irt2[i] = FALSE;
}
switch (m5)
{
case 0: /* Byte */
for (i=0; i<16; i++)
{
// Compare the element of the second operand with the ranges
for (j=0; j<16; j+=2)
{
erc = orc = FALSE;
// Compare the element of the second operand with the even element of the third operand.
if ((regs->VR_B(v4, j) & 0x80) && regs->VR_B(v2, i) == regs->VR_B(v3, j)) erc = TRUE;
if ((regs->VR_B(v4, j) & 0x40) && regs->VR_B(v2, i) < regs->VR_B(v3, j)) erc = TRUE;
if ((regs->VR_B(v4, j) & 0x20) && regs->VR_B(v2, i) > regs->VR_B(v3, j)) erc = TRUE;
// Compare the element of the second operand with the odd element of the third operand.
if ((regs->VR_B(v4, j+1) & 0x80) && regs->VR_B(v2, i) == regs->VR_B(v3, j+1)) orc = TRUE;
if ((regs->VR_B(v4, j+1) & 0x40) && regs->VR_B(v2, i) < regs->VR_B(v3, j+1)) orc = TRUE;
if ((regs->VR_B(v4, j+1) & 0x20) && regs->VR_B(v2, i) > regs->VR_B(v3, j+1)) orc = TRUE;
// Determine the result of the range comparison
if (erc == TRUE && orc == TRUE) irt1[i] = TRUE;
}
// Invert the ranges result if required
if (M6_IN) irt1[i] ^= TRUE;
// Compare the element of the second operand with zero
if (M6_ZS && regs->VR_B(v2,i) == 0) irt2[i] = TRUE;
}
if (M6_RT) // if M6_RT (Result Type)
{
for (i=0; i<16; i++)
{
regs->VR_B(v1, i) = (irt1[i] == TRUE) ? 0xFF : 0x00;
}
}
else // else !M6_RT
{
lxt1 = lxt2 = 16;
for (i=0; i<16; i++)
{
if (irt1[i] == TRUE && lxt1 == 16) lxt1 = i;
if (irt2[i] == TRUE && lxt2 == 16) lxt2 = i;
}
regs->VR_D(v1, 0) = min(lxt1, lxt2);
regs->VR_D(v1, 1) = 0;
}
break;
case 1: /* Halfword */
for (i=0; i<8; i++)
{
// Compare the element of the second operand with the ranges
for (j=0; j<8; j+=2)
{
erc = orc = FALSE;
// Compare the element of the second operand with the even element of the third operand.
if ((regs->VR_H(v4, j) & 0x8000) && regs->VR_H(v2, i) == regs->VR_H(v3, j)) erc = TRUE;
if ((regs->VR_H(v4, j) & 0x4000) && regs->VR_H(v2, i) < regs->VR_H(v3, j)) erc = TRUE;
if ((regs->VR_H(v4, j) & 0x2000) && regs->VR_H(v2, i) > regs->VR_H(v3, j)) erc = TRUE;
// Compare the element of the second operand with the odd element of the third operand.
if ((regs->VR_H(v4, j+1) & 0x8000) && regs->VR_H(v2, i) == regs->VR_H(v3, j+1)) orc = TRUE;
if ((regs->VR_H(v4, j+1) & 0x4000) && regs->VR_H(v2, i) < regs->VR_H(v3, j+1)) orc = TRUE;
if ((regs->VR_H(v4, j+1) & 0x2000) && regs->VR_H(v2, i) > regs->VR_H(v3, j+1)) orc = TRUE;
// Determine the result of the range comparison
if (erc == TRUE && orc == TRUE) irt1[i] = TRUE;
}
// Invert the ranges result if required
if (M6_IN) irt1[i] ^= TRUE;
// Compare the element of the second operand with zero
if (M6_ZS && regs->VR_H(v2,i) == 0) irt2[i] = TRUE;
}
if (M6_RT) // if M6_RT (Result Type)
{
for (i=0; i<8; i++)
{
regs->VR_H(v1, i) = (irt1[i] == TRUE) ? 0xFFFF : 0x0000;
}
}
else // else !M6_RT
{
lxt1 = lxt2 = 16;
for (i=0; i<8; i++)
{
if (irt1[i] == TRUE && lxt1 == 16) lxt1 = i * 2;
if (irt2[i] == TRUE && lxt2 == 16) lxt2 = i * 2;
}
regs->VR_D(v1, 0) = min(lxt1, lxt2);
regs->VR_D(v1, 1) = 0;
}
break;
case 2: /* Word */
for (i=0; i<4; i++)
{
// Compare the element of the second operand with the ranges
for (j=0; j<4; j+=2)
{
erc = orc = FALSE;
// Compare the element of the second operand with the even element of the third operand.
if ((regs->VR_F(v4, j) & 0x80000000) && regs->VR_F(v2, i) == regs->VR_F(v3, j)) erc = TRUE;
if ((regs->VR_F(v4, j) & 0x40000000) && regs->VR_F(v2, i) < regs->VR_F(v3, j)) erc = TRUE;
if ((regs->VR_F(v4, j) & 0x20000000) && regs->VR_F(v2, i) > regs->VR_F(v3, j)) erc = TRUE;
// Compare the element of the second operand with the odd element of the third operand.
if ((regs->VR_F(v4, j+1) & 0x80000000) && regs->VR_F(v2, i) == regs->VR_F(v3, j+1)) orc = TRUE;
if ((regs->VR_F(v4, j+1) & 0x40000000) && regs->VR_F(v2, i) < regs->VR_F(v3, j+1)) orc = TRUE;
if ((regs->VR_F(v4, j+1) & 0x20000000) && regs->VR_F(v2, i) > regs->VR_F(v3, j+1)) orc = TRUE;
// Determine the result of the range comparison
if (erc == TRUE && orc == TRUE) irt1[i] = TRUE;
}
// Invert the ranges result if required
if (M6_IN) irt1[i] ^= TRUE;
// Compare the element of the second operand with zero
if (M6_ZS && regs->VR_F(v2,i) == 0) irt2[i] = TRUE;
}
if (M6_RT) // if M6_RT (Result Type)
{
for (i=0; i<4; i++)
{
regs->VR_F(v1, i) = (irt1[i] == TRUE) ? 0xFFFFFFFF : 0x00000000;
}
}
else // else !M6_RT
{
lxt1 = lxt2 = 16;
for (i=0; i<4; i++)
{
if (irt1[i] == TRUE && lxt1 == 16) lxt1 = i * 4;
if (irt2[i] == TRUE && lxt2 == 16) lxt2 = i * 4;
}
regs->VR_D(v1, 0) = min(lxt1, lxt2);
regs->VR_D(v1, 1) = 0;
}
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
if (M6_CS) // if M6_CS (Condition Code Set)
{
switch (m5)
{
case 0: /* Byte */
lxt1 = lxt2 = mxt = 16;
break;
case 1: /* Halfword */
lxt1 = lxt2 = mxt = 8;
break;
case 2: /* Word */
lxt1 = lxt2 = mxt = 4;
break;
default: // Prevent erroneous "may be used uninitialized" warnings
lxt1 = lxt2 = mxt = 0;
break;
}
for (i = 0; i < mxt; i++)
{
if (irt1[i] == TRUE && lxt1 == mxt)
lxt1 = i;
if (M6_ZS) // if M6_ZS (Zero Search)
{
if (irt2[i] == TRUE && lxt2 == mxt)
lxt2 = i;
}
}
// cc 1 and 3 are possible when M6_ZS is 0 or 1.
if (lxt1 == mxt && lxt2 == mxt)
regs->psw.cc = 3;
else if (lxt1 < mxt && lxt2 == mxt )
regs->psw.cc = 1;
// cc 0 and 2 are only possible when M6_ZS is 1.
else if (lxt1 < lxt2)
regs->psw.cc = 2;
else
regs->psw.cc = 0;
}
#undef M6_IN
#undef M6_RT
#undef M6_ZS
#undef M6_CS
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E78B VSTRS - Vector String Search [VRR-d] */
/*-------------------------------------------------------------------*/
/* */
/* In PoP (SA22-7832-13), for VSTRS we can read: */
/* Byte element seven of the fourth operand specifies */
/* the length of the substring in bytes and must be in */
/* the range of 0-16. Other values will result in an */
/* unpredictable result. */
/* */
/* However, empirical evidence suggests that any value larger than */
/* 16 is treated as 16. This may be model dependant behaviour, but */
/* this implementation will follow a models (z15) behaviour. */
/* */
DEF_INST( vector_string_search )
{
int v1, v2, v3, v4, m5, m6;
char v2_temp[16], v3_temp[16], nulls[16];
int substr_len, char_size, str_len, eos, i, k;
VRR_D( inst, regs, v1, v2, v3, v4, m5, m6 );
ZVECTOR_CHECK( regs );
#define M6_RE ((m6 & 0xD) != 0) // Reserved
#define M6_ZS ((m6 & 0x2) != 0) // Zero Search
if (m5 > 2 || M6_RE)
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
/* Get the contents of v2 and v3 as a string of bytes arranged */
/* as they would be if they were in the guests storage. */
for (i = 0; i < 16; i++)
{
v2_temp[i] = regs->VR_B( v2, i );
v3_temp[i] = regs->VR_B( v3, i );
}
substr_len = regs->VR_B( v4, 7 );
switch (m5)
{
case 0:
char_size = 1;
break;
case 1:
char_size = 2;
break;
case 2:
char_size = 4;
break;
default: // Prevent erroneous "may be used uninitialized" warnings
char_size = 1;
break;
}
str_len = eos = i = k = 0;
if (M6_ZS)
{
memset( nulls, 0, sizeof(nulls) );
for (i = 0; i < 16; i += char_size)
{
if ( memcmp(&v3_temp[i], &nulls, char_size) == 0 )
{
break;
}
}
if ( i < substr_len )
{
substr_len = i;
}
if (substr_len == 0)
{
goto vector_string_search_full_match;
}
else
{
if (substr_len > 16)
{
substr_len = 16;
}
for ( ; k < 16 ; k += char_size )
{
if ( memcmp(&v2_temp[k], &nulls, char_size) == 0 )
{
eos = 1;
break;
}
}
str_len = k;
k = 0;
if ( (substr_len % char_size) != 0 )
{
goto vector_string_search_mdresult;
}
for ( ; ; k += char_size )
{
if ( k < str_len )
{
if ( eos == 0 || ( k + substr_len ) <= str_len )
{
if ((k + substr_len) <= str_len)
{
if ( memcmp(&v2_temp[k], &v3_temp[0], substr_len) == 0 )
{
goto vector_string_search_full_match;
}
}
else
{
if ( memcmp(&v2_temp[k], &v3_temp[0], str_len - k ) == 0 )
{
goto vector_string_search_partial_match;
}
}
}
else
{
goto vector_string_search_no_match_zero;
}
}
else
{
goto vector_string_search_no_match_zero;
}
}
}
}
else
{
if ( substr_len == 0 )
{
goto vector_string_search_full_match;
}
else
{
if ( (substr_len % char_size) != 0 )
{
goto vector_string_search_mdresult;
}
if (substr_len > 16)
{
substr_len = 16;
}
for ( ; ; k += char_size )
{
if (k == 16)
{
goto vector_string_search_no_match;
}
if ((k + substr_len) <= 16)
{
if ( memcmp(&v2_temp[k], &v3_temp[0], substr_len) == 0 )
{
goto vector_string_search_full_match;
}
}
else
{
if ( memcmp(&v2_temp[k], &v3_temp[0], 16 - k) == 0 )
{
goto vector_string_search_partial_match;
}
}
}
}
}
UNREACHABLE_CODE( goto vector_string_search_mdresult );
vector_string_search_mdresult:
regs->VR_D( v1, 0 ) = 16; /* Model dependant */
regs->VR_D( v1, 1 ) = 0; /* results are */
regs->psw.cc = 0; /* no match */ /* unpredictable */
goto vector_string_search_end;
vector_string_search_no_match:
regs->VR_D( v1, 0 ) = 16;
regs->VR_D( v1, 1 ) = 0;
regs->psw.cc = 0; /* no match */
goto vector_string_search_end;
vector_string_search_no_match_zero:
regs->VR_D( v1, 0 ) = 16;
regs->VR_D( v1, 1 ) = 0;
if ( eos == 1 )
regs->psw.cc = 1; /* no match, zero char */
else
regs->psw.cc = 0; /* no match */
goto vector_string_search_end;
vector_string_search_full_match:
regs->VR_D( v1, 0 ) = k;
regs->VR_D( v1, 1 ) = 0;
regs->psw.cc = 2; /* full match */
goto vector_string_search_end;
vector_string_search_partial_match:
regs->VR_D( v1, 0 ) = k;
regs->VR_D( v1, 1 ) = 0;
regs->psw.cc = 3; /* partial match */
goto vector_string_search_end;
vector_string_search_end:
#undef M6_RE
#undef M6_ZS
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E78C VPERM - Vector Permute [VRR-e] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_permute )
{
int v1, v2, v3, v4, m5, m6;
int i, j;
SV temp;
VRR_E( inst, regs, v1, v2, v3, v4, m5, m6 );
/* m5, m6 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
SV_D( temp, 0 ) = regs->VR_D( v2, 0 );
SV_D( temp, 1 ) = regs->VR_D( v2, 1 );
SV_D( temp, 2 ) = regs->VR_D( v3, 0 );
SV_D( temp, 3 ) = regs->VR_D( v3, 1 );
for (i = 0; i < 16; i++) {
j = regs->VR_B(v4, i) & 0x1f;
regs->VR_B(v1, i) = SV_B( temp, j );
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E78D VSEL - Vector Select [VRR-e] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_select )
{
int v1, v2, v3, v4, m5, m6;
VRR_E( inst, regs, v1, v2, v3, v4, m5, m6 );
/* m5, m6 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
regs->VR_D(v1, 1) = (regs->VR_D(v4, 1) & regs->VR_D(v2, 1)) | (~regs->VR_D(v4, 1) & regs->VR_D(v3, 1));
regs->VR_D(v1, 0) = (regs->VR_D(v4, 0) & regs->VR_D(v2, 0)) | (~regs->VR_D(v4, 0) & regs->VR_D(v3, 0));
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E794 VPK - Vector Pack [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_pack )
{
int v1, v2, v3, m4, m5, m6;
int i;
SV temp;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m5, m6 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
SV_D( temp, 0 ) = regs->VR_D( v2, 0 );
SV_D( temp, 1 ) = regs->VR_D( v2, 1 );
SV_D( temp, 2 ) = regs->VR_D( v3, 0 );
SV_D( temp, 3 ) = regs->VR_D( v3, 1 );
switch (m4)
{
case 1: /* Halfword: Low-order bytes from halfwords */
for ( i = 0; i < 16; i++ )
{
regs->VR_B( v1, i ) = SV_B( temp, (i*2)+1 );
}
break;
case 2: /* Word: Low-order halfwords from words */
for ( i = 0; i < 8; i++ )
{
regs->VR_H( v1, i ) = SV_H( temp, (i*2)+1 );
}
break;
case 3: /* Doubleword: Low-order words from doublewords */
for ( i = 0; i < 4; i++ )
{
regs->VR_F( v1, i ) = SV_F( temp, (i*2)+1 );
}
break;
default:
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E795 VPKLS - Vector Pack Logical Saturate [VRR-b] */
/*-------------------------------------------------------------------*/
DEF_INST(vector_pack_logical_saturate)
{
int v1, v2, v3, m4, m5;
int sat, allsat, i;
BYTE newcc;
SV temp;
VRR_B( inst, regs, v1, v2, v3, m4, m5 );
ZVECTOR_CHECK( regs );
#define M5_CS ((m5 & 0x1) != 0) // Condition Code Set
SV_D( temp, 0 ) = regs->VR_D( v2, 0 );
SV_D( temp, 1 ) = regs->VR_D( v2, 1 );
SV_D( temp, 2 ) = regs->VR_D( v3, 0 );
SV_D( temp, 3 ) = regs->VR_D( v3, 1 );
sat = allsat = 0;
switch (m4)
{
case 1: /* Halfword: Low-order bytes from halfwords */
for ( i = 0; i < 16; i++ )
{
if ( SV_H( temp, i ) <= 0x00FF )
{
regs->VR_B( v1, i ) = SV_B( temp, (i*2)+1 );
}
else
{
regs->VR_B( v1, i ) = 0xFF;
sat++;
}
}
allsat = 16;
break;
case 2: /* Word: Low-order halfwords from words */
for ( i = 0; i < 8; i++ )
{
if ( SV_F( temp, i ) <= 0x0000FFFF )
{
regs->VR_H( v1, i ) = SV_H( temp, (i*2)+1 );
}
else
{
regs->VR_H( v1, i ) = 0xFFFF;
sat++;
}
}
allsat = 8;
break;
case 3: /* Doubleword: Low-order words from doublewords */
for ( i = 0; i < 4; i++ )
{
if ( SV_D( temp, i ) <= 0x00000000FFFFFFFFull )
{
regs->VR_F( v1, i ) = SV_F( temp, (i*2)+1 );
}
else
{
regs->VR_F( v1, i ) = 0xFFFFFFFF;
sat++;
}
}
allsat = 4;
break;
default:
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
break;
}
if (M5_CS) // if M5_CS (Condition Code Set)
{
if ( sat >= allsat )
{
newcc = 3; // Saturation on all elements
}
else if ( sat != 0 )
{
newcc = 1; // At least one but not all elements saturated
}
else
{
newcc = 0; // No saturation
}
regs->psw.cc = newcc;
}
#undef M5_CS
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E797 VPKS - Vector Pack Saturate [VRR-b] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_pack_saturate )
{
int v1, v2, v3, m4, m5;
int sat, allsat, i;
BYTE newcc;
SV temp;
VRR_B( inst, regs, v1, v2, v3, m4, m5 );
ZVECTOR_CHECK( regs );
#define M5_CS ((m5 & 0x1) != 0) // Condition Code Set
SV_D( temp, 0 ) = regs->VR_D( v2, 0 );
SV_D( temp, 1 ) = regs->VR_D( v2, 1 );
SV_D( temp, 2 ) = regs->VR_D( v3, 0 );
SV_D( temp, 3 ) = regs->VR_D( v3, 1 );
sat = allsat = 0;
switch (m4)
{
case 1: /* Halfword: Low-order bytes from halfwords */
for ( i = 0; i < 16; i++ )
{
if ( !( SV_H( temp, i ) & 0x8000 ) )
{
if ( SV_H( temp, i ) <= 0x007F )
{
regs->VR_B( v1, i ) = SV_B( temp, (i*2)+1 );
}
else
{
regs->VR_B( v1, i ) = 0x7F;
sat++;
}
}
else
{
if ( (S16)SV_H( temp, i ) >= (S16)0xFF80 )
{
regs->VR_B( v1, i ) = SV_B( temp, (i*2)+1 );
}
else
{
regs->VR_B( v1, i ) = 0x80;
sat++;
}
}
}
allsat = 16;
break;
case 2: /* Word: Low-order halfwords from words */
for ( i = 0; i < 8; i++ )
{
if ( !( SV_F( temp, i ) & 0x80000000 ) )
{
if ( SV_F( temp, i ) <= 0x00007FFF )
{
regs->VR_H( v1, i ) = SV_H( temp, (i*2)+1 );
}
else
{
regs->VR_H( v1, i ) = 0x7FFF;
sat++;
}
}
else
{
if ( (S32)SV_F( temp, i ) >= (S32)0xFFFF8000 )
{
regs->VR_H( v1, i ) = SV_H( temp, (i*2)+1 );
}
else
{
regs->VR_H( v1, i ) = 0x8000;
sat++;
}
}
}
allsat = 8;
break;
case 3: /* Doubleword: Low-order words from doublewords */
for ( i = 0; i < 4; i++ )
{
if ( !( SV_D( temp, i ) & 0x8000000000000000ull ) )
{
if ( SV_D( temp, i ) <= 0x000000007FFFFFFFull )
{
regs->VR_F( v1, i ) = SV_F( temp, (i*2)+1 );
}
else
{
regs->VR_F( v1, i ) = 0x7FFFFFFF;
sat++;
}
}
else
{
if ( (S64)SV_D( temp, i ) >= (S64)0xFFFFFFFF80000000ull )
{
regs->VR_F( v1, i ) = SV_F( temp, (i*2)+1 );
}
else
{
regs->VR_F( v1, i ) = 0x80000000;
sat++;
}
}
}
allsat = 4;
break;
default:
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
break;
}
if (M5_CS) // if M5_CS (Condition Code Set)
{
if ( sat >= allsat )
{
newcc = 3; // Saturation on all elements
}
else if ( sat != 0 )
{
newcc = 1; // At least one but not all elements saturated
}
else
{
newcc = 0; // No saturation
}
regs->psw.cc = newcc;
}
#undef M5_CS
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7A1 VMLH - Vector Multiply Logical High [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_multiply_logical_high )
{
int v1, v2, v3, m4, m5, m6;
union { U64 d; U32 f; U16 h; } temp;
U128 u128temp1;
int i;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m5, m6 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
if ( (m4 == 3 || m4 == 4) && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m4)
{
case 0: /* Byte */
for (i=0; i < 16; i++)
{
temp.h = regs->VR_B(v2, i);
temp.h *= regs->VR_B(v3, i);
regs->VR_B(v1, i) = temp.h >> 8;
}
break;
case 1: /* Halfword */
for (i=0; i < 8; i++)
{
temp.f = regs->VR_H(v2, i);
temp.f *= regs->VR_H(v3, i);
regs->VR_H(v1, i) = temp.f >> 16;
}
break;
case 2: /* Word */
for (i=0; i < 4; i++)
{
temp.d = regs->VR_F(v2, i);
temp.d *= regs->VR_F(v3, i);
regs->VR_F(v1, i) = temp.d >> 32;
}
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++)
{
u128temp1 = U128_mul_64( regs->VR_D(v2, i), regs->VR_D(v3, i) );
regs->VR_D(v1, i) = u128temp1.Q.D.H.D;
}
break;
case 4: /* Quadword */
{
U128 tempv2, tempv3;
U128 temphi, templo;
tempv2.Q = regs->VR_Q(v2);
tempv3.Q = regs->VR_Q(v3);
U128_mul( tempv2, tempv3, &temphi, &templo );
regs->VR_Q(v1) = temphi.Q;
}
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7A2 VML - Vector Multiply Low [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_multiply_low )
{
int v1, v2, v3, m4, m5, m6;
union { U64 d; U32 f; U16 h; } temp;
U128 u128temp1;
int i;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m5, m6 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
if ( (m4 == 3 || m4 == 4) && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m4)
{
case 0: /* Byte */
for (i=0; i < 16; i++)
{
temp.h = regs->VR_B(v2, i);
temp.h *= regs->VR_B(v3, i);
regs->VR_B(v1, i) = temp.h & 0xFF;
}
break;
case 1: /* Halfword */
for (i=0; i < 8; i++)
{
temp.f = regs->VR_H(v2, i);
temp.f *= regs->VR_H(v3, i);
regs->VR_H(v1, i) = temp.f & 0xFFFF;
}
break;
case 2: /* Word */
for (i=0; i < 4; i++)
{
temp.d = regs->VR_F(v2, i);
temp.d *= regs->VR_F(v3, i);
regs->VR_F(v1, i) = temp.d & 0xFFFFFFFF;
}
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++)
{
u128temp1 = S128_mul_64( regs->VR_D(v2, i), regs->VR_D(v3, i) );
regs->VR_D(v1, i) = u128temp1.Q.D.L.D;
}
break;
case 4: /* Quadword */
{
U128 tempv2, tempv3;
U128 temphi, templo;
tempv2.Q = regs->VR_Q(v2);
tempv3.Q = regs->VR_Q(v3);
S128_mul( tempv2, tempv3, &temphi, &templo );
regs->VR_Q(v1) = templo.Q;
}
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7A3 VMH - Vector Multiply High [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_multiply_high )
{
int v1, v2, v3, m4, m5, m6;
union { S64 sd; S32 sf; S16 sh; } temp;
U128 u128temp1;
int i;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m5, m6 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
if ( (m4 == 3 || m4 == 4) && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m4)
{
case 0: /* Byte */
for (i=0; i < 16; i++)
{
temp.sh = (S8)regs->VR_B(v2, i);
temp.sh *= (S8)regs->VR_B(v3, i);
regs->VR_B(v1, i) = temp.sh >> 8;
}
break;
case 1: /* Halfword */
for (i=0; i < 8; i++)
{
temp.sf = (S16)regs->VR_H(v2, i);
temp.sf *= (S16)regs->VR_H(v3, i);
regs->VR_H(v1, i) = temp.sf >> 16;
}
break;
case 2: /* Word */
for (i=0; i < 4; i++)
{
temp.sd = (S32)regs->VR_F(v2, i);
temp.sd *= (S32)regs->VR_F(v3, i);
regs->VR_F(v1, i) = temp.sd >> 32;
}
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++)
{
u128temp1 = S128_mul_64( regs->VR_D(v2, i), regs->VR_D(v3, i) );
regs->VR_D(v1, i) = u128temp1.Q.D.H.D;
}
break;
case 4: /* Quadword */
{
U128 tempv2, tempv3;
U128 temphi, templo;
tempv2.Q = regs->VR_Q(v2);
tempv3.Q = regs->VR_Q(v3);
S128_mul( tempv2, tempv3, &temphi, &templo );
regs->VR_Q(v1) = temphi.Q;
}
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7A4 VMLE - Vector Multiply Logical Even [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_multiply_logical_even )
{
int v1, v2, v3, m4, m5, m6;
union { U64 d; U32 f; U16 h; } temp;
U128 u128temp1;
int i, j;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m5, m6 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
if ( m4 == 3 && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m4)
{
case 0: /* Byte */
for (i=0, j=0; i < 16; i+=2, j++)
{
temp.h = regs->VR_B(v2, i);
temp.h *= regs->VR_B(v3, i);
regs->VR_H(v1, j) = temp.h;
}
break;
case 1: /* Halfword */
for (i=0, j=0; i < 8; i+=2, j++)
{
temp.f = regs->VR_H(v2, i);
temp.f *= regs->VR_H(v3, i);
regs->VR_F(v1, j) = temp.f;
}
break;
case 2: /* Word */
for (i=0, j=0; i < 4; i+=2, j++)
{
temp.d = regs->VR_F(v2, i);
temp.d *= regs->VR_F(v3, i);
regs->VR_D(v1, j) = temp.d;
}
break;
case 3: /* Doubleword */
u128temp1 = U128_mul_64( regs->VR_D(v2, 0), regs->VR_D(v3, 0) );
regs->VR_Q(v1) = u128temp1.Q;
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7A5 VMLO - Vector Multiply Logical Odd [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_multiply_logical_odd )
{
int v1, v2, v3, m4, m5, m6;
union { U64 d; U32 f; U16 h; } temp;
U128 u128temp1;
int i, j;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m5, m6 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
if ( (m4 == 3 || m4 == 4) && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m4)
{
case 0: /* Byte */
for (i=1, j=0; i < 16; i+=2, j++)
{
temp.h = regs->VR_B(v2, i);
temp.h *= regs->VR_B(v3, i);
regs->VR_H(v1, j) = temp.h;
}
break;
case 1: /* Halfword */
for (i=1, j=0; i < 8; i+=2, j++)
{
temp.f = regs->VR_H(v2, i);
temp.f *= regs->VR_H(v3, i);
regs->VR_F(v1, j) = temp.f;
}
break;
case 2: /* Word */
for (i=1, j=0; i < 4; i+=2, j++)
{
temp.d = regs->VR_F(v2, i);
temp.d *= regs->VR_F(v3, i);
regs->VR_D(v1, j) = temp.d;
}
break;
case 3: /* Doubleword */
u128temp1 = U128_mul_64( regs->VR_D(v2, 1), regs->VR_D(v3, 1) );
regs->VR_Q(v1) = u128temp1.Q;
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7A6 VME - Vector Multiply Even [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_multiply_even )
{
int v1, v2, v3, m4, m5, m6;
union { S64 sd; S32 sf; S16 sh; } temp;
U128 u128temp1;
int i, j;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m5, m6 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
if ( m4 == 3 && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m4)
{
case 0: /* Byte */
for (i=0, j=0; i < 16; i+=2, j++)
{
temp.sh = (S8)regs->VR_B(v2, i);
temp.sh *= (S8)regs->VR_B(v3, i);
regs->VR_H(v1, j) = temp.sh;
}
break;
case 1: /* Halfword */
for (i=0, j=0; i < 8; i+=2, j++)
{
temp.sf = (S16)regs->VR_H(v2, i);
temp.sf *= (S16)regs->VR_H(v3, i);
regs->VR_F(v1, j) = temp.sf;
}
break;
case 2: /* Word */
for (i=0, j=0; i < 4; i+=2, j++)
{
temp.sd = (S32)regs->VR_F(v2, i);
temp.sd *= (S32)regs->VR_F(v3, i);
regs->VR_D(v1, j) = temp.sd;
}
break;
case 3: /* Doubleword */
u128temp1 = S128_mul_64( regs->VR_D(v2, 0), regs->VR_D(v3, 0) );
regs->VR_Q(v1) = u128temp1.Q;
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7A7 VMO - Vector Multiply Odd [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_multiply_odd )
{
int v1, v2, v3, m4, m5, m6;
union { S64 sd; S32 sf; S16 sh; } temp;
U128 u128temp1;
int i, j;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m5, m6 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
if ( m4 == 3 && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m4)
{
case 0: /* Byte */
for (i=1, j=0; i < 16; i+=2, j++)
{
temp.sh = (S8)regs->VR_B(v2, i);
temp.sh *= (S8)regs->VR_B(v3, i);
regs->VR_H(v1, j) = temp.sh;
}
break;
case 1: /* Halfword */
for (i=1, j=0; i < 8; i+=2, j++)
{
temp.sf = (S16)regs->VR_H(v2, i);
temp.sf *= (S16)regs->VR_H(v3, i);
regs->VR_F(v1, j) = temp.sf;
}
break;
case 2: /* Word */
for (i=1, j=0; i < 4; i+=2, j++)
{
temp.sd = (S32)regs->VR_F(v2, i);
temp.sd *= (S32)regs->VR_F(v3, i);
regs->VR_D(v1, j) = temp.sd;
}
break;
case 3: /* Doubleword */
u128temp1 = S128_mul_64( regs->VR_D(v2, 1), regs->VR_D(v3, 1) );
regs->VR_Q(v1) = u128temp1.Q;
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7A9 VMALH - Vector Multiply and Add Logical High [VRR-d] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_multiply_and_add_logical_high )
{
int v1, v2, v3, v4, m5, m6;
union { U64 d; U32 f; U16 h; } temp;
U128 u128temp1;
int i;
VRR_D( inst, regs, v1, v2, v3, v4, m5, m6 );
/* m6 is not part of this instruction */
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
if ( (m5 == 3 || m5 == 4) && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m5)
{
case 0: /* Byte */
for (i=0; i < 16; i++)
{
temp.h = regs->VR_B(v2, i);
temp.h *= regs->VR_B(v3, i);
temp.h += regs->VR_B(v4, i);
regs->VR_B(v1, i) = temp.h >> 8;
}
break;
case 1: /* Halfword */
for (i=0; i < 8; i++)
{
temp.f = regs->VR_H(v2, i);
temp.f *= regs->VR_H(v3, i);
temp.f += regs->VR_H(v4, i);
regs->VR_H(v1, i) = temp.f >> 16;
}
break;
case 2: /* Word */
for (i=0; i < 4; i++)
{
temp.d = regs->VR_F(v2, i);
temp.d *= regs->VR_F(v3, i);
temp.d += regs->VR_F(v4, i);
regs->VR_F(v1, i) = temp.d >> 32;
}
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++)
{
u128temp1 = U128_mul_64( regs->VR_D(v2, i), regs->VR_D(v3, i) );
u128temp1 = U128_add ( u128temp1, U128_U64( regs->VR_D(v4, i) ));
regs->VR_D(v1, i) = u128temp1.Q.D.H.D;
}
break;
case 4: /* Quadword */
{
U128 tempv2, tempv3, tempv4;
U128 temphi, templo;
tempv2.Q = regs->VR_Q(v2);
tempv3.Q = regs->VR_Q(v3);
tempv4.Q = regs->VR_Q(v4);
U128_mul( tempv2, tempv3, &temphi, &templo );
U256_add_U128 ( &temphi, &templo, tempv4, &temphi, &templo );
regs->VR_Q(v1) = temphi.Q;
}
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7AA VMAL - Vector Multiply and Add Low [VRR-d] */
/*-------------------------------------------------------------------*/
DEF_INST(vector_multiply_and_add_low)
{
int v1, v2, v3, v4, m5, m6;
union { U64 d; U32 f; U16 h; } temp;
U128 u128temp1;
int i;
VRR_D(inst, regs, v1, v2, v3, v4, m5, m6);
/* m6 is not part of this instruction */
UNREFERENCED( m6 );
ZVECTOR_CHECK(regs);
if ( (m5 == 3 || m5 == 4) && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m5)
{
case 0: /* Byte */
for (i=0; i < 16; i++)
{
temp.h = regs->VR_B(v2, i);
temp.h *= regs->VR_B(v3, i);
temp.h += regs->VR_B(v4, i);
regs->VR_B(v1, i) = temp.h & 0xFF;
}
break;
case 1: /* Halfword */
for (i=0; i < 8; i++)
{
temp.f = regs->VR_H(v2, i);
temp.f *= regs->VR_H(v3, i);
temp.f += regs->VR_H(v4, i);
regs->VR_H(v1, i) = temp.f & 0xFFFF;
}
break;
case 2: /* Word */
for (i=0; i < 4; i++)
{
temp.d = regs->VR_F(v2, i);
temp.d *= regs->VR_F(v3, i);
temp.d += regs->VR_F(v4, i);
regs->VR_F(v1, i) = temp.d & 0xFFFFFFFF;
}
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++)
{
u128temp1 = S128_mul_64( regs->VR_D(v2, i), regs->VR_D(v3, i) );
u128temp1 = S128_add ( u128temp1, U128_S64( regs->VR_D(v4, i) ));
regs->VR_D(v1, i) = u128temp1.Q.D.L.D;
}
break;
case 4: /* Quadword */
{
U128 tempv2, tempv3, tempv4;
U128 temphi, templo;
tempv2.Q = regs->VR_Q(v2);
tempv3.Q = regs->VR_Q(v3);
tempv4.Q = regs->VR_Q(v4);
S128_mul( tempv2, tempv3, &temphi, &templo );
S256_add_S128 ( &temphi, &templo, tempv4, &temphi, &templo );
regs->VR_Q(v1) = templo.Q;
}
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END(regs);
}
/*-------------------------------------------------------------------*/
/* E7AB VMAH - Vector Multiply and Add High [VRR-d] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_multiply_and_add_high )
{
int v1, v2, v3, v4, m5, m6;
union { S64 sd; S32 sf; S16 sh; } temp;
U128 u128temp1;
int i;
VRR_D( inst, regs, v1, v2, v3, v4, m5, m6 );
/* m6 is not part of this instruction */
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
if ( (m5 == 3 || m5 == 4) && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m5)
{
case 0: /* Byte */
for (i=0; i < 16; i++)
{
temp.sh = (S8)regs->VR_B(v2, i);
temp.sh *= (S8)regs->VR_B(v3, i);
temp.sh += (S8)regs->VR_B(v4, i);
regs->VR_B(v1, i) = temp.sh >> 8;
}
break;
case 1: /* Halfword */
for (i=0; i < 8; i++)
{
temp.sf = (S16)regs->VR_H(v2, i);
temp.sf *= (S16)regs->VR_H(v3, i);
temp.sf += (S16)regs->VR_H(v4, i);
regs->VR_H(v1, i) = temp.sf >> 16;
}
break;
case 2: /* Word */
for (i=0; i < 4; i++)
{
temp.sd = (S32)regs->VR_F(v2, i);
temp.sd *= (S32)regs->VR_F(v3, i);
temp.sd += (S32)regs->VR_F(v4, i);
regs->VR_F(v1, i) = temp.sd >> 32;
}
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++)
{
u128temp1 = S128_mul_64( regs->VR_D(v2, i), regs->VR_D(v3, i) );
u128temp1 = S128_add ( u128temp1, U128_S64( regs->VR_D(v4, i) ));
regs->VR_D(v1, i) = u128temp1.Q.D.H.D;
}
break;
case 4: /* Quadword */
{
U128 tempv2, tempv3, tempv4;
U128 temphi, templo;
tempv2.Q = regs->VR_Q(v2);
tempv3.Q = regs->VR_Q(v3);
tempv4.Q = regs->VR_Q(v4);
S128_mul( tempv2, tempv3, &temphi, &templo );
S256_add_S128 ( &temphi, &templo, tempv4, &temphi, &templo );
regs->VR_Q(v1) = temphi.Q;
}
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7AC VMALE - Vector Multiply and Add Logical Even [VRR-d] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_multiply_and_add_logical_even )
{
int v1, v2, v3, v4, m5, m6;
union { U64 d; U32 f; U16 h; } temp;
U128 u128temp1, u128temp2;
int i, j;
VRR_D( inst, regs, v1, v2, v3, v4, m5, m6 );
/* m6 is not part of this instruction */
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
if ( m5 == 3 && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m5)
{
case 0: /* Byte */
for (i=0, j=0; i < 16; i+=2, j++)
{
temp.h = regs->VR_B(v2, i);
temp.h *= regs->VR_B(v3, i);
temp.h += regs->VR_H(v4, j);
regs->VR_H(v1, j) = temp.h;
}
break;
case 1: /* Halfword */
for (i=0, j=0; i < 8; i+=2, j++)
{
temp.f = regs->VR_H(v2, i);
temp.f *= regs->VR_H(v3, i);
temp.f += regs->VR_F(v4, j);
regs->VR_F(v1, j) = temp.f;
}
break;
case 2: /* Word */
for (i=0, j=0; i < 4; i+=2, j++)
{
temp.d = regs->VR_F(v2, i);
temp.d *= regs->VR_F(v3, i);
temp.d += regs->VR_D(v4, j);
regs->VR_D(v1, j) = temp.d;
}
break;
case 3: /* Doubleword */
u128temp2.Q = regs->VR_Q(v4);
u128temp1 = U128_mul_64( regs->VR_D(v2, 0), regs->VR_D(v3, 0) );
u128temp1 = U128_add ( u128temp1, u128temp2 );
regs->VR_Q(v1) = u128temp1.Q;
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7AD VMALO - Vector Multiply and Add Logical Odd [VRR-d] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_multiply_and_add_logical_odd )
{
int v1, v2, v3, v4, m5, m6;
union { U64 d; U32 f; U16 h; } temp;
U128 u128temp1, u128temp2;
int i, j;
VRR_D( inst, regs, v1, v2, v3, v4, m5, m6 );
/* m6 is not part of this instruction */
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
if ( m5 == 3 && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m5)
{
case 0: /* Byte */
for (i=1, j=0; i < 16; i+=2, j++)
{
temp.h = regs->VR_B(v2, i);
temp.h *= regs->VR_B(v3, i);
temp.h += regs->VR_H(v4, j);
regs->VR_H(v1, j) = temp.h;
}
break;
case 1: /* Halfword */
for (i=1, j=0; i < 8; i+=2, j++)
{
temp.f = regs->VR_H(v2, i);
temp.f *= regs->VR_H(v3, i);
temp.f += regs->VR_F(v4, j);
regs->VR_F(v1, j) = temp.f;
}
break;
case 2: /* Word */
for (i=1, j=0; i < 4; i+=2, j++)
{
temp.d = regs->VR_F(v2, i);
temp.d *= regs->VR_F(v3, i);
temp.d += regs->VR_D(v4, j);
regs->VR_D(v1, j) = temp.d;
}
break;
case 3: /* Doubleword */
u128temp2.Q = regs->VR_Q(v4);
u128temp1 = U128_mul_64( regs->VR_D(v2, 1), regs->VR_D(v3, 1) );
u128temp1 = U128_add ( u128temp1, u128temp2 );
regs->VR_Q(v1) = u128temp1.Q;
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7AE VMAE - Vector Multiply and Add Even [VRR-d] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_multiply_and_add_even )
{
int v1, v2, v3, v4, m5, m6;
union { S64 sd; S32 sf; S16 sh; } temp;
U128 u128temp1, u128temp2;
int i, j;
VRR_D( inst, regs, v1, v2, v3, v4, m5, m6 );
/* m6 is not part of this instruction */
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
if ( m5 == 3 && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m5)
{
case 0: /* Byte */
for (i=0, j=0; i < 16; i+=2, j++)
{
temp.sh = (S8)regs->VR_B(v2, i);
temp.sh *= (S8)regs->VR_B(v3, i);
temp.sh += (S16)regs->VR_H(v4, j);
regs->VR_H(v1, j) = temp.sh;
}
break;
case 1: /* Halfword */
for (i=0, j=0; i < 8; i+=2, j++)
{
temp.sf = (S16)regs->VR_H(v2, i);
temp.sf *= (S16)regs->VR_H(v3, i);
temp.sf += (S32)regs->VR_F(v4, j);
regs->VR_F(v1, j) = temp.sf;
}
break;
case 2: /* Word */
for (i=0, j=0; i < 4; i+=2, j++)
{
temp.sd = (S32)regs->VR_F(v2, i);
temp.sd *= (S32)regs->VR_F(v3, i);
temp.sd += (S64)regs->VR_D(v4, j);
regs->VR_D(v1, j) = temp.sd;
}
break;
case 3: /* Doubleword */
u128temp2.Q = regs->VR_Q(v4);
u128temp1 = S128_mul_64( regs->VR_D(v2, 0), regs->VR_D(v3, 0) );
u128temp1 = S128_add ( u128temp1, u128temp2 );
regs->VR_Q(v1) = u128temp1.Q;
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7AF VMAO - Vector Multiply and Add Odd [VRR-d] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_multiply_and_add_odd )
{
int v1, v2, v3, v4, m5, m6;
union { S64 sd; S32 sf; S16 sh; } temp;
U128 u128temp1, u128temp2;
int i, j;
VRR_D( inst, regs, v1, v2, v3, v4, m5, m6 );
/* m6 is not part of this instruction */
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
if ( m5 == 3 && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m5)
{
case 0: /* Byte */
for (i=1, j=0; i < 16; i+=2, j++)
{
temp.sh = (S8)regs->VR_B(v2, i);
temp.sh *= (S8)regs->VR_B(v3, i);
temp.sh += (S16)regs->VR_H(v4, j);
regs->VR_H(v1, j) = temp.sh;
}
break;
case 1: /* Halfword */
for (i=1, j=0; i < 8; i+=2, j++)
{
temp.sf = (S16)regs->VR_H(v2, i);
temp.sf *= (S16)regs->VR_H(v3, i);
temp.sf += (S32)regs->VR_F(v4, j);
regs->VR_F(v1, j) = temp.sf;
}
break;
case 2: /* Word */
for (i=1, j=0; i < 4; i+=2, j++)
{
temp.sd = (S32)regs->VR_F(v2, i);
temp.sd *= (S32)regs->VR_F(v3, i);
temp.sd += (S64)regs->VR_D(v4, j);
regs->VR_D(v1, j) = temp.sd;
}
break;
case 3: /* Doubleword */
u128temp2.Q = regs->VR_Q(v4);
u128temp1 = S128_mul_64( regs->VR_D(v2, 1), regs->VR_D(v3, 1) );
u128temp1 = S128_add ( u128temp1, u128temp2 );
regs->VR_Q(v1) = u128temp1.Q;
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
#if defined( FEATURE_198_VECTOR_ENH_FACILITY_3 )
/*-------------------------------------------------------------------*/
/* E7B0 VDL - Vector Divide Logical [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_divide_logical )
{
int v1, v2, v3, m4, m5, m6;
int i;
union { U64 d[2]; U32 f[4]; } temp;
U128 dividend, divisor, quotient;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m6 is not part of this instruction */
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
#define M5_IDC ((m5 & 0x8) != 0) // Integer-Divide Control
switch (m4)
{
case 2: /* Word */
for (i=0; i < 4; i++)
{
if (regs->VR_F( v3, i ) == 0)
{
if (M5_IDC)
{
temp.f[i] = 0;
continue;
}
else
vector_processing_trap( regs, i, VXC_INTEGER_DIVIDE );
}
temp.f[i] = regs->VR_F( v2, i ) / regs->VR_F( v3, i );
}
for (i=0; i < 4; i++)
{
regs->VR_F( v1, i ) = temp.f[i];
}
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++)
{
if (regs->VR_D( v3, i ) == 0)
{
if (M5_IDC)
{
temp.d[i] = 0;
continue;
}
else
vector_processing_trap( regs, i, VXC_INTEGER_DIVIDE );
}
temp.d[i] = regs->VR_D( v2, i ) / regs->VR_D( v3, i );
}
for (i=0; i < 2; i++)
{
regs->VR_D( v1, i ) = temp.d[i];
}
break;
case 4: /* Quadword */
dividend.Q = regs->VR_Q( v2 );
divisor.Q = regs->VR_Q( v3 );
if (U128_isZero( divisor ))
{
if (M5_IDC)
{
regs->VR_D( v1, 0 ) = 0;
regs->VR_D( v1, 1 ) = 0;
break;
}
else
vector_processing_trap( regs, 0, VXC_INTEGER_DIVIDE );
}
quotient = U128_div( dividend, divisor );
regs->VR_Q( v1 ) = quotient.Q;
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
#undef M5_IDC
ZVECTOR_END( regs );
}
#endif /* defined( FEATURE_198_VECTOR_ENH_FACILITY_3 ) */
#if defined( FEATURE_198_VECTOR_ENH_FACILITY_3 )
/*-------------------------------------------------------------------*/
/* E7B1 VRL - Vector Remainder Logical [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_remainder_logical )
{
int v1, v2, v3, m4, m5, m6;
int i;
union { U64 d[2]; U32 f[4]; } temp;
U128 dividend, divisor, remainder;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m6 is not part of this instruction */
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
#define M5_IDC ((m5 & 0x8) != 0) // Integer-Divide Control
switch (m4)
{
case 2: /* Word */
for (i=0; i < 4; i++)
{
if (regs->VR_F( v3, i ) == 0)
{
if (M5_IDC)
{
temp.f[i] = 0;
continue;
}
else
vector_processing_trap( regs, i, VXC_INTEGER_DIVIDE );
}
temp.f[i] = regs->VR_F( v2, i ) % regs->VR_F( v3, i );
}
for (i=0; i < 4; i++)
{
regs->VR_F( v1, i ) = temp.f[i];
}
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++)
{
if (regs->VR_D( v3, i ) == 0)
{
if (M5_IDC)
{
temp.d[i] = 0;
continue;
}
else
vector_processing_trap( regs, i, VXC_INTEGER_DIVIDE );
}
temp.d[i] = regs->VR_D( v2, i ) % regs->VR_D( v3, i );
}
for (i=0; i < 2; i++)
{
regs->VR_D( v1, i ) = temp.d[i];
}
break;
case 4: /* Quadword */
dividend.Q = regs->VR_Q( v2 );
divisor.Q = regs->VR_Q( v3 );
if (U128_isZero( divisor ))
{
if (M5_IDC)
{
regs->VR_D( v1, 0 ) = 0;
regs->VR_D( v1, 1 ) = 0;
break;
}
else
vector_processing_trap( regs, 0, VXC_INTEGER_DIVIDE );
}
remainder = U128_rem( dividend, divisor );
regs->VR_Q( v1 ) = remainder.Q;
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
#undef M5_IDC
ZVECTOR_END( regs );
}
#endif /* defined( FEATURE_198_VECTOR_ENH_FACILITY_3 ) */
#if defined( FEATURE_198_VECTOR_ENH_FACILITY_3 )
/*-------------------------------------------------------------------*/
/* E7B2 VD - Vector Divide [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_divide )
{
int v1, v2, v3, m4, m5, m6;
int i;
union { U64 d[2]; U32 f[4]; } temp;
U128 dividend, divisor, quotient;
U128 negone, negmax;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m6 is not part of this instruction */
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
#define M5_IDC ((m5 & 0x8) != 0) // Integer-Divide Control
switch (m4)
{
case 2: /* Word */
for (i=0; i < 4; i++)
{
if (regs->VR_F( v3, i ) == 0 ||
(regs->VR_F( v3, i ) == 0xFFFFFFFF && regs->VR_F( v2, i ) == 0x80000000))
{
if (M5_IDC)
{
temp.f[i] = 0;
continue;
}
else
vector_processing_trap( regs, i, VXC_INTEGER_DIVIDE );
}
temp.f[i] = (S32)regs->VR_F( v2, i ) / (S32)regs->VR_F( v3, i );
}
for (i=0; i < 4; i++)
{
regs->VR_F( v1, i ) = temp.f[i];
}
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++)
{
if (regs->VR_D( v3, i ) == 0 ||
(regs->VR_D( v3, i ) == 0xFFFFFFFFFFFFFFFFull && regs->VR_D( v2, i ) == 0x8000000000000000ull))
{
if (M5_IDC)
{
temp.d[i] = 0;
continue;
}
else
vector_processing_trap( regs, i, VXC_INTEGER_DIVIDE );
}
temp.d[i] = (S64)regs->VR_D( v2, i ) / (S64)regs->VR_D( v3, i );
}
for (i=0; i < 2; i++)
{
regs->VR_D( v1, i ) = temp.d[i];
}
break;
case 4: /* Quadword */
negone.Q.D.H.D = 0xFFFFFFFFFFFFFFFFull;
negone.Q.D.L.D = 0xFFFFFFFFFFFFFFFFull;
negmax.Q.D.H.D = 0x8000000000000000ull;
negmax.Q.D.L.D = 0x0000000000000000ull;
dividend.Q = regs->VR_Q( v2 );
divisor.Q = regs->VR_Q( v3 );
if (U128_isZero( divisor ) ||
(U128_cmp( divisor, negone ) == 0 && U128_cmp( dividend, negmax ) == 0))
{
if (M5_IDC)
{
regs->VR_D( v1, 0 ) = 0;
regs->VR_D( v1, 1 ) = 0;
break;
}
else
vector_processing_trap( regs, 0, VXC_INTEGER_DIVIDE );
}
quotient = S128_div( dividend, divisor );
regs->VR_Q( v1 ) = quotient.Q;
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
#undef M5_IDC
ZVECTOR_END( regs );
}
#endif /* defined( FEATURE_198_VECTOR_ENH_FACILITY_3 ) */
#if defined( FEATURE_198_VECTOR_ENH_FACILITY_3 )
/*-------------------------------------------------------------------*/
/* E7B3 VR - Vector Remainder [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_remainder )
{
int v1, v2, v3, m4, m5, m6;
int i;
union { U64 d[2]; U32 f[4]; } temp;
U128 dividend, divisor, remainder;
U128 negone, negmax;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m6 is not part of this instruction */
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
#define M5_IDC ((m5 & 0x8) != 0) // Integer-Divide Control
switch (m4)
{
case 2: /* Word */
for (i=0; i < 4; i++)
{
if (regs->VR_F( v3, i ) == 0)
{
if (M5_IDC)
{
temp.f[i] = 0;
continue;
}
else
vector_processing_trap( regs, i, VXC_INTEGER_DIVIDE );
}
if (regs->VR_F( v3, i ) == 0xFFFFFFFF && regs->VR_F( v2, i ) == 0x80000000)
{
temp.f[i] = 0;
continue;
}
temp.f[i] = (S32)regs->VR_F( v2, i ) % (S32)regs->VR_F( v3, i );
}
for (i=0; i < 4; i++)
{
regs->VR_F( v1, i ) = temp.f[i];
}
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++)
{
if (regs->VR_D( v3, i ) == 0)
{
if (M5_IDC)
{
temp.d[i] = 0;
continue;
}
else
vector_processing_trap( regs, i, VXC_INTEGER_DIVIDE );
}
if (regs->VR_D( v3, i ) == 0xFFFFFFFFFFFFFFFFull && regs->VR_D( v2, i ) == 0x8000000000000000ull)
{
temp.d[i] = 0;
continue;
}
temp.d[i] = (S64)regs->VR_D( v2, i ) % (S64)regs->VR_D( v3, i );
}
for (i=0; i < 2; i++)
{
regs->VR_D( v1, i ) = temp.d[i];
}
break;
case 4: /* Quadword */
negone.Q.D.H.D = 0xFFFFFFFFFFFFFFFFull;
negone.Q.D.L.D = 0xFFFFFFFFFFFFFFFFull;
negmax.Q.D.H.D = 0x8000000000000000ull;
negmax.Q.D.L.D = 0x0000000000000000ull;
dividend.Q = regs->VR_Q( v2 );
divisor.Q = regs->VR_Q( v3 );
if (U128_isZero( divisor ))
{
if (M5_IDC)
{
regs->VR_D( v1, 0 ) = 0;
regs->VR_D( v1, 1 ) = 0;
break;
}
else
vector_processing_trap( regs, 0, VXC_INTEGER_DIVIDE );
}
if (U128_cmp( divisor, negone ) == 0 && U128_cmp( dividend, negmax ) == 0)
{
regs->VR_D( v1, 0 ) = 0;
regs->VR_D( v1, 1 ) = 0;
break;
}
remainder = S128_rem( dividend, divisor );
regs->VR_Q( v1 ) = remainder.Q;
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
#undef M5_IDC
ZVECTOR_END( regs );
}
#endif /* defined( FEATURE_198_VECTOR_ENH_FACILITY_3 ) */
/*-------------------------------------------------------------------*/
/* E7B4 VGFM - Vector Galois Field Multiply Sum [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_galois_field_multiply_sum )
{
int v1, v2, v3, m4, m5, m6;
int i, k; /* loop index */
U16 accu16[16]; /* byte accumulator */
U32 accu32[8]; /* halfword accumulator */
U64 accu64[4]; /* word accumulator */
U64 accu128h[2]; /* doubleword accumulator - high */
U64 accu128l[2]; /* doubleword accumulator - low */
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m5, m6 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
switch (m4)
{
case 0: /* Byte */
for (i=0; i < 16; i++)
accu16[i] = (U16) gf_mul_32( (U32) regs->VR_B(v2, i), (U32) regs->VR_B(v3, i) );
/* sum even-odd pair */
for ( i=0, k=0; i < 8; i++, k += 2)
regs->VR_H( v1, i ) = accu16[k] ^ accu16[k+1];
break;
case 1: /* Halfword */
for (i=0; i < 8; i++)
accu32[i] = (U32) gf_mul_32( (U32) regs->VR_H(v2, i), (U32) regs->VR_H(v3, i) );
/* sum even-odd pair */
for ( i=0, k=0; i < 4; i++, k += 2)
regs->VR_F( v1, i ) = accu32[k] ^ accu32[k+1];
break;
case 2: /* Word */
for (i=0; i < 4; i++)
accu64[i] = (U64) gf_mul_32( (U32) regs->VR_F(v2, i), (U32) regs->VR_F(v3, i) );
/* sum even-odd pair */
for ( i=0, k=0; i < 2; i++, k += 2)
regs->VR_D( v1, i ) = accu64[k] ^ accu64[k+1];
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++)
gf_mul_64( regs->VR_D(v2, i), regs->VR_D(v3, i), &accu128h[i], &accu128l[i]);
/* sum even-odd pair */
regs->VR_D( v1, 0 ) = accu128h[0] ^ accu128h[1];
regs->VR_D( v1, 1 ) = accu128l[0] ^ accu128l[1];
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
#if defined( FEATURE_135_ZVECTOR_ENH_FACILITY_1 )
/*-------------------------------------------------------------------*/
/* E7B8 VMSL - Vector Multiply Sum Logical [VRR-d] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_multiply_sum_logical )
{
int v1, v2, v3, v4, m5, m6;
U128 intere, intero;
#if defined( _MSVC_ )
U128 copyv4;
#endif
VRR_D( inst, regs, v1, v2, v3, v4, m5, m6 );
ZVECTOR_CHECK( regs );
#define M6_ES ((m6 & 0x8) != 0) // Even Shift Indication
#define M6_OS ((m6 & 0x4) != 0) // Odd Shift Indication
switch (m5)
{
case 3: /* Doubleword */
intere = U128_mul_64( regs->VR_D(v2, 0), regs->VR_D(v3, 0) );
intero = U128_mul_64( regs->VR_D(v2, 1), regs->VR_D(v3, 1) );
if (M6_ES)
intere = U128_mul_32( intere, 2 ); // Shift left
if (M6_OS)
intero = U128_mul_32( intero, 2 ); // Shift left
intere = U128_add( intere, intero );
#if defined( _MSVC_ )
copyv4.Q = regs->VR_Q(v4);
intere = U128_add( intere, copyv4 );
#else
intere = U128_add( intere, (U128)regs->VR_Q(v4) );
#endif
regs->VR_Q(v1) = intere.Q;
break;
default:
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
break;
}
#undef M6_ES
#undef M6_OS
ZVECTOR_END( regs );
}
#endif /* defined( FEATURE_135_ZVECTOR_ENH_FACILITY_1 ) */
/*-------------------------------------------------------------------*/
/* E7B9 VACCC - Vector Add With Carry Compute Carry [VRR-d] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_add_with_carry_compute_carry )
{
int v1, v2, v3, v4, m5, m6;
union { U64 d[4]; } temp;
U64 carry;
int i;
VRR_D( inst, regs, v1, v2, v3, v4, m5, m6 );
/* m6 is not part of this instruction */
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
switch (m5)
{
case 4: /* Quadword */
carry = regs->VR_D( v4, 1 ) & 0x0000000000000001ull;
for (i=3; i >= 0; i--)
{
temp.d[i] = carry;
temp.d[i] += regs->VR_F( v3, i );
temp.d[i] += regs->VR_F( v2, i );
carry = temp.d[i] >> 32;
}
regs->VR_D( v1, 0 ) = 0;
regs->VR_D( v1, 1 ) = carry;
break;
default:
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7BB VAC - Vector Add With Carry [VRR-d] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_add_with_carry )
{
int v1, v2, v3, v4, m5, m6;
U128 inter, rmost;
#if defined( _MSVC_ )
U128 copyv2, copyv3;
#endif
VRR_D( inst, regs, v1, v2, v3, v4, m5, m6 );
/* m6 is not part of this instruction */
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
switch (m5)
{
case 4: /* Quadword */
#if defined( _MSVC_ )
copyv2.Q = regs->VR_Q(v2);
copyv3.Q = regs->VR_Q(v3);
inter = U128_add( copyv2, copyv3 );
#else
inter = U128_add( (U128)regs->VR_Q(v2), (U128)regs->VR_Q(v3) );
#endif
if (regs->VR_D( v4, 1 ) & 0x0000000000000001ull)
{
rmost.Q.D.H.D = 0;
rmost.Q.D.L.D = 1;
inter = U128_add(inter, rmost);
}
regs->VR_Q(v1) = inter.Q;
break;
default:
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
break;
}
ZVECTOR_END( regs );
}
/*-----------------------------------------------------------------------*/
/* E7BC VGFMA - Vector Galois Field Multiply Sum and Accumulate [VRR-d] */
/*-----------------------------------------------------------------------*/
DEF_INST( vector_galois_field_multiply_sum_and_accumulate )
{
int v1, v2, v3, v4, m5, m6;
int i, k; /* loop index */
U16 accu16[16]; /* byte accumulator */
U32 accu32[8]; /* halfword accumulator */
U64 accu64[4]; /* word accumulator */
U64 accu128h[2]; /* doubleword accumulator - high */
U64 accu128l[2]; /* doubleword accumulator - low */
VRR_D( inst, regs, v1, v2, v3, v4, m5, m6 );
/* m6 is not part of this instruction */
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
switch (m5)
{
case 0: /* Byte */
for (i=0; i < 16; i++)
accu16[i] = (U16) gf_mul_32( (U32) regs->VR_B(v2, i), (U32) regs->VR_B(v3, i) );
/* sum even-odd pair plus vector accumulate */
for ( i=0, k=0; i < 8; i++, k += 2)
regs->VR_H( v1, i ) = accu16[k] ^ accu16[k+1] ^ regs->VR_H( v4, i);
break;
case 1: /* Halfword */
for (i=0; i < 8; i++)
accu32[i] = (U32) gf_mul_32( (U32) regs->VR_H(v2, i), (U32) regs->VR_H(v3, i) );
/* sum even-odd pair plus vector accumulate */
for ( i=0, k=0; i < 4; i++, k += 2)
regs->VR_F( v1, i ) = accu32[k] ^ accu32[k+1] ^ regs->VR_F( v4, i);
break;
case 2: /* Word */
for (i=0; i < 4; i++)
accu64[i] = (U64) gf_mul_32( (U32) regs->VR_F(v2, i), (U32) regs->VR_F(v3, i) );
/* sum even-odd pair plus vector accumulate */
for ( i=0, k=0; i < 2; i++, k += 2)
regs->VR_D( v1, i ) = accu64[k] ^ accu64[k+1] ^ regs->VR_D( v4, i );
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++)
gf_mul_64( regs->VR_D(v2, i), regs->VR_D(v3, i), &accu128h[i], &accu128l[i]);
/* sum even-odd pair plus vector accumulate */
regs->VR_D( v1, 0 ) = accu128h[0] ^ accu128h[1] ^ regs->VR_D( v4, 0);
regs->VR_D( v1, 1 ) = accu128l[0] ^ accu128l[1] ^ regs->VR_D( v4, 1);
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
//------------------------------------------------------------------------------
// PROGRAMMING NOTE: the "potentially incorrect code/behavior" that Microsoft's
// C4319 warning is reporting us about was thoroughly researched and determined
// to be unwarranted IN THIS PARTICULAR SPECIFIC CASE. Thus the disablement of
// the warning, as the code, as written, was determined to be 100% correct.
// Refer to GitHub Issue #787 (especially near the end) for further details.
//------------------------------------------------------------------------------
#if defined(_MSVC_) && (_MSC_VER >= VS2022)
PUSH_MSVC_WARNINGS()
DISABLE_MSVC_WARNING( 4319 )
#endif
/*-----------------------------------------------------------------------------*/
/* E7BD VSBCBI - Vector Subtract With Borrow Compute Borrow Indication [VRR-d] */
/*-----------------------------------------------------------------------------*/
DEF_INST( vector_subtract_with_borrow_compute_borrow_indication )
{
int v1, v2, v3, v4, m5, m6;
union { U64 d; } temp;
int i;
VRR_D( inst, regs, v1, v2, v3, v4, m5, m6 );
/* m6 is not part of this instruction */
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
switch (m5)
{
case 4: /* Quadword */
temp.d = regs->VR_D( v4, 1 ) & 0x0000000000000001ull;
for (i=3; i >= 0; i--)
{
temp.d += ~regs->VR_F( v3, i );
temp.d += regs->VR_F( v2, i );
temp.d >>= 32;
}
regs->VR_D( v1, 0 ) = 0;
regs->VR_D( v1, 1 ) = temp.d;
break;
default:
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
break;
}
ZVECTOR_END( regs );
}
#if defined(_MSVC_) && (_MSC_VER >= VS2022)
POP_MSVC_WARNINGS()
#endif
//------------------------------------------------------------------------------
// PROGRAMMING NOTE: the "potentially incorrect code/behavior" that Microsoft's
// C4319 warning is reporting us about was thoroughly researched and determined
// to be unwarranted IN THIS PARTICULAR SPECIFIC CASE. Thus the disablement of
// the warning, as the code, as written, was determined to be 100% correct.
// Refer to GitHub Issue #787 (especially near the end) for further details.
//------------------------------------------------------------------------------
#if defined(_MSVC_) && (_MSC_VER >= VS2022)
PUSH_MSVC_WARNINGS()
DISABLE_MSVC_WARNING( 4319 )
#endif
/*-------------------------------------------------------------------*/
/* E7BF VSBI - Vector Subtract With Borrow Indication [VRR-d] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_subtract_with_borrow_indication )
{
int v1, v2, v3, v4, m5, m6;
union { U64 d[4]; } temp;
U64 carry;
int i;
VRR_D( inst, regs, v1, v2, v3, v4, m5, m6 );
/* m6 is not part of this instruction */
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
switch (m5)
{
case 4: /* Quadword */
carry = regs->VR_D( v4, 1 ) & 0x0000000000000001ull;
for (i=3; i >= 0; i--)
{
temp.d[i] = carry;
temp.d[i] += ~regs->VR_F( v3, i );
temp.d[i] += regs->VR_F( v2, i );
carry = temp.d[i] >> 32;
}
for (i=3; i >= 0; i--)
regs->VR_F( v1, i ) = temp.d[i];
break;
default:
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
break;
}
ZVECTOR_END( regs );
}
#if defined(_MSVC_) && (_MSC_VER >= VS2022)
POP_MSVC_WARNINGS()
#endif
/*-------------------------------------------------------------------*/
/* E7D4 VUPLL - Vector Unpack Logical Low [VRR-a] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_unpack_logical_low )
{
int v1, v2, m3, m4, m5, i;
union { U64 d[2]; U32 f[4]; U16 h[8]; } temp;
VRR_A( inst, regs, v1, v2, m3, m4, m5 );
/* m4, m5 are not part of this instruction */
UNREFERENCED( m4 );
UNREFERENCED( m5 );
ZVECTOR_CHECK( regs );
if ( m3 == 3 && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m3)
{
case 0: /* Byte */
for (i = 0; i < 8; i++)
temp.h[i] = (U16) regs->VR_B(v2, i + 8);
for (i = 0; i < 8; i++)
regs->VR_H(v1, i) = temp.h[i];
break;
case 1: /* Halfword */
for (i = 0; i < 4; i++)
temp.f[i] = (U32) regs->VR_H(v2, i + 4);
for (i = 0; i < 4; i++)
regs->VR_F(v1, i) = temp.f[i];
break;
case 2: /* Word */
for (i = 0; i < 2; i++)
temp.d[i] = (U64) regs->VR_F(v2, i + 2);
for (i = 0; i < 2; i++)
regs->VR_D(v1, i) = temp.d[i];
break;
case 3: /* Doubleword */
regs->VR_D(v1, 1) = regs->VR_D(v2, 1);
regs->VR_D(v1, 0) = 0x0000000000000000ull;
break;
default:
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7D5 VUPLH - Vector Unpack Logical High [VRR-a] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_unpack_logical_high )
{
int v1, v2, m3, m4, m5, i;
union { U64 d[2]; U32 f[4]; U16 h[8]; } temp;
VRR_A( inst, regs, v1, v2, m3, m4, m5 );
/* m4, m5 are not part of this instruction */
UNREFERENCED( m4 );
UNREFERENCED( m5 );
ZVECTOR_CHECK( regs );
if ( m3 == 3 && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m3)
{
case 0: /* Byte */
for (i = 0; i < 8; i++)
temp.h[i] = (U16) regs->VR_B(v2, i);
for (i = 0; i < 8; i++)
regs->VR_H(v1, i) = temp.h[i];
break;
case 1: /* Halfword */
for (i = 0; i < 4; i++)
temp.f[i] = (U32) regs->VR_H(v2, i);
for (i = 0; i < 4; i++)
regs->VR_F(v1, i) = temp.f[i];
break;
case 2: /* Word */
for (i = 0; i < 2; i++)
temp.d[i] = (U64) regs->VR_F(v2, i);
for (i = 0; i < 2; i++)
regs->VR_D(v1, i) = temp.d[i];
break;
case 3: /* Doubleword */
regs->VR_D(v1, 1) = regs->VR_D(v2, 0);
regs->VR_D(v1, 0) = 0x0000000000000000ull;
break;
default:
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7D6 VUPL - Vector Unpack Low [VRR-a] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_unpack_low )
{
int v1, v2, m3, m4, m5;
union { U64 sd[2]; U32 sf[4]; U16 sh[8]; } temp;
int i;
VRR_A( inst, regs, v1, v2, m3, m4, m5 );
/* m4, m5 are not part of this instruction */
UNREFERENCED( m4 );
UNREFERENCED( m5 );
ZVECTOR_CHECK( regs );
if ( m3 == 3 && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m3)
{
case 0: /* Byte */
for (i = 0; i < 8; i++)
{
temp.sh[i] = regs->VR_B(v2, i + 8);
if (temp.sh[i] & 0x0080) temp.sh[i] |= 0xFF00;
}
for (i = 0; i < 8; i++)
regs->VR_H(v1, i) = temp.sh[i];
break;
case 1: /* Halfword */
for (i = 0; i < 4; i++)
{
temp.sf[i] = regs->VR_H(v2, i + 4);
if (temp.sf[i] & 0x00008000) temp.sf[i] |= 0xFFFF0000;
}
for (i = 0; i < 4; i++)
regs->VR_F(v1, i) = temp.sf[i];
break;
case 2: /* Word */
for (i = 0; i < 2; i++)
{
temp.sd[i] = regs->VR_F(v2, i + 2);
if (temp.sd[i] & 0x0000000080000000ull) temp.sd[i] |= 0xFFFFFFFF00000000ull;
}
for (i = 0; i < 2; i++)
regs->VR_D(v1, i) = temp.sd[i];
break;
case 3: /* Doubleword */
if (regs->VR_D(v2, 1) & 0x8000000000000000ull)
{
regs->VR_D(v1, 1) = regs->VR_D(v2, 1);
regs->VR_D(v1, 0) = 0xFFFFFFFFFFFFFFFFull;
}
else
{
regs->VR_D(v1, 1) = regs->VR_D(v2, 1);
regs->VR_D(v1, 0) = 0x0000000000000000ull;
}
break;
default:
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7D7 VUPH - Vector Unpack High [VRR-a] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_unpack_high )
{
int v1, v2, m3, m4, m5;
union { U64 sd[2]; U32 sf[4]; U16 sh[8]; } temp;
int i;
VRR_A( inst, regs, v1, v2, m3, m4, m5 );
/* m4, m5 are not part of this instruction */
UNREFERENCED( m4 );
UNREFERENCED( m5 );
ZVECTOR_CHECK( regs );
if ( m3 == 3 && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m3)
{
case 0: /* Byte */
for (i = 0; i < 8; i++)
{
temp.sh[i] = regs->VR_B(v2, i);
if (temp.sh[i] & 0x0080) temp.sh[i] |= 0xFF00;
}
for (i = 0; i < 8; i++)
regs->VR_H(v1, i) = temp.sh[i];
break;
case 1: /* Halfword */
for (i = 0; i < 4; i++)
{
temp.sf[i] = regs->VR_H(v2, i);
if (temp.sf[i] & 0x00008000) temp.sf[i] |= 0xFFFF0000;
}
for (i = 0; i < 4; i++)
regs->VR_F(v1, i) = temp.sf[i];
break;
case 2: /* Word */
for (i = 0; i < 2; i++)
{
temp.sd[i] = regs->VR_F(v2, i);
if (temp.sd[i] & 0x0000000080000000ull) temp.sd[i] |= 0xFFFFFFFF00000000ull;
}
for (i = 0; i < 2; i++)
regs->VR_D(v1, i) = temp.sd[i];
break;
case 3: /* Doubleword */
if (regs->VR_D(v2, 0) & 0x8000000000000000ull)
{
regs->VR_D(v1, 1) = regs->VR_D(v2, 0);
regs->VR_D(v1, 0) = 0xFFFFFFFFFFFFFFFFull;
}
else
{
regs->VR_D(v1, 1) = regs->VR_D(v2, 0);
regs->VR_D(v1, 0) = 0x0000000000000000ull;
}
break;
default:
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7D8 VTM - Vector Test Under Mask [VRR-a] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_test_under_mask )
{
int v1, v2, m3, m4, m5;
union { U64 d[2]; } temp;
VRR_A( inst, regs, v1, v2, m3, m4, m5 );
/* m3, m4, m5 are not part of this instruction */
UNREFERENCED( m3 );
UNREFERENCED( m4 );
UNREFERENCED( m5 );
ZVECTOR_CHECK( regs );
//note: V2 is mask
temp.d[0] = regs->VR_D(v1,0) & regs->VR_D(v2,0);
temp.d[1] = regs->VR_D(v1,1) & regs->VR_D(v2,1);
// Selected bits all zeros; or all mask bits zero
if ( temp.d[0] == 0 && temp.d[1] == 0 )
regs->psw.cc = 0;
// Selected bits all ones
else if ( temp.d[0] == regs->VR_D(v2,0) && temp.d[1] == regs->VR_D(v2,1) )
regs->psw.cc = 3;
// Selected bits a mix of zeros and ones
else
regs->psw.cc = 1;
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7D9 VECL - Vector Element Compare Logical [VRR-a] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_element_compare_logical )
{
int v1, v2, m3, m4, m5;
VRR_A( inst, regs, v1, v2, m3, m4, m5 );
/* m4, m5 are not part of this instruction */
UNREFERENCED( m4 );
UNREFERENCED( m5 );
ZVECTOR_CHECK( regs );
if ( m3 == 4 && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m3)
{
case 0: /* Byte */
if (regs->VR_B( v1, 7 ) == regs->VR_B( v2, 7 ))
regs->psw.cc = 0;
else if (regs->VR_B( v1, 7 ) < regs->VR_B( v2, 7 ))
regs->psw.cc = 1;
else
regs->psw.cc = 2;
break;
case 1: /* Halfword */
if (regs->VR_H( v1, 3 ) == regs->VR_H( v2, 3 ))
regs->psw.cc = 0;
else if (regs->VR_H( v1, 3 ) < regs->VR_H( v2, 3 ))
regs->psw.cc = 1;
else
regs->psw.cc = 2;
break;
case 2: /* Word */
if (regs->VR_F( v1, 1 ) == regs->VR_F( v2, 1 ))
regs->psw.cc = 0;
else if (regs->VR_F( v1, 1 ) < regs->VR_F( v2, 1 ))
regs->psw.cc = 1;
else
regs->psw.cc = 2;
break;
case 3: /* Doubleword */
if (regs->VR_D( v1, 0 ) == regs->VR_D( v2, 0 ))
regs->psw.cc = 0;
else if (regs->VR_D( v1, 0 ) < regs->VR_D( v2, 0 ))
regs->psw.cc = 1;
else
regs->psw.cc = 2;
break;
case 4: /* Quadword */
{
U128 tempv1, tempv2;
int rc;
tempv1.Q = regs->VR_Q(v1);
tempv2.Q = regs->VR_Q(v2);
rc = U128_cmp( tempv1, tempv2 );
if (rc == 0)
regs->psw.cc = 0;
else if (rc == -1)
regs->psw.cc = 1;
else
regs->psw.cc = 2;
}
break;
default:
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7DB VEC - Vector Element Compare [VRR-a] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_element_compare )
{
int v1, v2, m3, m4, m5;
VRR_A( inst, regs, v1, v2, m3, m4, m5 );
/* m4, m5 are not part of this instruction */
UNREFERENCED( m4 );
UNREFERENCED( m5 );
ZVECTOR_CHECK( regs );
if ( m3 == 4 && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m3)
{
case 0: /* Byte */
if ((S8)regs->VR_B( v1, 7 ) == (S8)regs->VR_B( v2, 7 ))
regs->psw.cc = 0;
else if ((S8)regs->VR_B( v1, 7 ) < (S8)regs->VR_B( v2, 7 ))
regs->psw.cc = 1;
else
regs->psw.cc = 2;
break;
case 1: /* Halfword */
if ((S16)regs->VR_H( v1, 3 ) == (S16)regs->VR_H( v2, 3 ))
regs->psw.cc = 0;
else if ((S16)regs->VR_H( v1, 3 ) < (S16)regs->VR_H( v2, 3 ))
regs->psw.cc = 1;
else
regs->psw.cc = 2;
break;
case 2: /* Word */
if ((S32)regs->VR_F( v1, 1 ) == (S32)regs->VR_F( v2, 1 ))
regs->psw.cc = 0;
else if ((S32)regs->VR_F( v1, 1 ) < (S32)regs->VR_F( v2, 1 ))
regs->psw.cc = 1;
else
regs->psw.cc = 2;
break;
case 3: /* Doubleword */
if ((S64)regs->VR_D( v1, 0 ) == (S64)regs->VR_D( v2, 0 ))
regs->psw.cc = 0;
else if ((S64)regs->VR_D( v1, 0 ) < (S64)regs->VR_D( v2, 0 ))
regs->psw.cc = 1;
else
regs->psw.cc = 2;
break;
case 4: /* Quadword */
{
U128 tempv1, tempv2;
int rc;
tempv1.Q = regs->VR_Q(v1);
tempv2.Q = regs->VR_Q(v2);
rc = S128_cmp( tempv1, tempv2 );
if (rc == 0)
regs->psw.cc = 0;
else if (rc == -1)
regs->psw.cc = 1;
else
regs->psw.cc = 2;
}
break;
default:
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7DE VLC - Vector Load Complement [VRR-a] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_load_complement )
{
int v1, v2, m3, m4, m5;
int i;
VRR_A( inst, regs, v1, v2, m3, m4, m5 );
/* m4, m5 are not part of this instruction */
UNREFERENCED( m4 );
UNREFERENCED( m5 );
ZVECTOR_CHECK( regs );
if ( m3 == 4 && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m3)
{
case 0: /* Byte */
for (i=0; i < 16; i++)
regs->VR_B( v1, i ) = ~(S8)regs->VR_B( v2, i ) + 1;
break;
case 1: /* Halfword */
for (i=0; i < 8; i++)
regs->VR_H( v1, i ) = ~(S16)regs->VR_H( v2, i ) + 1;
break;
case 2: /* Word */
for (i=0; i < 4; i++)
regs->VR_F( v1, i ) = ~(S32)regs->VR_F( v2, i ) + 1;
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++)
regs->VR_D( v1, i ) = ~(S64)regs->VR_D( v2, i ) + 1;
break;
case 4: /* Quadword */
{
U128 tempv1, tempv2;
tempv2.Q = regs->VR_Q(v2);
tempv1 = S128_neg( tempv2 );
regs->VR_Q(v1) = tempv1.Q;
}
break;
default:
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7DF VLP - Vector Load Positive [VRR-a] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_load_positive )
{
int v1, v2, m3, m4, m5;
int i;
VRR_A( inst, regs, v1, v2, m3, m4, m5 );
/* m4, m5 are not part of this instruction */
UNREFERENCED( m4 );
UNREFERENCED( m5 );
ZVECTOR_CHECK( regs );
if ( m3 == 4 && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m3)
{
case 0: /* Byte */
for (i=0; i < 16; i++)
regs->VR_B( v1, i ) = (S8)regs->VR_B( v2, i ) < 0 ?
-((S8)regs->VR_B( v2, i )) :
(S8)regs->VR_B( v2, i );
break;
case 1: /* Halfword */
for (i=0; i < 8; i++)
regs->VR_H( v1, i ) = (S16)regs->VR_H( v2, i ) < 0 ?
-((S16)regs->VR_H( v2, i )) :
(S16)regs->VR_H( v2, i );
break;
case 2: /* Word */
for (i=0; i < 4; i++)
regs->VR_F( v1, i ) = (S32)regs->VR_F( v2, i ) < 0 ?
-((S32)regs->VR_F( v2, i )) :
(S32)regs->VR_F( v2, i );
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++)
regs->VR_D( v1, i ) = (S64)regs->VR_D( v2, i ) < 0 ?
-((S64)regs->VR_D( v2, i )) :
(S64)regs->VR_D( v2, i );
break;
case 4: /* Quadword */
{
U128 tempv1, tempv2;
tempv2.Q = regs->VR_Q(v2);
if (S128_isNeg( tempv2 ))
tempv1 = S128_neg( tempv2 );
else
tempv1 = tempv2;
regs->VR_Q(v1) = tempv1.Q;
}
break;
default:
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7F0 VAVGL - Vector Average Logical [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_average_logical )
{
int v1, v2, v3, m4, m5, m6;
int i; /* loop index */
U64 lsa, lsb; /* least significant 64-bits */
U64 msa; /* most significant 64-bits */
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
ZVECTOR_CHECK( regs );
/* m5 and m5 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
switch (m4)
{
case 0: /* Byte */
for (i=0; i < 16; i++) {
regs->VR_B(v1, i) = (U8) ( ( (U16) regs->VR_B(v2, i) + (U16) regs->VR_B(v3, i) + 1) >> 1 );
}
break;
case 1: /* Halfword */
for (i=0; i < 8; i++) {
regs->VR_H(v1, i) = (U16) ( ( (U32) regs->VR_H(v2, i) + (U32) regs->VR_H(v3, i) + 1) >> 1 );
}
break;
case 2: /* Word */
for (i=0; i < 4; i++) {
regs->VR_F(v1, i) = (U32) ( ( (U64) regs->VR_F(v2, i) + (U64) regs->VR_F(v3, i) + 1) >> 1 );
}
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++) {
/* U128 a + U64 b */
msa = 0;
lsa = regs->VR_D(v2, i);
lsb = regs->VR_D(v3, i);
/* inline U128: a + b */
lsa += lsb;
if ( lsa < lsb ) msa++;
/* inline U128: a+1 */
lsa += 1;
if ( lsa < 1 ) msa++;
/* shift right: average */
regs->VR_D(v1, i) = (lsa >> 1) | ( msa << 63 );
}
break;
case 4: /* Quadword */
{
U128 tempv1, tempv2, tempv3;
U128 temp1, temp2;
int carry = 0;
tempv2.Q = regs->VR_Q(v2);
tempv3.Q = regs->VR_Q(v3);
temp1 = U128_add( tempv2, tempv3);
if ( U128_cmp( temp1, tempv2) == -1 ) carry++;
temp2 = U128_add( temp1, U128_one() );
if ( U128_cmp( temp2, temp1) == -1 ) carry++;
tempv1 = U128_shrl( temp2, 1 );
if ( carry ) tempv1.Q.D.H.D |= 0x8000000000000000ull;
regs->VR_Q(v1) = tempv1.Q;
}
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7F1 VACC - Vector Add Compute Carry [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_add_compute_carry )
{
int v1, v2, v3, m4, m5, m6;
union { U64 d; } temp;
int i;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m5, m6 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
switch (m4)
{
case 0: /* Byte */
for (i=0; i < 16; i++)
{
regs->VR_B( v1, i ) = (U8) ( ( (U16)regs->VR_B( v2, i ) + (U16)regs->VR_B( v3, i ) ) >> 8 );
}
break;
case 1: /* Halfword */
for (i=0; i < 8; i++)
{
regs->VR_H( v1, i ) = (U16) ( ( (U32)regs->VR_H( v2, i ) + (U32)regs->VR_H( v3, i ) ) >> 16 );
}
break;
case 2: /* Word */
for (i=0; i < 4; i++)
{
regs->VR_F( v1, i ) = (U32) ( ( (U64)regs->VR_F( v2, i ) + (U64)regs->VR_F( v3, i ) ) >> 32 );
}
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++)
{
temp.d = 0;
temp.d += regs->VR_F( v2, (i*2)+1 );
temp.d += regs->VR_F( v3, (i*2)+1 );
temp.d >>= 32;
temp.d += regs->VR_F( v2, i*2 );
temp.d += regs->VR_F( v3, i*2 );
regs->VR_D( v1, i ) = temp.d >> 32;
}
break;
case 4: /* Quadword */
temp.d = 0;
for (i=3; i >= 0; i--)
{
temp.d += regs->VR_F( v2, i );
temp.d += regs->VR_F( v3, i );
temp.d >>= 32;
}
regs->VR_D( v1, 0 ) = 0;
regs->VR_D( v1, 1 ) = temp.d;
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7F2 VAVG - Vector Average [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_average )
{
int v1, v2, v3, m4, m5, m6;
int i; /* loop index */
union { S64 sd; } temp; /* signed temp */
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
ZVECTOR_CHECK( regs );
/* m5 and m5 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
switch (m4)
{
case 0: /* Byte */
for (i=0; i < 16; i++) {
regs->VR_B(v1, i) = ( (S16) ( (S8) regs->VR_B(v2, i) + (S8) regs->VR_B(v3, i) ) + 1) >> 1;
}
break;
case 1: /* Halfword */
for (i=0; i < 8; i++) {
regs->VR_H(v1, i) = ( (S32) ( (S16) regs->VR_H(v2, i) + (S16) regs->VR_H(v3, i) ) + 1) >> 1;
}
break;
case 2: /* Word */
for (i=0; i < 4; i++) {
regs->VR_F(v1, i) = ( (S64) ( (S32) regs->VR_F(v2, i) + (S32) regs->VR_F(v3, i) ) + 1) >> 1;
}
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++) {
if (
( regs->VR_D(v2, i) & 0x8000000000000000ull ) ==
( regs->VR_D(v3, i) & 0x8000000000000000ull )
)
{
/* same signs: possible overflow */
if ( regs->VR_D(v2, i) & 0x8000000000000000ull )
{
/* negative signs: allow overflow, round and force back to negative */
temp.sd = (S64) regs->VR_D(v2, i) + (S64) regs->VR_D(v3, i);
temp.sd++;
regs->VR_D(v1, i) = (U64) ( temp.sd >> 1 ) | 0x8000000000000000ull;
}
else
{
/* positive signs: handle as U64 values */
regs->VR_D(v1, i) = (U64) ( ( (U64) regs->VR_D(v2, i) + (U64) regs->VR_D(v3, i) + 1) >> 1 );
}
}
else
{
/* different signs */
regs->VR_D(v1, i) = (U64) ( ( (S64) regs->VR_D(v2, i) + (S64) regs->VR_D(v3, i) + 1) >> 1 );
}
}
break;
case 4: /* Quadword */
{
U128 temp128, tempv2, tempv3;
tempv2.Q = regs->VR_Q(v2);
tempv3.Q = regs->VR_Q(v3);
if (
( regs->VR_D(v2, 0) & 0x8000000000000000ull ) ==
( regs->VR_D(v3, 0) & 0x8000000000000000ull )
)
{
/* same signs: possible overflow */
if ( regs->VR_D(v2, 0) & 0x8000000000000000ull )
{
/* negative signs: allow overflow, round and force back to negative */
temp128 = S128_add( tempv2, tempv3 );
temp128 = S128_add( temp128, U128_one() );
temp128 = U128_shrl( temp128, 1 );
temp128.Q.D.H.D |= 0x8000000000000000ull;
regs->VR_Q(v1) = temp128.Q;
}
else
{
/* positive signs: handle as U128 values */
temp128 = S128_add( tempv2, tempv3 );
temp128 = S128_add( temp128, U128_one() );
temp128 = U128_shrl( temp128, 1 );
regs->VR_Q(v1) = temp128.Q;
}
}
else
{
/* different signs */
temp128 = S128_add( tempv2, tempv3 );
temp128 = S128_add( temp128, U128_one() );
temp128 = U128_shra( temp128, 1 );
regs->VR_Q(v1) = temp128.Q;
}
}
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7F3 VA - Vector Add [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST(vector_add)
{
int v1, v2, v3, m4, m5, m6, i;
U128 temp;
#if defined( _MSVC_ )
U128 copyv2, copyv3;
#endif
VRR_C(inst, regs, v1, v2, v3, m4, m5, m6);
/* m5, m6 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK(regs);
switch (m4)
{
case 0: /* Byte */
for (i=0; i < 16; i++) {
regs->VR_B(v1, i) = (S8) regs->VR_B(v2, i) + (S8) regs->VR_B(v3, i);
}
break;
case 1: /* Halfword */
for (i=0; i < 8; i++) {
regs->VR_H(v1, i) = (S16) regs->VR_H(v2, i) + (S16) regs->VR_H(v3, i);
}
break;
case 2: /* Word */
for (i=0; i < 4; i++) {
regs->VR_F(v1, i) = (S32) regs->VR_F(v2, i) + (S32) regs->VR_F(v3, i);
}
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++) {
regs->VR_D(v1, i) = (S64) regs->VR_D(v2, i) + (S64) regs->VR_D(v3, i);
}
break;
case 4: /* Quadword */
#if defined( _MSVC_ )
copyv2.Q = regs->VR_Q(v2);
copyv3.Q = regs->VR_Q(v3);
temp = U128_add( copyv2, copyv3 );
#else
temp = U128_add( (U128)regs->VR_Q(v2), (U128)regs->VR_Q(v3) );
#endif
regs->VR_Q(v1) = temp.Q;
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END(regs);
}
/*-------------------------------------------------------------------*/
/* E7F5 VSCBI - Vector Subtract Compute Borrow Indication [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_subtract_compute_borrow_indication )
{
int v1, v2, v3, m4, m5, m6;
int i;
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m5, m6 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
switch (m4)
{
case 0: /* Byte */
for (i=0; i < 16; i++)
regs->VR_B( v1, i ) = (regs->VR_B( v2, i ) < regs->VR_B( v3, i )) ? 0 : 1;
break;
case 1: /* Halfword */
for (i=0; i < 8; i++)
regs->VR_H( v1, i ) = (regs->VR_H( v2, i ) < regs->VR_H( v3, i )) ? 0 : 1;
break;
case 2: /* Word */
for (i=0; i < 4; i++)
regs->VR_F( v1, i ) = (regs->VR_F( v2, i ) < regs->VR_F( v3, i )) ? 0 : 1;
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++)
regs->VR_D( v1, i ) = (regs->VR_D( v2, i ) < regs->VR_D( v3, i )) ? 0 : 1;
break;
case 4: /* Quadword */
if (regs->VR_D( v2, 0 ) == regs->VR_D( v3, 0 ))
{
regs->VR_D( v1, 1 ) = (regs->VR_D( v2, 1 ) < regs->VR_D( v3, 1 )) ? 0 : 1;
regs->VR_D( v1, 0 ) = 0;
}
else
{
regs->VR_D( v1, 1 ) = (regs->VR_D( v2, 0 ) < regs->VR_D( v3, 0 )) ? 0 : 1;
regs->VR_D( v1, 0 ) = 0;
}
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7F7 VS - Vector Subtract [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST(vector_subtract)
{
int v1, v2, v3, m4, m5, m6, i;
U128 temp;
#if defined( _MSVC_ )
U128 copyv2, copyv3;
#endif
VRR_C(inst, regs, v1, v2, v3, m4, m5, m6);
/* m5, m6 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK(regs);
switch (m4)
{
case 0: /* Byte */
for (i=0; i < 16; i++) {
regs->VR_B(v1, i) = (S8) regs->VR_B(v2, i) - (S8) regs->VR_B(v3, i);
}
break;
case 1: /* Halfword */
for (i=0; i < 8; i++) {
regs->VR_H(v1, i) = (S16) regs->VR_H(v2, i) - (S16) regs->VR_H(v3, i);
}
break;
case 2: /* Word */
for (i=0; i < 4; i++) {
regs->VR_F(v1, i) = (S32) regs->VR_F(v2, i) - (S32) regs->VR_F(v3, i);
}
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++) {
regs->VR_D(v1, i) = (S64)regs->VR_D(v2, i) - (S64)regs->VR_D(v3, i);
}
break;
case 4: /* Quadword */
#if defined( _MSVC_ )
copyv2.Q = regs->VR_Q(v2);
copyv3.Q = regs->VR_Q(v3);
temp = U128_sub( copyv2, copyv3 );
#else
temp = U128_sub( (U128)regs->VR_Q(v2), (U128)regs->VR_Q(v3) );
#endif
regs->VR_Q(v1) = temp.Q;
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END(regs);
}
/*-------------------------------------------------------------------*/
/* E7F8 VCEQ - Vector Compare Equal [VRR-b] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_compare_equal )
{
int v1, v2, v3, m4, m5;
int i, el, eq = 0;
VRR_B( inst, regs, v1, v2, v3, m4, m5 );
ZVECTOR_CHECK( regs );
#define M5_CS ((m5 & 0x1) != 0) // Condition Code Set
if ( m4 == 4 && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m4)
{
case 0: /* Byte */
for (el=16, i=0; i < 16; i++) {
if (regs->VR_B(v2, i) == regs->VR_B(v3, i)) {
regs->VR_B(v1, i) = 0xff;
eq++;
}
else {
regs->VR_B(v1, i) = 0x00;
}
}
break;
case 1: /* Halfword */
for (el=8, i=0; i < 8; i++) {
if (regs->VR_H(v2, i) == regs->VR_H(v3, i)) {
regs->VR_H(v1, i) = 0xffff;
eq++;
}
else {
regs->VR_H(v1, i) = 0x0000;
}
}
break;
case 2: /* Word */
for (el=4, i=0; i < 4; i++) {
if (regs->VR_F(v2, i) == regs->VR_F(v3, i)) {
regs->VR_F(v1, i) = 0xFFFFFFFF;
eq++;
}
else {
regs->VR_F(v1, i) = 0x00000000;
}
}
break;
case 3: /* Doubleword */
for (el=2, i=0; i < 2; i++) {
if (regs->VR_D(v2, i) == regs->VR_D(v3, i)) {
regs->VR_D(v1, i) = 0xFFFFFFFFFFFFFFFFull;
eq++;
}
else {
regs->VR_D(v1, i) = 0x0000000000000000ull;
}
}
break;
case 4: /* Quadword */
{
U128 tempv1, tempv2, tempv3;
int rc;
el = 1;
tempv2.Q = regs->VR_Q(v2);
tempv3.Q = regs->VR_Q(v3);
rc = U128_cmp( tempv2, tempv3 );
if (rc == 0) {
tempv1 = U128_minus_one();
eq++;
}
else {
tempv1 = U128_zero();
}
regs->VR_Q(v1) = tempv1.Q;
}
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
if (M5_CS) {
if (eq == el)
regs->psw.cc = 0;
else if (eq != 0)
regs->psw.cc = 1;
else
regs->psw.cc = 3;
}
#undef M5_CS
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7F9 VCHL - Vector Compare High Logical [VRR-b] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_compare_high_logical )
{
int v1, v2, v3, m4, m5;
int i, el, hi = 0;
VRR_B( inst, regs, v1, v2, v3, m4, m5 );
ZVECTOR_CHECK( regs );
#define M5_CS ((m5 & 0x1) != 0) // Condition Code Set
if ( m4 == 4 && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m4)
{
case 0: /* Byte */
for (el=16, i=0; i < 16; i++) {
if (regs->VR_B(v2, i) > regs->VR_B(v3, i)) {
regs->VR_B(v1, i) = 0xff;
hi++;
}
else {
regs->VR_B(v1, i) = 0x00;
}
}
break;
case 1: /* Halfword */
for (el=8, i=0; i < 8; i++) {
if (regs->VR_H(v2, i) > regs->VR_H(v3, i)) {
regs->VR_H(v1, i) = 0xffff;
hi++;
}
else {
regs->VR_H(v1, i) = 0x0000;
}
}
break;
case 2: /* Word */
for (el=4, i=0; i < 4; i++) {
if (regs->VR_F(v2, i) > regs->VR_F(v3, i)) {
regs->VR_F(v1, i) = 0xFFFFFFFF;
hi++;
}
else {
regs->VR_F(v1, i) = 0x00000000;
}
}
break;
case 3: /* Doubleword */
for (el=2, i=0; i < 2; i++) {
if (regs->VR_D(v2, i) > regs->VR_D(v3, i)) {
regs->VR_D(v1, i) = 0xFFFFFFFFFFFFFFFFull;
hi++;
}
else {
regs->VR_D(v1, i) = 0x0000000000000000ull;
}
}
break;
case 4: /* Quadword */
{
U128 tempv1, tempv2, tempv3;
int rc;
el = 1;
tempv2.Q = regs->VR_Q(v2);
tempv3.Q = regs->VR_Q(v3);
rc = U128_cmp( tempv2, tempv3 );
if (rc == 1) {
tempv1 = U128_minus_one();
hi++;
}
else {
tempv1 = U128_zero();
}
regs->VR_Q(v1) = tempv1.Q;
}
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
if (M5_CS) {
if (hi == el)
regs->psw.cc = 0;
else if (hi != 0)
regs->psw.cc = 1;
else
regs->psw.cc = 3;
}
#undef M5_CS
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7FB VCH - Vector Compare High [VRR-b] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_compare_high )
{
int v1, v2, v3, m4, m5;
int i, el, hi = 0;
VRR_B( inst, regs, v1, v2, v3, m4, m5 );
ZVECTOR_CHECK( regs );
#define M5_CS ((m5 & 0x1) != 0) // Condition Code Set
if ( m4 == 4 && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m4)
{
case 0: /* Byte */
for (el=16, i=0; i < 16; i++) {
if ( (S8) regs->VR_B(v2, i) > (S8) regs->VR_B(v3, i) ) {
regs->VR_B(v1, i) = 0xff;
hi++;
}
else {
regs->VR_B(v1, i) = 0x00;
}
}
break;
case 1: /* Halfword */
for (el=8, i=0; i < 8; i++) {
if ( (S16) regs->VR_H(v2, i) > (S16) regs->VR_H(v3, i) ) {
regs->VR_H(v1, i) = 0xffff;
hi++;
}
else {
regs->VR_H(v1, i) = 0x0000;
}
}
break;
case 2: /* Word */
for (el=4, i=0; i < 4; i++) {
if ( (S32) regs->VR_F(v2, i) > (S32) regs->VR_F(v3, i) ) {
regs->VR_F(v1, i) = 0xFFFFFFFF;
hi++;
}
else {
regs->VR_F(v1, i) = 0x00000000;
}
}
break;
case 3: /* Doubleword */
for (el=2, i=0; i < 2; i++) {
if ( (S64) regs->VR_D(v2, i) > (S64) regs->VR_D(v3, i) ) {
regs->VR_D(v1, i) = 0xFFFFFFFFFFFFFFFFull;
hi++;
}
else {
regs->VR_D(v1, i) = 0x0000000000000000ull;
}
}
break;
case 4: /* Quadword */
{
U128 tempv1, tempv2, tempv3;
int rc;
el = 1;
tempv2.Q = regs->VR_Q(v2);
tempv3.Q = regs->VR_Q(v3);
rc = S128_cmp( tempv2, tempv3 );
if (rc == 1) {
tempv1 = U128_minus_one();
hi++;
}
else {
tempv1 = U128_zero();
}
regs->VR_Q(v1) = tempv1.Q;
}
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
if (M5_CS) {
if (hi == el)
regs->psw.cc = 0;
else if (hi != 0)
regs->psw.cc = 1;
else
regs->psw.cc = 3;
}
#undef M5_CS
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7FC VMNL - Vector Minimum Logical [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_minimum_logical )
{
int v1, v2, v3, m4, m5, m6;
int i; /* loop index */
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m5, m6 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
if ( m4 == 4 && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m4)
{
case 0: /* Byte */
for (i=0; i < 16; i++) {
regs->VR_B(v1, i) = regs->VR_B(v2, i) <= regs->VR_B(v3, i) ? regs->VR_B(v2, i) : regs->VR_B(v3, i);
}
break;
case 1: /* Halfword */
for (i=0; i < 8; i++) {
regs->VR_H(v1, i) = regs->VR_H(v2, i) <= regs->VR_H(v3, i) ? regs->VR_H(v2, i) : regs->VR_H(v3, i);
}
break;
case 2: /* Word */
for (i=0; i < 4; i++) {
regs->VR_F(v1, i) = regs->VR_F(v2, i) <= regs->VR_F(v3, i) ? regs->VR_F(v2, i) : regs->VR_F(v3, i);
}
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++) {
regs->VR_D(v1, i) = regs->VR_D(v2, i) <= regs->VR_D(v3, i) ? regs->VR_D(v2, i) : regs->VR_D(v3, i);
}
break;
case 4: /* Quadword */
{
U128 tempv2, tempv3;
tempv2.Q = regs->VR_Q(v2);
tempv3.Q = regs->VR_Q(v3);
regs->VR_Q(v1) = ( U128_cmp( tempv2, tempv3) == -1) ? regs->VR_Q(v2) : regs->VR_Q(v3);
}
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7FD VMXL - Vector Maximum Logical [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_maximum_logical )
{
int v1, v2, v3, m4, m5, m6;
int i; /* loop index */
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m5, m6 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
if ( m4 == 4 && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m4)
{
case 0: /* Byte */
for (i=0; i < 16; i++) {
regs->VR_B(v1, i) = regs->VR_B(v2, i) >= regs->VR_B(v3, i) ? regs->VR_B(v2, i) : regs->VR_B(v3, i);
}
break;
case 1: /* Halfword */
for (i=0; i < 8; i++) {
regs->VR_H(v1, i) = regs->VR_H(v2, i) >= regs->VR_H(v3, i) ? regs->VR_H(v2, i) : regs->VR_H(v3, i);
}
break;
case 2: /* Word */
for (i=0; i < 4; i++) {
regs->VR_F(v1, i) = regs->VR_F(v2, i) >= regs->VR_F(v3, i) ? regs->VR_F(v2, i) : regs->VR_F(v3, i);
}
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++) {
regs->VR_D(v1, i) = regs->VR_D(v2, i) >= regs->VR_D(v3, i) ? regs->VR_D(v2, i) : regs->VR_D(v3, i);
}
break;
case 4: /* Quadword */
{
U128 tempv2, tempv3;
tempv2.Q = regs->VR_Q(v2);
tempv3.Q = regs->VR_Q(v3);
regs->VR_Q(v1) = ( U128_cmp( tempv2, tempv3) == 1) ? regs->VR_Q(v2) : regs->VR_Q(v3);
}
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7FE VMN - Vector Minimum [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_minimum )
{
int v1, v2, v3, m4, m5, m6;
int i; /* loop index */
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m5, m6 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
if ( m4 == 4 && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m4)
{
case 0: /* Byte */
for (i=0; i < 16; i++) {
regs->VR_B(v1, i) = (S8) regs->VR_B(v2, i) <= (S8) regs->VR_B(v3, i) ? regs->VR_B(v2, i) : regs->VR_B(v3, i);
}
break;
case 1: /* Halfword */
for (i=0; i < 8; i++) {
regs->VR_H(v1, i) = (S16) regs->VR_H(v2, i) <= (S16) regs->VR_H(v3, i) ? regs->VR_H(v2, i) : regs->VR_H(v3, i);
}
break;
case 2: /* Word */
for (i=0; i < 4; i++) {
regs->VR_F(v1, i) = (S32) regs->VR_F(v2, i) <= (S32) regs->VR_F(v3, i) ? regs->VR_F(v2, i) : regs->VR_F(v3, i);
}
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++) {
regs->VR_D(v1, i) = (S64) regs->VR_D(v2, i) <= (S64) regs->VR_D(v3, i) ? regs->VR_D(v2, i) : regs->VR_D(v3, i);
}
break;
case 4: /* Quadword */
{
U128 tempv2, tempv3;
tempv2.Q = regs->VR_Q(v2);
tempv3.Q = regs->VR_Q(v3);
regs->VR_Q(v1) = ( S128_cmp( tempv2, tempv3) == -1) ? regs->VR_Q(v2) : regs->VR_Q(v3);
}
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
/*-------------------------------------------------------------------*/
/* E7FF VMX - Vector Maximum [VRR-c] */
/*-------------------------------------------------------------------*/
DEF_INST( vector_maximum )
{
int v1, v2, v3, m4, m5, m6;
int i; /* loop index */
VRR_C( inst, regs, v1, v2, v3, m4, m5, m6 );
/* m5, m6 are not part of this instruction */
UNREFERENCED( m5 );
UNREFERENCED( m6 );
ZVECTOR_CHECK( regs );
if ( m4 == 4 && !FACILITY_ENABLED( 198_VECTOR_ENH_3, regs ) )
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
switch (m4)
{
case 0: /* Byte */
for (i=0; i < 16; i++) {
regs->VR_B(v1, i) = (S8) regs->VR_B(v2, i) >= (S8) regs->VR_B(v3, i) ? regs->VR_B(v2, i) : regs->VR_B(v3, i);
}
break;
case 1: /* Halfword */
for (i=0; i < 8; i++) {
regs->VR_H(v1, i) = (S16) regs->VR_H(v2, i) >= (S16) regs->VR_H(v3, i) ? regs->VR_H(v2, i) : regs->VR_H(v3, i);
}
break;
case 2: /* Word */
for (i=0; i < 4; i++) {
regs->VR_F(v1, i) = (S32) regs->VR_F(v2, i) >= (S32) regs->VR_F(v3, i) ? regs->VR_F(v2, i) : regs->VR_F(v3, i);
}
break;
case 3: /* Doubleword */
for (i=0; i < 2; i++) {
regs->VR_D(v1, i) = (S64) regs->VR_D(v2, i) >= (S64) regs->VR_D(v3, i) ? regs->VR_D(v2, i) : regs->VR_D(v3, i);
}
break;
case 4: /* Quadword */
{
U128 tempv2, tempv3;
tempv2.Q = regs->VR_Q(v2);
tempv3.Q = regs->VR_Q(v3);
regs->VR_Q(v1) = ( S128_cmp( tempv2, tempv3) == 1) ? regs->VR_Q(v2) : regs->VR_Q(v3);
}
break;
default:
ARCH_DEP( program_interrupt )( regs, PGM_SPECIFICATION_EXCEPTION );
break;
}
ZVECTOR_END( regs );
}
#endif /* defined( FEATURE_129_ZVECTOR_FACILITY ) */
#if !defined( _GEN_ARCH )
#if defined( _ARCH_NUM_1 )
#define _GEN_ARCH _ARCH_NUM_1
#include "zvector.c"
#endif
#if defined( _ARCH_NUM_2 )
#undef _GEN_ARCH
#define _GEN_ARCH _ARCH_NUM_2
#include "zvector.c"
#endif
#endif /*!defined(_GEN_ARCH)*/