mirror of
https://github.com/SDL-Hercules-390/hyperion.git
synced 2026-07-27 19:10:08 +02:00
d79382bbfe
* 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
8345 lines
255 KiB
C
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)*/
|