mirror of
https://github.com/SDL-Hercules-390/hyperion.git
synced 2026-05-30 14:07:41 +02:00
50546b33fc
Update to device list git-svn-id: file:///home/jj/hercules.svn/trunk@821 956126f8-22a0-4046-8f4a-272fa8102e63
4950 lines
176 KiB
C
4950 lines
176 KiB
C
/* ESAME.C (c) Copyright Jan Jaeger, 2000-2002 */
|
|
/* ESAME (z/Architecture) instructions */
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* This module implements the instructions which exist in ESAME */
|
|
/* mode but not in ESA/390 mode, as described in the manual */
|
|
/* SA22-7832-00 z/Architecture Principles of Operation */
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* Additional credits: */
|
|
/* EPSW/EREGG/LMD instructions - Roger Bowler */
|
|
/* PKA/PKU/UNPKA/UNPKU instructions - Roger Bowler */
|
|
/* Divide logical instructions - Vic Cross */
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
#include "hercules.h"
|
|
|
|
#include "opcode.h"
|
|
|
|
#include "inline.h"
|
|
|
|
#if !defined(_LONG_MATH)
|
|
#define _LONG_MATH
|
|
/* These routines need to go into inline.h *JJ */
|
|
static inline int add_logical_long(U64 *result, U64 op1, U64 op2)
|
|
{
|
|
*result = op1 + op2;
|
|
|
|
return (*result == 0 ? 0 : 1) | (op1 > *result ? 2 : 0);
|
|
} /* end add_logical_long() */
|
|
|
|
|
|
static inline int sub_logical_long(U64 *result, U64 op1, U64 op2)
|
|
{
|
|
*result = op1 - op2;
|
|
|
|
return (*result == 0 ? 0 : 1) | (op1 < *result ? 0 : 2);
|
|
} /* end sub_logical_long() */
|
|
|
|
|
|
static inline int add_signed_long(U64 *result, U64 op1, U64 op2)
|
|
{
|
|
*result = (S64)op1 + (S64)op2;
|
|
|
|
return (((S64)op1 < 0 && (S64)op2 < 0 && (S64)*result >= 0)
|
|
|| ((S64)op1 >= 0 && (S64)op2 >= 0 && (S64)*result < 0)) ? 3 :
|
|
(S64)*result < 0 ? 1 :
|
|
(S64)*result > 0 ? 2 : 0;
|
|
} /* end add_signed_long() */
|
|
|
|
|
|
static inline int sub_signed_long(U64 *result, U64 op1, U64 op2)
|
|
{
|
|
*result = (S64)op1 - (S64)op2;
|
|
|
|
return (((S64)op1 < 0 && (S64)op2 >= 0 && (S64)*result >= 0)
|
|
|| ((S64)op1 >= 0 && (S64)op2 < 0 && (S64)*result < 0)) ? 3 :
|
|
(S64)*result < 0 ? 1 :
|
|
(S64)*result > 0 ? 2 : 0;
|
|
} /* end sub_signed_long() */
|
|
|
|
|
|
static inline int div_logical_long
|
|
(U64 *rem, U64 *quot, U64 high, U64 lo, U64 d)
|
|
{
|
|
int i;
|
|
|
|
*quot = 0;
|
|
if (high >= d) return 1;
|
|
for (i = 0; i < 64; i++)
|
|
{
|
|
int ovf;
|
|
ovf = high >> 63;
|
|
high = (high << 1) | (lo >> 63);
|
|
lo <<= 1;
|
|
*quot <<= 1;
|
|
if (high >= d || ovf)
|
|
{
|
|
*quot += 1;
|
|
high -= d;
|
|
}
|
|
}
|
|
*rem = high;
|
|
return 0;
|
|
} /* end div_logical_long() */
|
|
|
|
|
|
static inline int mult_logical_long
|
|
(U64 *high, U64 *lo, U64 md, U64 mr)
|
|
{
|
|
int i;
|
|
|
|
*high = 0; *lo = 0;
|
|
for (i = 0; i < 64; i++)
|
|
{
|
|
U64 ovf;
|
|
ovf = *high;
|
|
if (md & 1)
|
|
*high += mr;
|
|
md >>= 1;
|
|
*lo = (*lo >> 1) | (*high << 63);
|
|
if(ovf > *high)
|
|
*high = (*high >> 1) | 0x8000000000000000ULL;
|
|
else
|
|
*high >>= 1;
|
|
}
|
|
return 0;
|
|
} /* end mult_logical_long() */
|
|
#endif /*!defined(_LONG_MATH)*/
|
|
|
|
|
|
#if defined(FEATURE_BINARY_FLOATING_POINT)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B29C STFPC - Store FPC [S] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(store_fpc)
|
|
{
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
|
|
S(inst, execflag, regs, b2, effective_addr2);
|
|
|
|
BFPINST_CHECK(regs);
|
|
|
|
/* Store register contents at operand address */
|
|
ARCH_DEP(vstore4) ( regs->fpc, effective_addr2, b2, regs );
|
|
|
|
} /* end DEF_INST(store_fpc) */
|
|
#endif /*defined(FEATURE_BINARY_FLOATING_POINT)*/
|
|
|
|
|
|
#if defined(FEATURE_BINARY_FLOATING_POINT)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B29D LFPC - Load FPC [S] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_fpc)
|
|
{
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
U32 tmp_fpc;
|
|
|
|
S(inst, execflag, regs, b2, effective_addr2);
|
|
|
|
BFPINST_CHECK(regs);
|
|
|
|
/* Load FPC register from operand address */
|
|
tmp_fpc = ARCH_DEP(vfetch4) (effective_addr2, b2, regs);
|
|
|
|
if(tmp_fpc & FPC_RESERVED)
|
|
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
|
|
else
|
|
regs->fpc = tmp_fpc;
|
|
|
|
} /* end DEF_INST(load_fpc) */
|
|
#endif /*defined(FEATURE_BINARY_FLOATING_POINT)*/
|
|
|
|
|
|
#if defined(FEATURE_BINARY_FLOATING_POINT)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B384 SFPC - Set FPC [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(set_fpc)
|
|
{
|
|
int r1, unused; /* Values of R fields */
|
|
|
|
RRE(inst, execflag, regs, r1, unused);
|
|
|
|
BFPINST_CHECK(regs);
|
|
|
|
/* Load FPC register from R1 register bits 32-63 */
|
|
if(regs->GR_L(r1) & FPC_RESERVED)
|
|
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
|
|
else
|
|
regs->fpc = regs->GR_L(r1);
|
|
|
|
} /* end DEF_INST(set_fpc) */
|
|
#endif /*defined(FEATURE_BINARY_FLOATING_POINT)*/
|
|
|
|
|
|
#if defined(FEATURE_BINARY_FLOATING_POINT)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B38C EFPC - Extract FPC [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(extract_fpc)
|
|
{
|
|
int r1, unused; /* Values of R fields */
|
|
|
|
RRE(inst, execflag, regs, r1, unused);
|
|
|
|
BFPINST_CHECK(regs);
|
|
|
|
/* Load R1 register bits 32-63 from FPC register */
|
|
regs->GR_L(r1) = regs->fpc;
|
|
|
|
} /* end DEF_INST(extract_fpc) */
|
|
#endif /*defined(FEATURE_BINARY_FLOATING_POINT)*/
|
|
|
|
|
|
#if defined(FEATURE_BINARY_FLOATING_POINT)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B299 SRNM - Set Rounding Mode [S] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(set_rounding_mode)
|
|
{
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
|
|
S(inst, execflag, regs, b2, effective_addr2);
|
|
|
|
BFPINST_CHECK(regs);
|
|
|
|
/* Set FPC register rounding mode bits from operand address */
|
|
regs->fpc &= ~(FPC_RM);
|
|
regs->fpc |= (effective_addr2 & FPC_RM);
|
|
|
|
} /* end DEF_INST(set_rounding_mode) */
|
|
#endif /*defined(FEATURE_BINARY_FLOATING_POINT)*/
|
|
|
|
|
|
#if defined(FEATURE_LINKAGE_STACK)
|
|
/*-------------------------------------------------------------------*/
|
|
/* 01FF TRAP2 - Trap [E] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(trap2)
|
|
{
|
|
E(inst, execflag, regs);
|
|
|
|
SIE_MODE_XC_SOPEX(regs);
|
|
|
|
ARCH_DEP(trap_x) (0, execflag, regs, 0);
|
|
|
|
} /* end DEF_INST(trap2) */
|
|
#endif /*defined(FEATURE_LINKAGE_STACK)*/
|
|
|
|
|
|
#if defined(FEATURE_LINKAGE_STACK)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B2FF TRAP4 - Trap [S] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(trap4)
|
|
{
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
|
|
S(inst, execflag, regs, b2, effective_addr2);
|
|
|
|
SIE_MODE_XC_SOPEX(regs);
|
|
|
|
ARCH_DEP(trap_x) (1, execflag, regs, effective_addr2);
|
|
|
|
} /* end DEF_INST(trap4) */
|
|
#endif /*defined(FEATURE_LINKAGE_STACK)*/
|
|
|
|
|
|
#if defined(FEATURE_RESUME_PROGRAM)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B277 RP - Resume Program [S] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(resume_program)
|
|
{
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
VADR pl_addr; /* Address of parmlist */
|
|
U16 flags; /* Flags in parmfield */
|
|
U16 psw_offset; /* Offset to new PSW */
|
|
U16 ar_offset; /* Offset to new AR */
|
|
U16 gr_offset; /* Offset to new GR */
|
|
U32 ar; /* Copy of new AR */
|
|
#if defined(FEATURE_ESAME)
|
|
U16 grd_offset; /* Offset of disjoint GR_H */
|
|
BYTE psw[16]; /* Copy of new PSW */
|
|
U64 gr; /* Copy of new GR */
|
|
U64 ia; /* ia for trace */
|
|
#else /*!defined(FEATURE_ESAME)*/
|
|
BYTE psw[8]; /* Copy of new PSW */
|
|
U32 gr; /* Copy of new GR */
|
|
U32 ia; /* ia for trace */
|
|
#endif /*!defined(FEATURE_ESAME)*/
|
|
BYTE amode; /* amode for trace */
|
|
PSW save_psw; /* Saved copy of current PSW */
|
|
RADR abs; /* Absolute address of parm */
|
|
#ifdef FEATURE_TRACING
|
|
CREG newcr12 = 0; /* CR12 upon completion */
|
|
#endif /*FEATURE_TRACING*/
|
|
|
|
S(inst, execflag, regs, b2, effective_addr2);
|
|
|
|
/* Determine the address of the parameter list */
|
|
pl_addr = !execflag ? regs->psw.IA : (regs->ET + 4);
|
|
|
|
/* Fetch flags from the instruction address space */
|
|
abs = LOGICAL_TO_ABS (pl_addr, 0, regs,
|
|
ACCTYPE_INSTFETCH, regs->psw.pkey);
|
|
FETCH_HW(flags, sysblk.mainstor + abs);
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/* Bits 0-12 must be zero */
|
|
if(flags & 0xFFF8)
|
|
#else /*!defined(FEATURE_ESAME)*/
|
|
/* All flag bits must be zero in ESA/390 mode */
|
|
if(flags)
|
|
#endif /*!defined(FEATURE_ESAME)*/
|
|
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
|
|
|
|
/* Fetch the offset to the new psw */
|
|
abs = LOGICAL_TO_ABS (pl_addr + 2, 0, regs,
|
|
ACCTYPE_INSTFETCH, regs->psw.pkey);
|
|
FETCH_HW(psw_offset, sysblk.mainstor + abs);
|
|
|
|
/* Fetch the offset to the new ar */
|
|
abs = LOGICAL_TO_ABS (pl_addr + 4, 0, regs,
|
|
ACCTYPE_INSTFETCH, regs->psw.pkey);
|
|
FETCH_HW(ar_offset, sysblk.mainstor + abs);
|
|
|
|
/* Fetch the offset to the new gr */
|
|
abs = LOGICAL_TO_ABS (pl_addr + 6, 0, regs,
|
|
ACCTYPE_INSTFETCH, regs->psw.pkey);
|
|
FETCH_HW(gr_offset, sysblk.mainstor + abs);
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/* Fetch the offset to the new disjoint gr_h */
|
|
if((flags & 0x0003) == 0x0003)
|
|
{
|
|
abs = LOGICAL_TO_ABS (pl_addr + 8, 0, regs,
|
|
ACCTYPE_INSTFETCH, regs->psw.pkey);
|
|
FETCH_HW(grd_offset, sysblk.mainstor + abs);
|
|
}
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
/* Fetch the PSW from the operand address + psw offset */
|
|
#if defined(FEATURE_ESAME)
|
|
if(flags & 0x0004)
|
|
ARCH_DEP(vfetchc) (psw, 15, (effective_addr2 + psw_offset)
|
|
& ADDRESS_MAXWRAP(regs), b2, regs);
|
|
else
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
ARCH_DEP(vfetchc) (psw, 7, (effective_addr2 + psw_offset)
|
|
& ADDRESS_MAXWRAP(regs), b2, regs);
|
|
|
|
|
|
/* Fetch new AR (B2) from operand address + AR offset */
|
|
ar = ARCH_DEP(vfetch4) ((effective_addr2 + ar_offset)
|
|
& ADDRESS_MAXWRAP(regs), b2, regs);
|
|
|
|
|
|
/* Fetch the new gr from operand address + GPR offset */
|
|
#if defined(FEATURE_ESAME)
|
|
if(flags & 0x0002)
|
|
gr = ARCH_DEP(vfetch8) ((effective_addr2 + gr_offset)
|
|
& ADDRESS_MAXWRAP(regs), b2, regs);
|
|
else
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
gr = ARCH_DEP(vfetch4) ((effective_addr2 + gr_offset)
|
|
& ADDRESS_MAXWRAP(regs), b2, regs);
|
|
|
|
#if defined(FEATURE_TRACING)
|
|
#if defined(FEATURE_ESAME)
|
|
FETCH_DW(ia, psw + 8);
|
|
amode = psw[3] & 0x01;
|
|
#else /*!defined(FEATURE_ESAME)*/
|
|
FETCH_FW(ia, psw + 4);
|
|
ia &= 0x7FFFFFFF;
|
|
amode = psw[4] & 0x80;
|
|
#endif /*!defined(FEATURE_ESAME)*/
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/* Add a mode trace entry when switching in/out of 64 bit mode */
|
|
if((regs->CR(12) & CR12_MTRACE) && regs->psw.amode64 != amode)
|
|
ARCH_DEP(trace_ms) (regs->CR(12) & CR12_BRTRACE, ia | regs->psw.amode64 ? amode << 31 : 0, regs);
|
|
else
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
if (regs->CR(12) & CR12_BRTRACE)
|
|
newcr12 = ARCH_DEP(trace_br) (amode, ia, regs);
|
|
#endif /*defined(FEATURE_TRACING)*/
|
|
|
|
|
|
/* Save current PSW */
|
|
save_psw = regs->psw;
|
|
|
|
|
|
/* Use bits 16-23, 32-63 of psw in operand, other bits from old psw */
|
|
psw[0] = save_psw.sysmask;
|
|
psw[1] = save_psw.pkey | 0x08 | save_psw.mach<<2 | save_psw.wait<<1 | save_psw.prob;
|
|
psw[3] = 0;
|
|
|
|
|
|
#if defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)
|
|
if(regs->sie_state
|
|
&& (regs->siebk->mx & SIE_MX_XC)
|
|
&& (psw[2] & 0x80))
|
|
ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION);
|
|
#endif /*defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/
|
|
|
|
|
|
/* Privileged Operation exception when setting home
|
|
space mode in problem state */
|
|
if(!REAL_MODE(®s->psw)
|
|
&& regs->psw.prob
|
|
&& ((psw[2] & 0xC0) == 0xC0) )
|
|
ARCH_DEP(program_interrupt) (regs, PGM_PRIVILEGED_OPERATION_EXCEPTION);
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
if(flags & 0x0004)
|
|
{
|
|
/* Do not check esame bit (force to zero) */
|
|
psw[1] &= ~0x08;
|
|
if( ARCH_DEP(load_psw) (regs, psw) )/* only check invalid IA not odd */
|
|
{
|
|
/* restore the psw */
|
|
regs->psw = save_psw;
|
|
/* And generate a program interrupt */
|
|
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
|
|
}
|
|
}
|
|
else
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
{
|
|
#if defined(FEATURE_ESAME)
|
|
/* Do not check amode64 bit (force to zero) */
|
|
psw[3] &= ~0x01;
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
if( s390_load_psw(regs, psw) )
|
|
{
|
|
/* restore the psw */
|
|
regs->psw = save_psw;
|
|
/* And generate a program interrupt */
|
|
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
|
|
}
|
|
#if defined(FEATURE_ESAME)
|
|
regs->psw.notesame = 0;
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
}
|
|
|
|
/* load_psw() has set the ILC to zero. This needs to
|
|
be reset to 4 for an eventual PER event */
|
|
regs->psw.ilc = 4;
|
|
|
|
/* Check for odd IA in psw */
|
|
if(regs->psw.IA & 0x01)
|
|
{
|
|
/* restore the psw */
|
|
regs->psw = save_psw;
|
|
/* And generate a program interrupt */
|
|
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
|
|
}
|
|
|
|
SET_IC_EXTERNAL_MASK(regs);
|
|
SET_IC_MCK_MASK(regs);
|
|
SET_IC_ECIO_MASK(regs);
|
|
SET_IC_PSW_WAIT(regs);
|
|
|
|
/* Update access register b2 */
|
|
regs->AR(b2) = ar;
|
|
INVALIDATE_AEA(b2, regs);
|
|
|
|
/* Update general register b2 */
|
|
#if defined(FEATURE_ESAME)
|
|
if(flags & 0x0002)
|
|
regs->GR_G(b2) = gr;
|
|
else
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
regs->GR_L(b2) = gr;
|
|
|
|
#ifdef FEATURE_TRACING
|
|
/* Update trace table address if branch tracing is on */
|
|
if (regs->CR(12) & CR12_BRTRACE)
|
|
regs->CR(12) = newcr12;
|
|
#endif /*FEATURE_TRACING*/
|
|
|
|
#if defined(FEATURE_PER)
|
|
if( EN_IC_PER_SB(regs)
|
|
#if defined(FEATURE_PER2)
|
|
&& ( !(regs->CR(9) & CR9_BAC)
|
|
|| PER_RANGE_CHECK(regs->psw.IA,regs->CR(10),regs->CR(11)) )
|
|
#endif /*defined(FEATURE_PER2)*/
|
|
)
|
|
ON_IC_PER_SB(regs);
|
|
#endif /*defined(FEATURE_PER)*/
|
|
|
|
/* Space switch event when switching into or
|
|
out of home space mode AND space-switch-event on in CR1 or CR13 */
|
|
if((HOME_SPACE_MODE(&(regs->psw)) ^ HOME_SPACE_MODE(&save_psw))
|
|
&& (!REAL_MODE(®s->psw))
|
|
&& ((regs->CR(1) & SSEVENT_BIT) || (regs->CR(13) & SSEVENT_BIT)
|
|
|| OPEN_IC_PERINT(regs) ))
|
|
{
|
|
if (HOME_SPACE_MODE(&(regs->psw)))
|
|
{
|
|
/* When switching into home-space mode, set the
|
|
translation exception address equal to the primary
|
|
ASN, with the high-order bit set equal to the value
|
|
of the primary space-switch-event control bit */
|
|
regs->TEA = regs->CR_LHL(4);
|
|
if (regs->CR(1) & SSEVENT_BIT)
|
|
regs->TEA |= TEA_SSEVENT;
|
|
}
|
|
else
|
|
{
|
|
/* When switching out of home-space mode, set the
|
|
translation exception address equal to zero, with
|
|
the high-order bit set equal to the value of the
|
|
home space-switch-event control bit */
|
|
regs->TEA = 0;
|
|
if (regs->CR(13) & SSEVENT_BIT)
|
|
regs->TEA |= TEA_SSEVENT;
|
|
}
|
|
regs->psw.ilc = 4;
|
|
ARCH_DEP(program_interrupt) (regs, PGM_SPACE_SWITCH_EVENT);
|
|
}
|
|
|
|
RETURN_INTCHECK(regs);
|
|
|
|
} /* end DEF_INST(resume_program) */
|
|
#endif /*defined(FEATURE_RESUME_PROGRAM)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME) && defined(FEATURE_TRACING)
|
|
/*-------------------------------------------------------------------*/
|
|
/* EB0F TRACG - Trace Long [RSE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(trace_long)
|
|
{
|
|
int r1, r3; /* Register numbers */
|
|
int b2; /* effective address base */
|
|
VADR effective_addr2; /* effective address */
|
|
#if defined(FEATURE_TRACING)
|
|
U32 op; /* Operand */
|
|
#endif /*defined(FEATURE_TRACING)*/
|
|
|
|
RSE(inst, execflag, regs, r1, r3, b2, effective_addr2);
|
|
|
|
PRIV_CHECK(regs);
|
|
|
|
FW_CHECK(effective_addr2, regs);
|
|
|
|
/* Exit if explicit tracing (control reg 12 bit 31) is off */
|
|
if ( (regs->CR(12) & CR12_EXTRACE) == 0 )
|
|
return;
|
|
|
|
/* Fetch the trace operand */
|
|
op = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs );
|
|
|
|
/* Exit if bit zero of the trace operand is one */
|
|
if ( (op & 0x80000000) )
|
|
return;
|
|
|
|
/* Perform serialization and checkpoint-synchronization */
|
|
PERFORM_SERIALIZATION (regs);
|
|
PERFORM_CHKPT_SYNC (regs);
|
|
|
|
regs->CR(12) = ARCH_DEP(trace_tg) (r1, r3, op, regs);
|
|
|
|
/* Perform serialization and checkpoint-synchronization */
|
|
PERFORM_SERIALIZATION (regs);
|
|
PERFORM_CHKPT_SYNC (regs);
|
|
|
|
} /* end DEF_INST(trace_long) */
|
|
#endif /*defined(FEATURE_ESAME) && defined(FEATURE_TRACING)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E30E CVBG - Convert to Binary Long [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(convert_to_binary_long)
|
|
{
|
|
int r1; /* Values of R fields */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
U64 dreg; /* 64-bit result accumulator */
|
|
int i; /* Loop counter */
|
|
int h, d; /* Decimal digits */
|
|
BYTE sbyte; /* Source operand byte */
|
|
int ovf = 0; /* Overflow indicator */
|
|
U64 oreg = 0; /* 64 bit overflow work reg */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Initialize binary result */
|
|
dreg = 0;
|
|
|
|
/* Convert digits to binary */
|
|
for (i = 0; i < 16; i++)
|
|
{
|
|
/* Load next byte of operand */
|
|
sbyte = ARCH_DEP(vfetchb) ( effective_addr2, b2, regs );
|
|
|
|
/* Isolate high-order and low-order digits */
|
|
h = (sbyte & 0xF0) >> 4;
|
|
d = sbyte & 0x0F;
|
|
|
|
/* Check for valid high-order digit */
|
|
if (h > 9)
|
|
{
|
|
regs->dxc = DXC_DECIMAL;
|
|
ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
|
|
}
|
|
|
|
/* Accumulate high-order digit into result */
|
|
dreg *= 10;
|
|
dreg += h;
|
|
|
|
/* Set overflow indicator if an overflow has occurred */
|
|
if(dreg < oreg)
|
|
ovf = 1;
|
|
|
|
/* Save current value */
|
|
oreg = dreg;
|
|
|
|
/* Check for valid low-order digit or sign */
|
|
if (i < 15)
|
|
{
|
|
/* Check for valid low-order digit */
|
|
if (d > 9)
|
|
{
|
|
regs->dxc = DXC_DECIMAL;
|
|
ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
|
|
}
|
|
|
|
/* Accumulate low-order digit into result */
|
|
dreg *= 10;
|
|
dreg += d;
|
|
}
|
|
else
|
|
{
|
|
/* Check for valid sign */
|
|
if (d < 10)
|
|
{
|
|
regs->dxc = DXC_DECIMAL;
|
|
ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
|
|
}
|
|
}
|
|
|
|
/* Increment operand address */
|
|
effective_addr2++;
|
|
effective_addr2 &= ADDRESS_MAXWRAP(regs);
|
|
|
|
} /* end for(i) */
|
|
|
|
/* Result is negative if sign is X'B' or X'D' */
|
|
if (d == 0x0B || d == 0x0D)
|
|
{
|
|
if( (S64)dreg == -1LL )
|
|
ovf = 1;
|
|
(S64)dreg = -((S64)dreg);
|
|
}
|
|
|
|
/* Store result into R1 register */
|
|
regs->GR_G(r1) = dreg;
|
|
|
|
/* Program check if overflow */
|
|
if ( ovf )
|
|
ARCH_DEP(program_interrupt) (regs, PGM_FIXED_POINT_DIVIDE_EXCEPTION);
|
|
|
|
} /* end DEF_INST(convert_to_binary_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E32E CVDG - Convert to Decimal Long [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(convert_to_decimal_long)
|
|
{
|
|
int r1; /* Values of R fields */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
U64 n; /* Absolute value to convert */
|
|
BYTE result[16]; /* 31-digit signed result */
|
|
int i; /* Array subscript */
|
|
int d; /* Decimal digit or sign */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Special case when R1 is maximum negative value */
|
|
if (regs->GR_G(r1) == 0x8000000000000000ULL)
|
|
{
|
|
memcpy (result,
|
|
"\x00\x00\x00\x00\x00\x00\x92\x23"
|
|
"\x37\x20\x36\x85\x47\x75\x80\x8D",
|
|
sizeof(result));
|
|
}
|
|
else
|
|
{
|
|
/* Load absolute value and generate sign */
|
|
if (regs->GR_G(r1) < 0x8000000000000000ULL)
|
|
{
|
|
/* Value is positive */
|
|
n = regs->GR_G(r1);
|
|
d = 0x0C;
|
|
}
|
|
else
|
|
{
|
|
/* Value is negative */
|
|
n = -((S64)(regs->GR_G(r1)));
|
|
d = 0x0D;
|
|
}
|
|
|
|
/* Store sign and decimal digits from right to left */
|
|
memset (result, 0, 16);
|
|
for (i = 16 - 1; d != 0 || n != 0; i--)
|
|
{
|
|
result[i] = d;
|
|
d = n % 10;
|
|
n /= 10;
|
|
result[i] |= (d << 4);
|
|
d = n % 10;
|
|
n /= 10;
|
|
}
|
|
}
|
|
|
|
/* Store 16-byte packed decimal result at operand address */
|
|
ARCH_DEP(vstorec) ( result, 16-1, effective_addr2, b2, regs );
|
|
|
|
} /* end DEF_INST(convert_to_decimal_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E396 ML - Multiply Logical [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(multiply_logical)
|
|
{
|
|
int r1; /* Values of R fields */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective Address */
|
|
U32 m;
|
|
U64 p;
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
ODD_CHECK(r1, regs);
|
|
|
|
/* Load second operand from operand address */
|
|
m = ARCH_DEP(vfetch4) (effective_addr2, b2, regs);
|
|
|
|
/* Multiply unsigned values */
|
|
p = (U64)regs->GR_L(r1 + 1) * m;
|
|
|
|
/* Store the result */
|
|
regs->GR_L(r1) = (p >> 32);
|
|
regs->GR_L(r1 + 1) = (p & 0xFFFFFFFF);
|
|
|
|
} /* end DEF_INST(multiply_logical) */
|
|
#endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E386 MLG - Multiply Logical Long [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(multiply_logical_long)
|
|
{
|
|
int r1; /* Values of R fields */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective Address */
|
|
U64 m, ph, pl;
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
ODD_CHECK(r1, regs);
|
|
|
|
/* Load second operand from operand address */
|
|
m = ARCH_DEP(vfetch8) (effective_addr2, b2, regs);
|
|
|
|
/* Multiply unsigned values */
|
|
mult_logical_long(&ph, &pl, regs->GR_G(r1 + 1), m);
|
|
|
|
/* Store the result */
|
|
regs->GR_G(r1) = ph;
|
|
regs->GR_G(r1 + 1) = pl;
|
|
|
|
} /* end DEF_INST(multiply_logical_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B996 MLR - Multiply Logical Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(multiply_logical_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
U64 p;
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
ODD_CHECK(r1, regs);
|
|
|
|
/* Multiply unsigned values */
|
|
p = (U64)regs->GR_L(r1 + 1) * (U64)regs->GR_L(r2);
|
|
|
|
/* Store the result */
|
|
regs->GR_L(r1) = (p >> 32);
|
|
regs->GR_L(r1 + 1) = (p & 0xFFFFFFFF);
|
|
|
|
} /* end DEF_INST(multiply_logical_register) */
|
|
#endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B986 MLGR - Multiply Logical Long Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(multiply_logical_long_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
U64 ph, pl;
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
ODD_CHECK(r1, regs);
|
|
|
|
/* Multiply unsigned values */
|
|
mult_logical_long(&ph, &pl, regs->GR_G(r1 + 1), regs->GR_G(r2));
|
|
|
|
/* Store the result */
|
|
regs->GR_G(r1) = ph;
|
|
regs->GR_G(r1 + 1) = pl;
|
|
|
|
} /* end DEF_INST(multiply_logical_long_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E397 DL - Divide Logical [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(divide_logical)
|
|
{
|
|
int r1; /* Values of R fields */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective Address */
|
|
U32 d;
|
|
U64 n;
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
ODD_CHECK(r1, regs);
|
|
|
|
n = ((U64)regs->GR_L(r1) << 32) | (U32)regs->GR_L(r1 + 1);
|
|
|
|
/* Load second operand from operand address */
|
|
d = ARCH_DEP(vfetch4) (effective_addr2, b2, regs);
|
|
|
|
if (d == 0
|
|
|| (n / d) > 0xFFFFFFFF)
|
|
ARCH_DEP(program_interrupt) (regs, PGM_FIXED_POINT_DIVIDE_EXCEPTION);
|
|
|
|
/* Divide unsigned registers */
|
|
regs->GR_L(r1) = n % d;
|
|
regs->GR_L(r1 + 1) = n / d;
|
|
|
|
} /* end DEF_INST(divide_logical) */
|
|
#endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E387 DLG - Divide Logical Long [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(divide_logical_long)
|
|
{
|
|
int r1; /* Values of R fields */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective Address */
|
|
U64 d, r, q;
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
ODD_CHECK(r1, regs);
|
|
|
|
/* Load second operand from operand address */
|
|
d = ARCH_DEP(vfetch8) (effective_addr2, b2, regs);
|
|
|
|
if (regs->GR_G(r1) == 0) /* check for the simple case */
|
|
{
|
|
if (d == 0)
|
|
ARCH_DEP(program_interrupt) (regs, PGM_FIXED_POINT_DIVIDE_EXCEPTION);
|
|
|
|
/* Divide signed registers */
|
|
regs->GR_G(r1) = regs->GR_G(r1 + 1) % d;
|
|
regs->GR_G(r1 + 1) = regs->GR_G(r1 + 1) / d;
|
|
}
|
|
else
|
|
{
|
|
if (div_logical_long(&r, &q, regs->GR_G(r1), regs->GR_G(r1 + 1), d) )
|
|
ARCH_DEP(program_interrupt) (regs, PGM_FIXED_POINT_DIVIDE_EXCEPTION);
|
|
else
|
|
{
|
|
regs->GR_G(r1) = r;
|
|
regs->GR_G(r1 + 1) = q;
|
|
}
|
|
|
|
}
|
|
} /* end DEF_INST(divide_logical_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B997 DLR - Divide Logical Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(divide_logical_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
U64 n;
|
|
U32 d;
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
ODD_CHECK(r1, regs);
|
|
|
|
n = ((U64)regs->GR_L(r1) << 32) | regs->GR_L(r1 + 1);
|
|
|
|
d = regs->GR_L(r2);
|
|
|
|
if(d == 0
|
|
|| (n / d) > 0xFFFFFFFF)
|
|
ARCH_DEP(program_interrupt) (regs, PGM_FIXED_POINT_DIVIDE_EXCEPTION);
|
|
|
|
/* Divide signed registers */
|
|
regs->GR_L(r1) = n % d;
|
|
regs->GR_L(r1 + 1) = n / d;
|
|
|
|
} /* end DEF_INST(divide_logical_register) */
|
|
#endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B987 DLGR - Divide Logical Long Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(divide_logical_long_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
U64 r, q, d;
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
ODD_CHECK(r1, regs);
|
|
|
|
d = regs->GR_G(r2);
|
|
|
|
if (regs->GR_G(r1) == 0) /* check for the simple case */
|
|
{
|
|
if(d == 0)
|
|
ARCH_DEP(program_interrupt) (regs, PGM_FIXED_POINT_DIVIDE_EXCEPTION);
|
|
|
|
/* Divide signed registers */
|
|
regs->GR_G(r1) = regs->GR_G(r1 + 1) % d;
|
|
regs->GR_G(r1 + 1) = regs->GR_G(r1 + 1) / d;
|
|
}
|
|
else
|
|
{
|
|
if (div_logical_long(&r, &q, regs->GR_G(r1), regs->GR_G(r1 + 1), d) )
|
|
ARCH_DEP(program_interrupt) (regs, PGM_FIXED_POINT_DIVIDE_EXCEPTION);
|
|
else
|
|
{
|
|
regs->GR_G(r1) = r;
|
|
regs->GR_G(r1 + 1) = q;
|
|
}
|
|
}
|
|
} /* end DEF_INST(divide_logical_long_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B988 ALCGR - Add Logical with Carry Long Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(add_logical_carry_long_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
int carry = 0;
|
|
U64 n;
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
n = regs->GR_G(r2);
|
|
|
|
/* Add the carry to operand */
|
|
if(regs->psw.cc & 2)
|
|
carry = add_logical_long(&(regs->GR_G(r1)),
|
|
regs->GR_G(r1),
|
|
1) & 2;
|
|
|
|
/* Add unsigned operands and set condition code */
|
|
regs->psw.cc = add_logical_long(&(regs->GR_G(r1)),
|
|
regs->GR_G(r1),
|
|
n) | carry;
|
|
} /* end DEF_INST(add_logical_carry_long_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B989 SLBGR - Subtract Logical with Borrow Long Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(subtract_logical_borrow_long_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
int borrow = 0;
|
|
U64 n;
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
n = regs->GR_G(r2);
|
|
|
|
/* Subtract the borrow from operand */
|
|
if(!(regs->psw.cc & 2))
|
|
borrow = sub_logical_long(&(regs->GR_G(r1)),
|
|
regs->GR_G(r1),
|
|
1) & 2;
|
|
|
|
/* Subtract unsigned operands and set condition code */
|
|
regs->psw.cc = sub_logical_long(&(regs->GR_G(r1)),
|
|
regs->GR_G(r1),
|
|
n) & ~borrow;
|
|
|
|
} /* end DEF_INST(subtract_logical_borrow_long_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E388 ALCG - Add Logical with Carry Long [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(add_logical_carry_long)
|
|
{
|
|
int r1; /* Values of R fields */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
U64 n; /* 64-bit operand values */
|
|
int carry = 0;
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Load second operand from operand address */
|
|
n = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs );
|
|
|
|
/* Add the carry to operand */
|
|
if(regs->psw.cc & 2)
|
|
carry = add_logical_long(&(regs->GR_G(r1)),
|
|
regs->GR_G(r1),
|
|
1) & 2;
|
|
|
|
/* Add unsigned operands and set condition code */
|
|
regs->psw.cc = add_logical_long(&(regs->GR_G(r1)),
|
|
regs->GR_G(r1),
|
|
n) | carry;
|
|
} /* end DEF_INST(add_logical_carry_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E389 SLBG - Subtract Logical with Borrow Long [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(subtract_logical_borrow_long)
|
|
{
|
|
int r1; /* Values of R fields */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
U64 n; /* 64-bit operand values */
|
|
int borrow = 0;
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Load second operand from operand address */
|
|
n = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs );
|
|
|
|
/* Subtract the borrow from operand */
|
|
if(!(regs->psw.cc & 2))
|
|
borrow = sub_logical_long(&(regs->GR_G(r1)),
|
|
regs->GR_G(r1),
|
|
1) & 2;
|
|
|
|
/* Subtract unsigned operands and set condition code */
|
|
regs->psw.cc = sub_logical_long(&(regs->GR_G(r1)),
|
|
regs->GR_G(r1),
|
|
n) & ~borrow;
|
|
|
|
} /* end DEF_INST(subtract_logical_borrow_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B998 ALCR - Add Logical with Carry Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(add_logical_carry_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
int carry = 0;
|
|
U32 n;
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
n = regs->GR_L(r2);
|
|
|
|
/* Add the carry to operand */
|
|
if(regs->psw.cc & 2)
|
|
carry = add_logical(&(regs->GR_L(r1)),
|
|
regs->GR_L(r1),
|
|
1) & 2;
|
|
|
|
/* Add unsigned operands and set condition code */
|
|
regs->psw.cc = add_logical(&(regs->GR_L(r1)),
|
|
regs->GR_L(r1),
|
|
n) | carry;
|
|
} /* end DEF_INST(add_logical_carry_register) */
|
|
#endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B999 SLBR - Subtract Logical with Borrow Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(subtract_logical_borrow_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
int borrow = 0;
|
|
U32 n;
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
n = regs->GR_L(r2);
|
|
|
|
/* Subtract the borrow from operand */
|
|
if(!(regs->psw.cc & 2))
|
|
borrow = sub_logical(&(regs->GR_L(r1)),
|
|
regs->GR_L(r1),
|
|
1) & 2;
|
|
|
|
/* Subtract unsigned operands and set condition code */
|
|
regs->psw.cc = sub_logical(&(regs->GR_L(r1)),
|
|
regs->GR_L(r1),
|
|
n) & ~borrow;
|
|
|
|
} /* end DEF_INST(subtract_logical_borrow_register) */
|
|
#endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E398 ALC - Add Logical with Carry [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(add_logical_carry)
|
|
{
|
|
int r1; /* Values of R fields */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
U32 n; /* 32-bit operand values */
|
|
int carry = 0;
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Load second operand from operand address */
|
|
n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs );
|
|
|
|
/* Add the carry to operand */
|
|
if(regs->psw.cc & 2)
|
|
carry = add_logical(&(regs->GR_L(r1)),
|
|
regs->GR_L(r1),
|
|
1) & 2;
|
|
|
|
/* Add unsigned operands and set condition code */
|
|
regs->psw.cc = add_logical(&(regs->GR_L(r1)),
|
|
regs->GR_L(r1),
|
|
n) | carry;
|
|
} /* end DEF_INST(add_logical_carry) */
|
|
#endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E399 SLB - Subtract Logical with Borrow [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(subtract_logical_borrow)
|
|
{
|
|
int r1; /* Values of R fields */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
U32 n; /* 32-bit operand values */
|
|
int borrow = 0;
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Load second operand from operand address */
|
|
n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs );
|
|
|
|
/* Subtract the borrow from operand */
|
|
if(!(regs->psw.cc & 2))
|
|
borrow = sub_logical(&(regs->GR_L(r1)),
|
|
regs->GR_L(r1),
|
|
1) & 2;
|
|
|
|
/* Subtract unsigned operands and set condition code */
|
|
regs->psw.cc = sub_logical(&(regs->GR_L(r1)),
|
|
regs->GR_L(r1),
|
|
n) & ~borrow;
|
|
|
|
} /* end DEF_INST(subtract_logical_borrow) */
|
|
#endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E30D DSG - Divide Single Long [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(divide_single_long)
|
|
{
|
|
int r1; /* Values of R fields */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
U64 n; /* 64-bit operand values */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
ODD_CHECK(r1, regs);
|
|
|
|
/* Load second operand from operand address */
|
|
n = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs );
|
|
|
|
if(n == 0
|
|
|| ((S64)n == -1LL &&
|
|
regs->GR_G(r1) == 0x8000000000000000ULL))
|
|
ARCH_DEP(program_interrupt) (regs, PGM_FIXED_POINT_DIVIDE_EXCEPTION);
|
|
|
|
regs->GR_G(r1) = (S64)regs->GR_G(r1 + 1) % (S64)n;
|
|
regs->GR_G(r1 + 1) = (S64)regs->GR_G(r1 + 1) / (S64)n;
|
|
|
|
} /* end DEF_INST(divide_single_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E31D DSGF - Divide Single Long Fullword [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(divide_single_long_fullword)
|
|
{
|
|
int r1; /* Values of R fields */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
U32 n; /* 64-bit operand values */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
ODD_CHECK(r1, regs);
|
|
|
|
/* Load second operand from operand address */
|
|
n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs );
|
|
|
|
if(n == 0
|
|
|| ((S32)n == -1 &&
|
|
regs->GR_G(r1) == 0x8000000000000000ULL))
|
|
ARCH_DEP(program_interrupt) (regs, PGM_FIXED_POINT_DIVIDE_EXCEPTION);
|
|
|
|
regs->GR_G(r1) = (S64)regs->GR_G(r1 + 1) % (S32)n;
|
|
regs->GR_G(r1 + 1) = (S64)regs->GR_G(r1 + 1) / (S32)n;
|
|
|
|
} /* end DEF_INST(divide_single_long_fullword) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B90D DSGR - Divide Single Long Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(divide_single_long_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
U64 n;
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
ODD_CHECK(r1, regs);
|
|
|
|
if(regs->GR_G(r2) == 0
|
|
|| ((S64)regs->GR_G(r2) == -1LL &&
|
|
regs->GR_G(r1) == 0x8000000000000000ULL))
|
|
ARCH_DEP(program_interrupt) (regs, PGM_FIXED_POINT_DIVIDE_EXCEPTION);
|
|
|
|
n = regs->GR_G(r2);
|
|
|
|
/* Divide signed registers */
|
|
regs->GR_G(r1) = (S64)regs->GR_G(r1 + 1) % (S64)n;
|
|
regs->GR_G(r1 + 1) = (S64)regs->GR_G(r1 + 1) / (S64)n;
|
|
|
|
} /* end DEF_INST(divide_single_long_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B91D DSGFR - Divide Single Long Fullword Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(divide_single_long_fullword_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
U32 n;
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
ODD_CHECK(r1, regs);
|
|
|
|
if(regs->GR_L(r2) == 0
|
|
|| ((S32)regs->GR_L(r2) == -1 &&
|
|
regs->GR_G(r1) == 0x8000000000000000ULL))
|
|
ARCH_DEP(program_interrupt) (regs, PGM_FIXED_POINT_DIVIDE_EXCEPTION);
|
|
|
|
n = regs->GR_L(r2);
|
|
|
|
/* Divide signed registers */
|
|
regs->GR_G(r1) = (S64)regs->GR_G(r1 + 1) % (S32)n;
|
|
regs->GR_G(r1 + 1) = (S64)regs->GR_G(r1 + 1) / (S32)n;
|
|
|
|
} /* end DEF_INST(divide_single_long_fullword_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E390 LLGC - Load Logical Character [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_logical_character)
|
|
{
|
|
int r1; /* Value of R field */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
regs->GR_G(r1) = ARCH_DEP(vfetchb) ( effective_addr2, b2, regs );
|
|
|
|
} /* end DEF_INST(load_logical_character) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E391 LLGH - Load Logical Halfword [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_logical_halfword)
|
|
{
|
|
int r1; /* Value of R field */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
regs->GR_G(r1) = ARCH_DEP(vfetch2) ( effective_addr2, b2, regs );
|
|
|
|
} /* end DEF_INST(load_logical_halfword) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E38E STPQ - Store Pair to Quadword [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(store_pair_to_quadword)
|
|
{
|
|
int r1; /* Value of R field */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
QWORD qwork; /* Quadword work area */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
ODD_CHECK(r1, regs);
|
|
|
|
QW_CHECK(effective_addr2, regs);
|
|
|
|
/* Store regs in workarea */
|
|
STORE_DW(qwork, regs->GR_G(r1));
|
|
STORE_DW(qwork+8, regs->GR_G(r1+1));
|
|
|
|
/* Store R1 and R1+1 registers to second operand
|
|
Provide storage consistancy by means of obtaining
|
|
the main storage access lock */
|
|
OBTAIN_MAINLOCK(regs);
|
|
ARCH_DEP(vstorec) ( qwork, 16-1, effective_addr2, b2, regs );
|
|
RELEASE_MAINLOCK(regs);
|
|
|
|
} /* end DEF_INST(store_pair_to_quadword) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E38F LPQ - Load Pair from Quadword [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_pair_from_quadword)
|
|
{
|
|
int r1; /* Value of R field */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
QWORD qwork; /* Quadword work area */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
ODD_CHECK(r1, regs);
|
|
|
|
QW_CHECK(effective_addr2, regs);
|
|
|
|
/* Load R1 and R1+1 registers contents from second operand
|
|
Provide storage consistancy by means of obtaining
|
|
the main storage access lock */
|
|
OBTAIN_MAINLOCK(regs);
|
|
ARCH_DEP(vfetchc) ( qwork, 16-1, effective_addr2, b2, regs );
|
|
RELEASE_MAINLOCK(regs);
|
|
|
|
/* Load regs from workarea */
|
|
FETCH_DW(regs->GR_G(r1), qwork);
|
|
FETCH_DW(regs->GR_G(r1+1), qwork+8);
|
|
|
|
} /* end DEF_INST(load_pair_from_quadword) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B90E EREGG - Extract Stacked Registers Long [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(extract_stacked_registers_long)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
LSED lsed; /* Linkage stack entry desc. */
|
|
VADR lsea; /* Linkage stack entry addr */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
SIE_MODE_XC_OPEX(regs);
|
|
|
|
/* Find the virtual address of the entry descriptor
|
|
of the current state entry in the linkage stack */
|
|
lsea = ARCH_DEP(locate_stack_entry) (0, &lsed, regs);
|
|
|
|
/* Load registers from the stack entry */
|
|
ARCH_DEP(unstack_registers) (1, lsea, r1, r2, regs);
|
|
|
|
INVALIDATE_AEA_ALL(regs);
|
|
|
|
} /* end DEF_INST(extract_stacked_registers_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B98D EPSW - Extract PSW [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(extract_psw)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
QWORD currpsw; /* Work area for PSW */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
#if defined(_FEATURE_ZSIE)
|
|
if(regs->sie_state && (regs->siebk->ic[1] & SIE_IC1_LPSW))
|
|
longjmp(regs->progjmp, SIE_INTERCEPT_INST);
|
|
#endif /*defined(_FEATURE_ZSIE)*/
|
|
|
|
/* Store the current PSW in work area */
|
|
ARCH_DEP(store_psw) (regs, currpsw);
|
|
|
|
/* Load PSW bits 0-31 into bits 32-63 of the R1 register */
|
|
FETCH_FW(regs->GR_L(r1), currpsw);
|
|
|
|
/* If R2 specifies a register other than register zero,
|
|
load PSW bits 32-63 into bits 32-63 of the R2 register */
|
|
if(r2 != 0)
|
|
FETCH_FW(regs->GR_L(r2), currpsw+4);
|
|
|
|
} /* end DEF_INST(extract_psw) */
|
|
#endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B99D ESEA - Extract and Set Extended Authority [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(extract_and_set_extended_authority)
|
|
{
|
|
int r1, unused; /* Value of R field */
|
|
|
|
RRE(inst, execflag, regs, r1, unused);
|
|
|
|
PRIV_CHECK(regs);
|
|
|
|
#if 0
|
|
#if defined(_FEATURE_ZSIE)
|
|
if(regs->sie_state && (regs->siebk->lctl_ctl[1] & SIE_LCTL1_CR8))
|
|
longjmp(regs->progjmp, SIE_INTERCEPT_INST);
|
|
#endif /*defined(_FEATURE_ZSIE)*/
|
|
#endif
|
|
|
|
regs->GR_LHH(r1) = regs->CR_LHH(8);
|
|
regs->CR_LHH(8) = regs->GR_LHL(r1);
|
|
|
|
INVALIDATE_AIA(regs);
|
|
INVALIDATE_AEA_ALL(regs);
|
|
|
|
} /* end DEF_INST(extract_and_set_extended_authority) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* C0x0 LARL - Load Address Relative Long [RIL] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_address_relative_long)
|
|
{
|
|
int r1; /* Register number */
|
|
int opcd; /* Opcode */
|
|
U32 i2; /* 32-bit operand values */
|
|
|
|
RIL(inst, execflag, regs, r1, opcd, i2);
|
|
|
|
GR_A(r1, regs) = ((!execflag ? (regs->psw.IA - 6) : regs->ET)
|
|
+ 2LL*(S32)i2) & ADDRESS_MAXWRAP(regs);
|
|
|
|
} /* end DEF_INST(load_address_relative_long) */
|
|
#endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* A5x0 IIHH - Insert Immediate High High [RI] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(insert_immediate_high_high)
|
|
{
|
|
int r1; /* Register number */
|
|
int opcd; /* Opcode */
|
|
U16 i2; /* 16-bit operand values */
|
|
|
|
RI(inst, execflag, regs, r1, opcd, i2);
|
|
|
|
regs->GR_HHH(r1) = i2;
|
|
|
|
} /* end DEF_INST(insert_immediate_high_high) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* A5x1 IIHL - Insert Immediate High Low [RI] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(insert_immediate_high_low)
|
|
{
|
|
int r1; /* Register number */
|
|
int opcd; /* Opcode */
|
|
U16 i2; /* 16-bit operand values */
|
|
|
|
RI(inst, execflag, regs, r1, opcd, i2);
|
|
|
|
regs->GR_HHL(r1) = i2;
|
|
|
|
} /* end DEF_INST(insert_immediate_high_low) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* A5x2 IILH - Insert Immediate Low High [RI] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(insert_immediate_low_high)
|
|
{
|
|
int r1; /* Register number */
|
|
int opcd; /* Opcode */
|
|
U16 i2; /* 16-bit operand values */
|
|
|
|
RI(inst, execflag, regs, r1, opcd, i2);
|
|
|
|
regs->GR_LHH(r1) = i2;
|
|
|
|
} /* end DEF_INST(insert_immediate_low_high) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* A5x3 IILL - Insert Immediate Low Low [RI] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(insert_immediate_low_low)
|
|
{
|
|
int r1; /* Register number */
|
|
int opcd; /* Opcode */
|
|
U16 i2; /* 16-bit operand values */
|
|
|
|
RI(inst, execflag, regs, r1, opcd, i2);
|
|
|
|
regs->GR_LHL(r1) = i2;
|
|
|
|
} /* end DEF_INST(insert_immediate_low_low) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* A5x4 NIHH - And Immediate High High [RI] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(and_immediate_high_high)
|
|
{
|
|
int r1; /* Register number */
|
|
int opcd; /* Opcode */
|
|
U16 i2; /* 16-bit operand values */
|
|
|
|
RI(inst, execflag, regs, r1, opcd, i2);
|
|
|
|
regs->GR_HHH(r1) &= i2;
|
|
|
|
/* Set condition code according to result */
|
|
regs->psw.cc = regs->GR_HHH(r1) ? 1 : 0;
|
|
|
|
} /* end DEF_INST(and_immediate_high_high) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* A5x5 NIHL - And Immediate High Low [RI] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(and_immediate_high_low)
|
|
{
|
|
int r1; /* Register number */
|
|
int opcd; /* Opcode */
|
|
U16 i2; /* 16-bit operand values */
|
|
|
|
RI(inst, execflag, regs, r1, opcd, i2);
|
|
|
|
regs->GR_HHL(r1) &= i2;
|
|
|
|
/* Set condition code according to result */
|
|
regs->psw.cc = regs->GR_HHL(r1) ? 1 : 0;
|
|
|
|
} /* end DEF_INST(and_immediate_high_low) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* A5x6 NILH - And Immediate Low High [RI] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(and_immediate_low_high)
|
|
{
|
|
int r1; /* Register number */
|
|
int opcd; /* Opcode */
|
|
U16 i2; /* 16-bit operand values */
|
|
|
|
RI(inst, execflag, regs, r1, opcd, i2);
|
|
|
|
regs->GR_LHH(r1) &= i2;
|
|
|
|
/* Set condition code according to result */
|
|
regs->psw.cc = regs->GR_LHH(r1) ? 1 : 0;
|
|
|
|
} /* end DEF_INST(and_immediate_low_high) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* A5x7 NILL - And Immediate Low Low [RI] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(and_immediate_low_low)
|
|
{
|
|
int r1; /* Register number */
|
|
int opcd; /* Opcode */
|
|
U16 i2; /* 16-bit operand values */
|
|
|
|
RI(inst, execflag, regs, r1, opcd, i2);
|
|
|
|
regs->GR_LHL(r1) &= i2;
|
|
|
|
/* Set condition code according to result */
|
|
regs->psw.cc = regs->GR_LHL(r1) ? 1 : 0;
|
|
|
|
} /* end DEF_INST(and_immediate_low_low) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* A5x8 OIHH - Or Immediate High High [RI] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(or_immediate_high_high)
|
|
{
|
|
int r1; /* Register number */
|
|
int opcd; /* Opcode */
|
|
U16 i2; /* 16-bit operand values */
|
|
|
|
RI(inst, execflag, regs, r1, opcd, i2);
|
|
|
|
regs->GR_HHH(r1) |= i2;
|
|
|
|
/* Set condition code according to result */
|
|
regs->psw.cc = regs->GR_HHH(r1) ? 1 : 0;
|
|
|
|
} /* end DEF_INST(or_immediate_high_high) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* A5x9 OIHL - Or Immediate High Low [RI] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(or_immediate_high_low)
|
|
{
|
|
int r1; /* Register number */
|
|
int opcd; /* Opcode */
|
|
U16 i2; /* 16-bit operand values */
|
|
|
|
RI(inst, execflag, regs, r1, opcd, i2);
|
|
|
|
regs->GR_HHL(r1) |= i2;
|
|
|
|
/* Set condition code according to result */
|
|
regs->psw.cc = regs->GR_HHL(r1) ? 1 : 0;
|
|
|
|
} /* end DEF_INST(or_immediate_high_low) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* A5xA OILH - Or Immediate Low High [RI] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(or_immediate_low_high)
|
|
{
|
|
int r1; /* Register number */
|
|
int opcd; /* Opcode */
|
|
U16 i2; /* 16-bit operand values */
|
|
|
|
RI(inst, execflag, regs, r1, opcd, i2);
|
|
|
|
regs->GR_LHH(r1) |= i2;
|
|
|
|
/* Set condition code according to result */
|
|
regs->psw.cc = regs->GR_LHH(r1) ? 1 : 0;
|
|
|
|
} /* end DEF_INST(or_immediate_low_high) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* A5xB OILL - Or Immediate Low Low [RI] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(or_immediate_low_low)
|
|
{
|
|
int r1; /* Register number */
|
|
int opcd; /* Opcode */
|
|
U16 i2; /* 16-bit operand values */
|
|
|
|
RI(inst, execflag, regs, r1, opcd, i2);
|
|
|
|
regs->GR_LHL(r1) |= i2;
|
|
|
|
/* Set condition code according to result */
|
|
regs->psw.cc = regs->GR_LHL(r1) ? 1 : 0;
|
|
|
|
} /* end DEF_INST(or_immediate_low_low) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* A5xC LLIHH - Load Logical Immediate High High [RI] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_logical_immediate_high_high)
|
|
{
|
|
int r1; /* Register number */
|
|
int opcd; /* Opcode */
|
|
U16 i2; /* 16-bit operand values */
|
|
|
|
RI(inst, execflag, regs, r1, opcd, i2);
|
|
|
|
regs->GR_G(r1) = (U64)i2 << 48;
|
|
|
|
} /* end DEF_INST(load_logical_immediate_high_high) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* A5xD LLIHL - Load Logical Immediate High Low [RI] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_logical_immediate_high_low)
|
|
{
|
|
int r1; /* Register number */
|
|
int opcd; /* Opcode */
|
|
U16 i2; /* 16-bit operand values */
|
|
|
|
RI(inst, execflag, regs, r1, opcd, i2);
|
|
|
|
regs->GR_G(r1) = (U64)i2 << 32;
|
|
|
|
} /* end DEF_INST(load_logical_immediate_high_low) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* A5xE LLILH - Load Logical Immediate Low High [RI] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_logical_immediate_low_high)
|
|
{
|
|
int r1; /* Register number */
|
|
int opcd; /* Opcode */
|
|
U16 i2; /* 16-bit operand values */
|
|
|
|
RI(inst, execflag, regs, r1, opcd, i2);
|
|
|
|
regs->GR_G(r1) = (U64)i2 << 16;
|
|
|
|
} /* end DEF_INST(load_logical_immediate_low_high) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* A5xF LLILL - Load Logical Immediate Low Low [RI] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_logical_immediate_low_low)
|
|
{
|
|
int r1; /* Register number */
|
|
int opcd; /* Opcode */
|
|
U16 i2; /* 16-bit operand values */
|
|
|
|
RI(inst, execflag, regs, r1, opcd, i2);
|
|
|
|
regs->GR_G(r1) = (U64)i2;
|
|
|
|
} /* end DEF_INST(load_logical_immediate_low_low) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* C0x4 BRCL - Branch Relative on Condition Long [RIL] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(branch_relative_on_condition_long)
|
|
{
|
|
int r1; /* Register number */
|
|
int opcd; /* Opcode */
|
|
U32 i2; /* 32-bit operand values */
|
|
|
|
RIL(inst, execflag, regs, r1, opcd, i2);
|
|
|
|
/* Branch if R1 mask bit is set */
|
|
if ((0x08 >> regs->psw.cc) & r1)
|
|
{
|
|
/* Calculate the relative branch address */
|
|
regs->psw.IA = ((!execflag ? (regs->psw.IA - 6) : regs->ET)
|
|
+ 2LL*(S32)i2) & ADDRESS_MAXWRAP(regs);
|
|
#if defined(FEATURE_PER)
|
|
if( EN_IC_PER_SB(regs)
|
|
#if defined(FEATURE_PER2)
|
|
&& ( !(regs->CR(9) & CR9_BAC)
|
|
|| PER_RANGE_CHECK(regs->psw.IA,regs->CR(10),regs->CR(11)) )
|
|
#endif /*defined(FEATURE_PER2)*/
|
|
)
|
|
ON_IC_PER_SB(regs);
|
|
#endif /*defined(FEATURE_PER)*/
|
|
}
|
|
} /* end DEF_INST(branch_relative_on_condition_long) */
|
|
#endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* C0x5 BRASL - Branch Relative And Save Long [RIL] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(branch_relative_and_save_long)
|
|
{
|
|
int r1; /* Register number */
|
|
int opcd; /* Opcode */
|
|
U32 i2; /* 32-bit operand values */
|
|
|
|
RIL(inst, execflag, regs, r1, opcd, i2);
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
if(regs->psw.amode64)
|
|
regs->GR_G(r1) = regs->psw.IA;
|
|
else
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
if ( regs->psw.amode )
|
|
regs->GR_L(r1) = 0x80000000 | regs->psw.IA;
|
|
else
|
|
regs->GR_L(r1) = regs->psw.IA_LA24;
|
|
|
|
/* Set instruction address to the relative branch address */
|
|
regs->psw.IA = ((!execflag ? (regs->psw.IA - 6) : regs->ET)
|
|
+ 2LL*(S32)i2) & ADDRESS_MAXWRAP(regs);
|
|
|
|
#if defined(FEATURE_PER)
|
|
if( EN_IC_PER_SB(regs)
|
|
#if defined(FEATURE_PER2)
|
|
&& ( !(regs->CR(9) & CR9_BAC)
|
|
|| PER_RANGE_CHECK(regs->psw.IA,regs->CR(10),regs->CR(11)) )
|
|
#endif /*defined(FEATURE_PER2)*/
|
|
)
|
|
ON_IC_PER_SB(regs);
|
|
#endif /*defined(FEATURE_PER)*/
|
|
} /* end DEF_INST(branch_relative_and_save_long) */
|
|
#endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* EB20 CLMH - Compare Logical Characters under Mask High [RSE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(compare_logical_characters_under_mask_high)
|
|
{
|
|
int r1, r3; /* Register numbers */
|
|
int b2; /* effective address base */
|
|
VADR effective_addr2; /* effective address */
|
|
U32 n; /* 32-bit operand values */
|
|
int cc = 0; /* Condition code */
|
|
BYTE sbyte,
|
|
dbyte; /* Byte work areas */
|
|
int i; /* Integer work areas */
|
|
|
|
RSE(inst, execflag, regs, r1, r3, b2, effective_addr2);
|
|
|
|
/* Load value from register */
|
|
n = regs->GR_H(r1);
|
|
|
|
/* if mask is zero, access rupts recognized for 1 byte */
|
|
if (r3 == 0)
|
|
sbyte = ARCH_DEP(vfetchb) ( effective_addr2, b2, regs );
|
|
|
|
/* Compare characters in register with operand characters */
|
|
for ( i = 0; i < 4; i++ )
|
|
{
|
|
/* Test mask bit corresponding to this character */
|
|
if ( r3 & 0x08 )
|
|
{
|
|
/* Fetch character from register and operand */
|
|
dbyte = n >> 24;
|
|
sbyte = ARCH_DEP(vfetchb) ( effective_addr2++, b2, regs );
|
|
|
|
/* Compare bytes, set condition code if unequal */
|
|
if ( dbyte != sbyte )
|
|
{
|
|
cc = (dbyte < sbyte) ? 1 : 2;
|
|
break;
|
|
} /* end if */
|
|
}
|
|
|
|
/* Shift mask and register for next byte */
|
|
r3 <<= 1;
|
|
n <<= 8;
|
|
|
|
} /* end for(i) */
|
|
|
|
/* Update the condition code */
|
|
regs->psw.cc = cc;
|
|
|
|
} /* end DEF_INST(compare_logical_characters_under_mask_high) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* EB2C STCMH - Store Characters under Mask High [RSE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(store_characters_under_mask_high)
|
|
{
|
|
int r1, r3; /* Register numbers */
|
|
int b2; /* effective address base */
|
|
VADR effective_addr2; /* effective address */
|
|
U32 n; /* 32-bit operand values */
|
|
int i, j; /* Integer work areas */
|
|
BYTE cwork[4]; /* Character work areas */
|
|
|
|
RSE(inst, execflag, regs, r1, r3, b2, effective_addr2);
|
|
|
|
/* Load value from register */
|
|
n = regs->GR_H(r1);
|
|
|
|
/* Copy characters from register to work area */
|
|
for ( i = 0, j = 0; i < 4; i++ )
|
|
{
|
|
/* Test mask bit corresponding to this character */
|
|
if ( r3 & 0x08 )
|
|
{
|
|
/* Copy character from register to work area */
|
|
cwork[j++] = n >> 24;
|
|
}
|
|
|
|
/* Shift mask and register for next byte */
|
|
r3 <<= 1;
|
|
n <<= 8;
|
|
|
|
} /* end for(i) */
|
|
|
|
if (j == 0)
|
|
{
|
|
#if defined(MODEL_DEPENDENT_STCM)
|
|
/* If the mask is all zero, we nevertheless access one byte
|
|
from the storage operand, because POP states that an
|
|
access exception may be recognized on the first byte */
|
|
ARCH_DEP(validate_operand) (effective_addr2, b2, 0, ACCTYPE_WRITE, regs);
|
|
#endif /*defined(MODEL_DEPENDENT_STCM)*/
|
|
return;
|
|
}
|
|
|
|
/* Store result at operand location */
|
|
ARCH_DEP(vstorec) ( cwork, j-1, effective_addr2, b2, regs );
|
|
|
|
} /* end DEF_INST(store_characters_under_mask_high) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* EB80 ICMH - Insert Characters under Mask High [RSE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(insert_characters_under_mask_high)
|
|
{
|
|
int r1, r3; /* Register numbers */
|
|
int b2; /* effective address base */
|
|
VADR effective_addr2; /* effective address */
|
|
int cc = 0; /* Condition code */
|
|
BYTE tbyte; /* Byte work areas */
|
|
int h, i; /* Integer work areas */
|
|
U64 dreg; /* Double register work area */
|
|
|
|
RSE(inst, execflag, regs, r1, r3, b2, effective_addr2);
|
|
|
|
/* If the mask is all zero, we must nevertheless load one
|
|
byte from the storage operand, because POP requires us
|
|
to recognize an access exception on the first byte */
|
|
if ( r3 == 0 )
|
|
{
|
|
tbyte = ARCH_DEP(vfetchb) ( effective_addr2, b2, regs );
|
|
regs->psw.cc = 0;
|
|
return;
|
|
}
|
|
|
|
/* Load existing register value into 64-bit work area */
|
|
dreg = regs->GR_H(r1);
|
|
|
|
/* Insert characters into register from operand address */
|
|
for ( i = 0, h = 0; i < 4; i++ )
|
|
{
|
|
/* Test mask bit corresponding to this character */
|
|
if ( r3 & 0x08 )
|
|
{
|
|
/* Fetch the source byte from the operand */
|
|
tbyte = ARCH_DEP(vfetchb) ( effective_addr2, b2, regs );
|
|
|
|
/* If this is the first byte fetched then test the
|
|
high-order bit to determine the condition code */
|
|
if ( (r3 & 0xF0) == 0 )
|
|
h = (tbyte & 0x80) ? 1 : 2;
|
|
|
|
/* If byte is non-zero then set the condition code */
|
|
if ( tbyte != 0 )
|
|
cc = h;
|
|
|
|
/* Insert the byte into the register */
|
|
dreg &= 0xFFFFFFFF00FFFFFFULL;
|
|
dreg |= (U32)tbyte << 24;
|
|
|
|
/* Increment the operand address */
|
|
effective_addr2++;
|
|
effective_addr2 &= ADDRESS_MAXWRAP(regs);
|
|
}
|
|
|
|
/* Shift mask and register for next byte */
|
|
r3 <<= 1;
|
|
dreg <<= 8;
|
|
|
|
} /* end for(i) */
|
|
|
|
/* Load the register with the updated value */
|
|
regs->GR_H(r1) = dreg >> 32;
|
|
|
|
/* Set condition code */
|
|
regs->psw.cc = cc;
|
|
|
|
} /* end DEF_INST(insert_characters_under_mask_high) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* EC44 BRXHG - Branch Relative on Index High Long [RIE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(branch_relative_on_index_high_long)
|
|
{
|
|
int r1, r3; /* Register numbers */
|
|
U32 i2; /* 32-bit operand */
|
|
S64 i,j; /* Integer workareas */
|
|
|
|
RIE(inst, execflag, regs, r1, r3, i2);
|
|
|
|
/* Load the increment value from the R3 register */
|
|
i = (S64)regs->GR_G(r3);
|
|
|
|
/* Load compare value from R3 (if R3 odd), or R3+1 (if even) */
|
|
j = (r3 & 1) ? (S64)regs->GR_G(r3) : (S64)regs->GR_G(r3+1);
|
|
|
|
/* Add the increment value to the R1 register */
|
|
(S64)regs->GR_G(r1) += i;
|
|
|
|
/* Branch if result compares high */
|
|
if ( (S64)regs->GR_G(r1) > j )
|
|
{
|
|
regs->psw.IA = ((!execflag ? (regs->psw.IA - 6) : regs->ET)
|
|
+ 2LL*(S32)i2) & ADDRESS_MAXWRAP(regs);
|
|
#if defined(FEATURE_PER)
|
|
if( EN_IC_PER_SB(regs)
|
|
#if defined(FEATURE_PER2)
|
|
&& ( !(regs->CR(9) & CR9_BAC)
|
|
|| PER_RANGE_CHECK(regs->psw.IA,regs->CR(10),regs->CR(11)) )
|
|
#endif /*defined(FEATURE_PER2)*/
|
|
)
|
|
ON_IC_PER_SB(regs);
|
|
#endif /*defined(FEATURE_PER)*/
|
|
}
|
|
|
|
} /* end DEF_INST(branch_relative_on_index_high_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* EC45 BRXLG - Branch Relative on Index Low or Equal Long [RIE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(branch_relative_on_index_low_or_equal_long)
|
|
{
|
|
int r1, r3; /* Register numbers */
|
|
U32 i2; /* 32-bit operand */
|
|
S64 i,j; /* Integer workareas */
|
|
|
|
RIE(inst, execflag, regs, r1, r3, i2);
|
|
|
|
/* Load the increment value from the R3 register */
|
|
i = (S64)regs->GR_G(r3);
|
|
|
|
/* Load compare value from R3 (if R3 odd), or R3+1 (if even) */
|
|
j = (r3 & 1) ? (S64)regs->GR_G(r3) : (S64)regs->GR_G(r3+1);
|
|
|
|
/* Add the increment value to the R1 register */
|
|
(S64)regs->GR_G(r1) += i;
|
|
|
|
/* Branch if result compares low or equal */
|
|
if ( (S64)regs->GR_G(r1) <= j )
|
|
{
|
|
regs->psw.IA = ((!execflag ? (regs->psw.IA - 6) : regs->ET)
|
|
+ 2LL*(S32)i2) & ADDRESS_MAXWRAP(regs);
|
|
#if defined(FEATURE_PER)
|
|
if( EN_IC_PER_SB(regs)
|
|
#if defined(FEATURE_PER2)
|
|
&& ( !(regs->CR(9) & CR9_BAC)
|
|
|| PER_RANGE_CHECK(regs->psw.IA,regs->CR(10),regs->CR(11)) )
|
|
#endif /*defined(FEATURE_PER2)*/
|
|
)
|
|
ON_IC_PER_SB(regs);
|
|
#endif /*defined(FEATURE_PER)*/
|
|
}
|
|
|
|
} /* end DEF_INST(branch_relative_on_index_low_or_equal_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* EB44 BXHG - Branch on Index High Long [RSE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(branch_on_index_high_long)
|
|
{
|
|
int r1, r3; /* Register numbers */
|
|
int b2; /* effective address base */
|
|
VADR effective_addr2; /* effective address */
|
|
S64 i, j; /* Integer work areas */
|
|
|
|
RSE(inst, execflag, regs, r1, r3, b2, effective_addr2);
|
|
|
|
/* Load the increment value from the R3 register */
|
|
i = (S64)regs->GR_G(r3);
|
|
|
|
/* Load compare value from R3 (if R3 odd), or R3+1 (if even) */
|
|
j = (r3 & 1) ? (S64)regs->GR_G(r3) : (S64)regs->GR_G(r3+1);
|
|
|
|
/* Add the increment value to the R1 register */
|
|
(S64)regs->GR_G(r1) += i;
|
|
|
|
/* Branch if result compares high */
|
|
if ( (S64)regs->GR_G(r1) > j )
|
|
{
|
|
regs->psw.IA = effective_addr2;
|
|
#if defined(FEATURE_PER)
|
|
if( EN_IC_PER_SB(regs)
|
|
#if defined(FEATURE_PER2)
|
|
&& ( !(regs->CR(9) & CR9_BAC)
|
|
|| PER_RANGE_CHECK(effective_addr2,regs->CR(10),regs->CR(11)) )
|
|
#endif /*defined(FEATURE_PER2)*/
|
|
)
|
|
ON_IC_PER_SB(regs);
|
|
#endif /*defined(FEATURE_PER)*/
|
|
}
|
|
|
|
} /* end DEF_INST(branch_on_index_high_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* EB45 BXLEG - Branch on Index Low or Equal Long [RSE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(branch_on_index_low_or_equal_long)
|
|
{
|
|
int r1, r3; /* Register numbers */
|
|
int b2; /* effective address base */
|
|
VADR effective_addr2; /* effective address */
|
|
S64 i, j; /* Integer work areas */
|
|
|
|
RSE(inst, execflag, regs, r1, r3, b2, effective_addr2);
|
|
|
|
/* Load the increment value from the R3 register */
|
|
i = regs->GR_G(r3);
|
|
|
|
/* Load compare value from R3 (if R3 odd), or R3+1 (if even) */
|
|
j = (r3 & 1) ? (S64)regs->GR_G(r3) : (S64)regs->GR_G(r3+1);
|
|
|
|
/* Add the increment value to the R1 register */
|
|
(S64)regs->GR_G(r1) += i;
|
|
|
|
/* Branch if result compares low or equal */
|
|
if ( (S64)regs->GR_G(r1) <= j )
|
|
{
|
|
regs->psw.IA = effective_addr2;
|
|
#if defined(FEATURE_PER)
|
|
if( EN_IC_PER_SB(regs)
|
|
#if defined(FEATURE_PER2)
|
|
&& ( !(regs->CR(9) & CR9_BAC)
|
|
|| PER_RANGE_CHECK(effective_addr2,regs->CR(10),regs->CR(11)) )
|
|
#endif /*defined(FEATURE_PER2)*/
|
|
)
|
|
ON_IC_PER_SB(regs);
|
|
#endif /*defined(FEATURE_PER)*/
|
|
}
|
|
|
|
} /* end DEF_INST(branch_on_index_low_or_equal_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* EB30 CSG - Compare and Swap Long [RSE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(compare_and_swap_long)
|
|
{
|
|
int r1, r3; /* Register numbers */
|
|
int b2; /* effective address base */
|
|
VADR effective_addr2; /* effective address */
|
|
U64 n; /* 64-bit operand value */
|
|
|
|
RSE(inst, execflag, regs, r1, r3, b2, effective_addr2);
|
|
|
|
DW_CHECK(effective_addr2, regs);
|
|
|
|
/* Perform serialization before starting operation */
|
|
PERFORM_SERIALIZATION (regs);
|
|
|
|
/* Obtain main-storage access lock */
|
|
OBTAIN_MAINLOCK(regs);
|
|
|
|
/* Load second operand from operand address */
|
|
n = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs );
|
|
|
|
/* Compare operand with R1 register contents */
|
|
if ( regs->GR_G(r1) == n )
|
|
{
|
|
/* If equal, store R3 at operand location and set cc=0 */
|
|
ARCH_DEP(vstore8) ( regs->GR_G(r3), effective_addr2, b2, regs );
|
|
regs->psw.cc = 0;
|
|
}
|
|
else
|
|
{
|
|
/* If unequal, load R1 from operand and set cc=1 */
|
|
regs->GR_G(r1) = n;
|
|
regs->psw.cc = 1;
|
|
}
|
|
|
|
/* Release main-storage access lock */
|
|
RELEASE_MAINLOCK(regs);
|
|
|
|
/* Perform serialization after completing operation */
|
|
PERFORM_SERIALIZATION (regs);
|
|
|
|
#if MAX_CPU_ENGINES > 1 && defined(OPTION_CS_USLEEP)
|
|
/* It this is a failed compare and swap
|
|
and there is more then 1 CPU in the configuration
|
|
and there is no broadcast synchronization in progress
|
|
then call the hypervisor to end this timeslice,
|
|
this to prevent this virtual CPU monopolizing
|
|
the physical CPU on a spinlock */
|
|
if(regs->psw.cc && sysblk.numcpu > 1)
|
|
usleep(1L);
|
|
#endif /* MAX_CPU_ENGINES > 1 && defined)OPTION_CS_USLEEP) */
|
|
|
|
#if defined(_FEATURE_ZSIE)
|
|
if((regs->sie_state && (regs->siebk->ic[0] & SIE_IC0_CS1))
|
|
&& regs->psw.cc == 1)
|
|
{
|
|
if( !OPEN_IC_PERINT(regs) )
|
|
longjmp(regs->progjmp, SIE_INTERCEPT_INST);
|
|
else
|
|
longjmp(regs->progjmp, SIE_INTERCEPT_INSTCOMP);
|
|
}
|
|
#endif /*defined(_FEATURE_ZSIE)*/
|
|
|
|
} /* end DEF_INST(compare_and_swap_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* EB3E CDSG - Compare Double and Swap Long [RSE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(compare_double_and_swap_long)
|
|
{
|
|
int r1, r3; /* Register numbers */
|
|
int b2; /* effective address base */
|
|
VADR effective_addr2; /* effective address */
|
|
U64 n1, n2; /* 64-bit operand values */
|
|
|
|
RSE(inst, execflag, regs, r1, r3, b2, effective_addr2);
|
|
|
|
ODD2_CHECK(r1, r3, regs);
|
|
|
|
QW_CHECK(effective_addr2, regs);
|
|
|
|
/* Perform serialization before starting operation */
|
|
PERFORM_SERIALIZATION (regs);
|
|
|
|
/* Obtain main-storage access lock */
|
|
OBTAIN_MAINLOCK(regs);
|
|
|
|
/* Load second operand from operand address */
|
|
n1 = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs );
|
|
n2 = ARCH_DEP(vfetch8) ( effective_addr2 + 8, b2, regs );
|
|
|
|
/* Compare doubleword operand with R1:R1+1 register contents */
|
|
if ( regs->GR_G(r1) == n1 && regs->GR_G(r1+1) == n2 )
|
|
{
|
|
/* If equal, store R3:R3+1 at operand location and set cc=0 */
|
|
ARCH_DEP(validate_operand) (effective_addr2 + 8, b2, 8-1,
|
|
ACCTYPE_WRITE, regs);
|
|
ARCH_DEP(vstore8) ( regs->GR_G(r3), effective_addr2, b2, regs );
|
|
ARCH_DEP(vstore8) ( regs->GR_G(r3+1), effective_addr2 + 8, b2, regs );
|
|
regs->psw.cc = 0;
|
|
}
|
|
else
|
|
{
|
|
/* If unequal, load R1:R1+1 from operand and set cc=1 */
|
|
regs->GR_G(r1) = n1;
|
|
regs->GR_G(r1+1) = n2;
|
|
regs->psw.cc = 1;
|
|
}
|
|
|
|
/* Release main-storage access lock */
|
|
RELEASE_MAINLOCK(regs);
|
|
|
|
/* Perform serialization after completing operation */
|
|
PERFORM_SERIALIZATION (regs);
|
|
|
|
#if MAX_CPU_ENGINES > 1 && defined(OPTION_CS_USLEEP)
|
|
/* It this is a failed compare and swap
|
|
and there is more then 1 CPU in the configuration
|
|
and there is no broadcast synchronization in progress
|
|
then call the hypervisor to end this timeslice,
|
|
this to prevent this virtual CPU monopolizing
|
|
the physical CPU on a spinlock */
|
|
if(regs->psw.cc && sysblk.numcpu > 1)
|
|
usleep(1L);
|
|
#endif /* MAX_CPU_ENGINES > 1 && defined(OPTION_CS_USLEEP) */
|
|
|
|
#if defined(_FEATURE_ZSIE)
|
|
if((regs->sie_state && (regs->siebk->ic[0] & SIE_IC0_CDS1))
|
|
&& regs->psw.cc == 1)
|
|
{
|
|
if( !OPEN_IC_PERINT(regs) )
|
|
longjmp(regs->progjmp, SIE_INTERCEPT_INST);
|
|
else
|
|
longjmp(regs->progjmp, SIE_INTERCEPT_INSTCOMP);
|
|
}
|
|
#endif /*defined(_FEATURE_ZSIE)*/
|
|
|
|
} /* end DEF_INST(compare_double_and_swap_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E346 BCTG - Branch on Count Long [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(branch_on_count_long)
|
|
{
|
|
int r1; /* Value of R field */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Subtract 1 from the R1 operand and branch if non-zero */
|
|
if ( --(regs->GR_G(r1)) )
|
|
{
|
|
regs->psw.IA = effective_addr2;
|
|
#if defined(FEATURE_PER)
|
|
if( EN_IC_PER_SB(regs)
|
|
#if defined(FEATURE_PER2)
|
|
&& ( !(regs->CR(9) & CR9_BAC)
|
|
|| PER_RANGE_CHECK(effective_addr2,regs->CR(10),regs->CR(11)) )
|
|
#endif /*defined(FEATURE_PER2)*/
|
|
)
|
|
ON_IC_PER_SB(regs);
|
|
#endif /*defined(FEATURE_PER)*/
|
|
}
|
|
|
|
} /* end DEF_INST(branch_on_count_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B946 BCTGR - Branch on Count Long Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(branch_on_count_long_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
VADR newia; /* New instruction address */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
/* Compute the branch address from the R2 operand */
|
|
newia = regs->GR_G(r2) & ADDRESS_MAXWRAP(regs);
|
|
|
|
/* Subtract 1 from the R1 operand and branch if result
|
|
is non-zero and R2 operand is not register zero */
|
|
if ( --(regs->GR_G(r1)) && r2 != 0 )
|
|
{
|
|
regs->psw.IA = newia;
|
|
#if defined(FEATURE_PER)
|
|
if( EN_IC_PER_SB(regs)
|
|
#if defined(FEATURE_PER2)
|
|
&& ( !(regs->CR(9) & CR9_BAC)
|
|
|| PER_RANGE_CHECK(newia,regs->CR(10),regs->CR(11)) )
|
|
#endif /*defined(FEATURE_PER2)*/
|
|
)
|
|
ON_IC_PER_SB(regs);
|
|
#endif /*defined(FEATURE_PER)*/
|
|
}
|
|
|
|
} /* end DEF_INST(branch_on_count_long_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B920 CGR - Compare Long Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(compare_long_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
/* Compare signed operands and set condition code */
|
|
regs->psw.cc =
|
|
(S64)regs->GR_G(r1) < (S64)regs->GR_G(r2) ? 1 :
|
|
(S64)regs->GR_G(r1) > (S64)regs->GR_G(r2) ? 2 : 0;
|
|
|
|
} /* end DEF_INST(compare_long_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B930 CGFR - Compare Long Fullword Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(compare_long_fullword_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
/* Compare signed operands and set condition code */
|
|
regs->psw.cc =
|
|
(S64)regs->GR_G(r1) < (S32)regs->GR_L(r2) ? 1 :
|
|
(S64)regs->GR_G(r1) > (S32)regs->GR_L(r2) ? 2 : 0;
|
|
|
|
} /* end DEF_INST(compare_long_fullword_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E320 CG - Compare Long [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(compare_long)
|
|
{
|
|
int r1; /* Values of R fields */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
U64 n; /* 64-bit operand values */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Load second operand from operand address */
|
|
n = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs );
|
|
|
|
/* Compare signed operands and set condition code */
|
|
regs->psw.cc =
|
|
(S64)regs->GR_G(r1) < (S64)n ? 1 :
|
|
(S64)regs->GR_G(r1) > (S64)n ? 2 : 0;
|
|
|
|
} /* end DEF_INST(compare_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E330 CGF - Compare Long Fullword [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(compare_long_fullword)
|
|
{
|
|
int r1; /* Values of R fields */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
U32 n; /* 32-bit operand values */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Load second operand from operand address */
|
|
n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs );
|
|
|
|
/* Compare signed operands and set condition code */
|
|
regs->psw.cc =
|
|
(S64)regs->GR_G(r1) < (S32)n ? 1 :
|
|
(S64)regs->GR_G(r1) > (S32)n ? 2 : 0;
|
|
|
|
} /* end DEF_INST(compare_long_fullword) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E30A ALG - Add Logical Long [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(add_logical_long)
|
|
{
|
|
int r1; /* Values of R fields */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
U64 n; /* 64-bit operand values */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Load second operand from operand address */
|
|
n = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs );
|
|
|
|
/* Add unsigned operands and set condition code */
|
|
regs->psw.cc = add_logical_long(&(regs->GR_G(r1)),
|
|
regs->GR_G(r1),
|
|
n);
|
|
|
|
} /* end DEF_INST(add_logical_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E31A ALGF - Add Logical Long Fullword [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(add_logical_long_fullword)
|
|
{
|
|
int r1; /* Values of R fields */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
U32 n; /* 32-bit operand values */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Load second operand from operand address */
|
|
n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs );
|
|
|
|
/* Add unsigned operands and set condition code */
|
|
regs->psw.cc = add_logical_long(&(regs->GR_G(r1)),
|
|
regs->GR_G(r1),
|
|
n);
|
|
|
|
} /* end DEF_INST(add_logical_long_fullword) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E318 AGF - Add Long Fullword [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(add_long_fullword)
|
|
{
|
|
int r1; /* Values of R fields */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
U32 n; /* 32-bit operand values */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Load second operand from operand address */
|
|
n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs );
|
|
|
|
/* Add signed operands and set condition code */
|
|
regs->psw.cc = add_signed_long (&(regs->GR_G(r1)),
|
|
regs->GR_G(r1),
|
|
(S32)n);
|
|
|
|
/* Program check if fixed-point overflow */
|
|
if ( regs->psw.cc == 3 && regs->psw.fomask )
|
|
ARCH_DEP(program_interrupt) (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION);
|
|
|
|
} /* end DEF_INST(add_long_fullword) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E308 AG - Add Long [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(add_long)
|
|
{
|
|
int r1; /* Values of R fields */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
U64 n; /* 64-bit operand values */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Load second operand from operand address */
|
|
n = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs );
|
|
|
|
/* Add signed operands and set condition code */
|
|
regs->psw.cc = add_signed_long (&(regs->GR_G(r1)),
|
|
regs->GR_G(r1),
|
|
n);
|
|
|
|
/* Program check if fixed-point overflow */
|
|
if ( regs->psw.cc == 3 && regs->psw.fomask )
|
|
ARCH_DEP(program_interrupt) (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION);
|
|
|
|
} /* end DEF_INST(add_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E30B SLG - Subtract Logical Long [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(subtract_logical_long)
|
|
{
|
|
int r1; /* Values of R fields */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
U64 n; /* 64-bit operand values */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Load second operand from operand address */
|
|
n = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs );
|
|
|
|
/* Subtract unsigned operands and set condition code */
|
|
regs->psw.cc = sub_logical_long(&(regs->GR_G(r1)),
|
|
regs->GR_G(r1),
|
|
n);
|
|
|
|
} /* end DEF_INST(subtract_logical_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E31B SLGF - Subtract Logical Long Fullword [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(subtract_logical_long_fullword)
|
|
{
|
|
int r1; /* Values of R fields */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
U32 n; /* 32-bit operand values */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Load second operand from operand address */
|
|
n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs );
|
|
|
|
/* Subtract unsigned operands and set condition code */
|
|
regs->psw.cc = sub_logical_long(&(regs->GR_G(r1)),
|
|
regs->GR_G(r1),
|
|
n);
|
|
|
|
} /* end DEF_INST(subtract_logical_long_fullword) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E319 SGF - Subtract Long Fullword [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(subtract_long_fullword)
|
|
{
|
|
int r1; /* Values of R fields */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
U32 n; /* 32-bit operand values */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Load second operand from operand address */
|
|
n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs );
|
|
|
|
/* Subtract signed operands and set condition code */
|
|
regs->psw.cc = sub_signed_long(&(regs->GR_G(r1)),
|
|
regs->GR_G(r1),
|
|
(S32)n);
|
|
|
|
/* Program check if fixed-point overflow */
|
|
if ( regs->psw.cc == 3 && regs->psw.fomask )
|
|
ARCH_DEP(program_interrupt) (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION);
|
|
|
|
} /* end DEF_INST(subtract_long_fullword) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E309 SG - Subtract Long [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(subtract_long)
|
|
{
|
|
int r1; /* Values of R fields */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
U64 n; /* 64-bit operand values */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Load second operand from operand address */
|
|
n = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs );
|
|
|
|
/* Subtract signed operands and set condition code */
|
|
regs->psw.cc = sub_signed_long(&(regs->GR_G(r1)),
|
|
regs->GR_G(r1),
|
|
n);
|
|
|
|
/* Program check if fixed-point overflow */
|
|
if ( regs->psw.cc == 3 && regs->psw.fomask )
|
|
ARCH_DEP(program_interrupt) (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION);
|
|
|
|
} /* end DEF_INST(subtract_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B909 SGR - Subtract Long Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(subtract_long_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
/* Subtract signed operands and set condition code */
|
|
regs->psw.cc = sub_signed_long(&(regs->GR_G(r1)),
|
|
regs->GR_G(r1),
|
|
regs->GR_G(r2));
|
|
|
|
/* Program check if fixed-point overflow */
|
|
if ( regs->psw.cc == 3 && regs->psw.fomask )
|
|
ARCH_DEP(program_interrupt) (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION);
|
|
|
|
} /* end DEF_INST(subtract_long_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B919 SGFR - Subtract Long Fullword Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(subtract_long_fullword_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
/* Subtract signed operands and set condition code */
|
|
regs->psw.cc = sub_signed_long(&(regs->GR_G(r1)),
|
|
regs->GR_G(r1),
|
|
(S32)regs->GR_L(r2));
|
|
|
|
/* Program check if fixed-point overflow */
|
|
if ( regs->psw.cc == 3 && regs->psw.fomask )
|
|
ARCH_DEP(program_interrupt) (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION);
|
|
|
|
} /* end DEF_INST(subtract_long_fullword_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B908 AGR - Add Long Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(add_long_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
/* Add signed operands and set condition code */
|
|
regs->psw.cc = add_signed_long(&(regs->GR_G(r1)),
|
|
regs->GR_G(r1),
|
|
regs->GR_G(r2));
|
|
|
|
/* Program check if fixed-point overflow */
|
|
if ( regs->psw.cc == 3 && regs->psw.fomask )
|
|
ARCH_DEP(program_interrupt) (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION);
|
|
|
|
} /* end DEF_INST(add_long_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B918 AGFR - Add Long Fullword Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(add_long_fullword_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
/* Add signed operands and set condition code */
|
|
regs->psw.cc = add_signed_long(&(regs->GR_G(r1)),
|
|
regs->GR_G(r1),
|
|
(S32)regs->GR_L(r2));
|
|
|
|
/* Program check if fixed-point overflow */
|
|
if ( regs->psw.cc == 3 && regs->psw.fomask )
|
|
ARCH_DEP(program_interrupt) (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION);
|
|
|
|
} /* end DEF_INST(add_long_fullword_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B900 LPGR - Load Positive Long Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_positive_long_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
/* Condition code 3 and program check if overflow */
|
|
if ( regs->GR_G(r2) == 0x8000000000000000ULL )
|
|
{
|
|
regs->GR_G(r1) = regs->GR_G(r2);
|
|
regs->psw.cc = 3;
|
|
if ( regs->psw.fomask )
|
|
ARCH_DEP(program_interrupt) (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION);
|
|
return;
|
|
}
|
|
|
|
/* Load positive value of second operand and set cc */
|
|
(S64)regs->GR_G(r1) = (S64)regs->GR_G(r2) < 0 ?
|
|
-((S64)regs->GR_G(r2)) :
|
|
(S64)regs->GR_G(r2);
|
|
|
|
regs->psw.cc = (S64)regs->GR_G(r1) == 0 ? 0 : 2;
|
|
|
|
} /* end DEF_INST(load_positive_long_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B910 LPGFR - Load Positive Long Fullword Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_positive_long_fullword_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
S64 gpr2l;
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
gpr2l = (S32)regs->GR_L(r2);
|
|
|
|
/* Load positive value of second operand and set cc */
|
|
(S64)regs->GR_G(r1) = gpr2l < 0 ? -gpr2l : gpr2l;
|
|
|
|
regs->psw.cc = (S64)regs->GR_G(r1) == 0 ? 0 : 2;
|
|
|
|
} /* end DEF_INST(load_positive_long_fullword_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B901 LNGR - Load Negative Long Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_negative_long_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
/* Load negative value of second operand and set cc */
|
|
(S64)regs->GR_G(r1) = (S64)regs->GR_G(r2) > 0 ?
|
|
-((S64)regs->GR_G(r2)) :
|
|
(S64)regs->GR_G(r2);
|
|
|
|
regs->psw.cc = (S64)regs->GR_G(r1) == 0 ? 0 : 1;
|
|
|
|
} /* end DEF_INST(load_negative_long_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B911 LNGFR - Load Negative Long Fullword Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_negative_long_fullword_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
S64 gpr2l;
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
gpr2l = (S32)regs->GR_L(r2);
|
|
|
|
/* Load negative value of second operand and set cc */
|
|
(S64)regs->GR_G(r1) = gpr2l > 0 ? -gpr2l : gpr2l;
|
|
|
|
regs->psw.cc = (S64)regs->GR_G(r1) == 0 ? 0 : 1;
|
|
|
|
} /* end DEF_INST(load_negative_long_fullword_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B902 LTGR - Load and Test Long Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_and_test_long_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
/* Copy second operand and set condition code */
|
|
regs->GR_G(r1) = regs->GR_G(r2);
|
|
|
|
regs->psw.cc = (S64)regs->GR_G(r1) < 0 ? 1 :
|
|
(S64)regs->GR_G(r1) > 0 ? 2 : 0;
|
|
|
|
} /* end DEF_INST(load_and_test_long_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B912 LTGFR - Load and Test Long Fullword Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_and_test_long_fullword_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
/* Copy second operand and set condition code */
|
|
(S64)regs->GR_G(r1) = (S32)regs->GR_L(r2);
|
|
|
|
regs->psw.cc = (S64)regs->GR_G(r1) < 0 ? 1 :
|
|
(S64)regs->GR_G(r1) > 0 ? 2 : 0;
|
|
|
|
} /* end DEF_INST(load_and_test_long_fullword_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B903 LCGR - Load Complement Long Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_complement_long_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
/* Condition code 3 and program check if overflow */
|
|
if ( regs->GR_G(r2) == 0x8000000000000000ULL )
|
|
{
|
|
regs->GR_G(r1) = regs->GR_G(r2);
|
|
regs->psw.cc = 3;
|
|
if ( regs->psw.fomask )
|
|
ARCH_DEP(program_interrupt) (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION);
|
|
return;
|
|
}
|
|
|
|
/* Load complement of second operand and set condition code */
|
|
(S64)regs->GR_G(r1) = -((S64)regs->GR_G(r2));
|
|
|
|
regs->psw.cc = (S64)regs->GR_G(r1) < 0 ? 1 :
|
|
(S64)regs->GR_G(r1) > 0 ? 2 : 0;
|
|
|
|
} /* end DEF_INST(load_complement_long_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B913 LCGFR - Load Complement Long Fullword Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_complement_long_fullword_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
S64 gpr2l;
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
gpr2l = (S32)regs->GR_L(r2);
|
|
|
|
/* Load complement of second operand and set condition code */
|
|
(S64)regs->GR_G(r1) = -gpr2l;
|
|
|
|
regs->psw.cc = (S64)regs->GR_G(r1) < 0 ? 1 :
|
|
(S64)regs->GR_G(r1) > 0 ? 2 : 0;
|
|
|
|
} /* end DEF_INST(load_complement_long_fullword_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* A7x2 TMHH - Test under Mask High High [RI] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(test_under_mask_high_high)
|
|
{
|
|
int r1; /* Register number */
|
|
int opcd; /* Opcode */
|
|
U16 i2; /* 16-bit operand values */
|
|
U16 h1; /* 16-bit operand values */
|
|
U16 h2; /* 16-bit operand values */
|
|
|
|
RI(inst, execflag, regs, r1, opcd, i2);
|
|
|
|
/* AND register bits 0-15 with immediate operand */
|
|
h1 = i2 & regs->GR_HHH(r1);
|
|
|
|
/* Isolate leftmost bit of immediate operand */
|
|
for ( h2 = 0x8000; h2 != 0 && (h2 & i2) == 0; h2 >>= 1 );
|
|
|
|
/* Set condition code according to result */
|
|
regs->psw.cc =
|
|
( h1 == 0 ) ? 0 : /* result all zeroes */
|
|
((h1 ^ i2) == 0) ? 3 : /* result all ones */
|
|
((h1 & h2) == 0) ? 1 : /* leftmost bit zero */
|
|
2; /* leftmost bit one */
|
|
|
|
} /* end DEF_INST(test_under_mask_high_high) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* A7x3 TMHL - Test under Mask High Low [RI] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(test_under_mask_high_low)
|
|
{
|
|
int r1; /* Register number */
|
|
int opcd; /* Opcode */
|
|
U16 i2; /* 16-bit operand values */
|
|
U16 h1; /* 16-bit operand values */
|
|
U16 h2; /* 16-bit operand values */
|
|
|
|
RI(inst, execflag, regs, r1, opcd, i2);
|
|
|
|
/* AND register bits 16-31 with immediate operand */
|
|
h1 = i2 & regs->GR_HHL(r1);
|
|
|
|
/* Isolate leftmost bit of immediate operand */
|
|
for ( h2 = 0x8000; h2 != 0 && (h2 & i2) == 0; h2 >>= 1 );
|
|
|
|
/* Set condition code according to result */
|
|
regs->psw.cc =
|
|
( h1 == 0 ) ? 0 : /* result all zeroes */
|
|
((h1 ^ i2) == 0) ? 3 : /* result all ones */
|
|
((h1 & h2) == 0) ? 1 : /* leftmost bit zero */
|
|
2; /* leftmost bit one */
|
|
|
|
} /* end DEF_INST(test_under_mask_high_low) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* A7x7 BRCTG - Branch Relative on Count Long [RI] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(branch_relative_on_count_long)
|
|
{
|
|
int r1; /* Register number */
|
|
int opcd; /* Opcode */
|
|
U16 i2; /* 16-bit operand values */
|
|
|
|
RI(inst, execflag, regs, r1, opcd, i2);
|
|
|
|
/* Subtract 1 from the R1 operand and branch if non-zero */
|
|
if ( --(regs->GR_G(r1)) )
|
|
{
|
|
regs->psw.IA = ((!execflag ? (regs->psw.IA - 4) : regs->ET)
|
|
+ 2*(S16)i2) & ADDRESS_MAXWRAP(regs);
|
|
#if defined(FEATURE_PER)
|
|
if( EN_IC_PER_SB(regs)
|
|
#if defined(FEATURE_PER2)
|
|
&& ( !(regs->CR(9) & CR9_BAC)
|
|
|| PER_RANGE_CHECK(regs->psw.IA,regs->CR(10),regs->CR(11)) )
|
|
#endif /*defined(FEATURE_PER2)*/
|
|
)
|
|
ON_IC_PER_SB(regs);
|
|
#endif /*defined(FEATURE_PER)*/
|
|
}
|
|
} /* end DEF_INST(branch_relative_on_count_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E321 CLG - Compare Logical long [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(compare_logical_long)
|
|
{
|
|
int r1; /* Values of R fields */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
U64 n; /* 64-bit operand values */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Load second operand from operand address */
|
|
n = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs );
|
|
|
|
/* Compare unsigned operands and set condition code */
|
|
regs->psw.cc = regs->GR_G(r1) < n ? 1 :
|
|
regs->GR_G(r1) > n ? 2 : 0;
|
|
|
|
} /* end DEF_INST(compare_logical_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E331 CLGF - Compare Logical long fullword [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(compare_logical_long_fullword)
|
|
{
|
|
int r1; /* Values of R fields */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
U32 n; /* 32-bit operand values */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Load second operand from operand address */
|
|
n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs );
|
|
|
|
/* Compare unsigned operands and set condition code */
|
|
regs->psw.cc = regs->GR_G(r1) < n ? 1 :
|
|
regs->GR_G(r1) > n ? 2 : 0;
|
|
|
|
} /* end DEF_INST(compare_logical_long_fullword) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B931 CLGFR - Compare Logical Long Fullword Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(compare_logical_long_fullword_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
/* Compare unsigned operands and set condition code */
|
|
regs->psw.cc = regs->GR_G(r1) < regs->GR_L(r2) ? 1 :
|
|
regs->GR_G(r1) > regs->GR_L(r2) ? 2 : 0;
|
|
|
|
} /* end DEF_INST(compare_logical_long_fullword_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B917 LLGTR - Load Logical Long Thirtyone Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_logical_long_thirtyone_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
regs->GR_G(r1) = regs->GR_L(r2) & 0x7FFFFFFF;
|
|
|
|
} /* end DEF_INST(load_logical_long_thirtyone_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B921 CLGR - Compare Logical Long Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(compare_logical_long_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
/* Compare unsigned operands and set condition code */
|
|
regs->psw.cc = regs->GR_G(r1) < regs->GR_G(r2) ? 1 :
|
|
regs->GR_G(r1) > regs->GR_G(r2) ? 2 : 0;
|
|
|
|
} /* end DEF_INST(compare_logical_long_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* EB1C RLLG - Rotate Left Single Logical Long [RSE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(rotate_left_single_logical_long)
|
|
{
|
|
int r1, r3; /* Register numbers */
|
|
int b2; /* effective address base */
|
|
VADR effective_addr2; /* effective address */
|
|
U64 n; /* Integer work areas */
|
|
|
|
RSE(inst, execflag, regs, r1, r3, b2, effective_addr2);
|
|
|
|
/* Use rightmost six bits of operand address as shift count */
|
|
n = effective_addr2 & 0x3F;
|
|
|
|
/* Rotate and copy contents of r3 to r1 */
|
|
regs->GR_G(r1) = (regs->GR_G(r3) << n)
|
|
| ((n == 0) ? 0 : (regs->GR_G(r3) >> (64 - n)));
|
|
|
|
} /* end DEF_INST(rotate_left_single_logical_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* EB1D RLL - Rotate Left Single Logical [RSE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(rotate_left_single_logical)
|
|
{
|
|
int r1, r3; /* Register numbers */
|
|
int b2; /* effective address base */
|
|
VADR effective_addr2; /* effective address */
|
|
U64 n; /* Integer work areas */
|
|
|
|
RSE(inst, execflag, regs, r1, r3, b2, effective_addr2);
|
|
|
|
/* Use rightmost five bits of operand address as shift count */
|
|
n = effective_addr2 & 0x1F;
|
|
|
|
/* Rotate and copy contents of r3 to r1 */
|
|
regs->GR_L(r1) = (regs->GR_L(r3) << n)
|
|
| ((n == 0) ? 0 : (regs->GR_L(r3) >> (32 - n)));
|
|
|
|
} /* end DEF_INST(rotate_left_single_logical) */
|
|
#endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* EB0D SLLG - Shift Left Single Logical Long [RSE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(shift_left_single_logical_long)
|
|
{
|
|
int r1, r3; /* Register numbers */
|
|
int b2; /* effective address base */
|
|
VADR effective_addr2; /* effective address */
|
|
U64 n; /* Integer work areas */
|
|
|
|
RSE(inst, execflag, regs, r1, r3, b2, effective_addr2);
|
|
|
|
/* Use rightmost six bits of operand address as shift count */
|
|
n = effective_addr2 & 0x3F;
|
|
|
|
/* Copy contents of r3 to r1 and perform shift */
|
|
regs->GR_G(r1) = regs->GR_G(r3) << n;
|
|
|
|
} /* end DEF_INST(shift_left_single_logical_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* EB0C SRLG - Shift Right Single Logical Long [RSE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(shift_right_single_logical_long)
|
|
{
|
|
int r1, r3; /* Register numbers */
|
|
int b2; /* effective address base */
|
|
VADR effective_addr2; /* effective address */
|
|
U64 n; /* Integer work areas */
|
|
|
|
RSE(inst, execflag, regs, r1, r3, b2, effective_addr2);
|
|
|
|
/* Use rightmost six bits of operand address as shift count */
|
|
n = effective_addr2 & 0x3F;
|
|
|
|
/* Copy contents of r3 to r1 and perform shift */
|
|
regs->GR_G(r1) = regs->GR_G(r3) >> n;
|
|
|
|
} /* end DEF_INST(shift_right_single_logical_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* EB0B SLAG - Shift Left Single Long [RSE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(shift_left_single_long)
|
|
{
|
|
int r1, r3; /* Register numbers */
|
|
int b2; /* effective address base */
|
|
VADR effective_addr2; /* effective address */
|
|
U64 n, n1, n2; /* 64-bit operand values */
|
|
int i, j; /* Integer work areas */
|
|
|
|
RSE(inst, execflag, regs, r1, r3, b2, effective_addr2);
|
|
|
|
/* Use rightmost six bits of operand address as shift count */
|
|
n = effective_addr2 & 0x3F;
|
|
|
|
/* Load the numeric and sign portions from the R3 register */
|
|
n1 = regs->GR_G(r3) & 0x7FFFFFFFFFFFFFFFULL;
|
|
n2 = regs->GR_G(r3) & 0x8000000000000000ULL;
|
|
|
|
/* Shift the numeric portion left n positions */
|
|
for (i = 0, j = 0; i < n; i++)
|
|
{
|
|
/* Shift bits 1-63 left one bit position */
|
|
n1 <<= 1;
|
|
|
|
/* Overflow if bit shifted out is unlike the sign bit */
|
|
if ((n1 & 0x8000000000000000ULL) != n2)
|
|
j = 1;
|
|
}
|
|
|
|
/* Load the updated value into the R1 register */
|
|
regs->GR_G(r1) = (n1 & 0x7FFFFFFFFFFFFFFFULL) | n2;
|
|
|
|
/* Condition code 3 and program check if overflow occurred */
|
|
if (j)
|
|
{
|
|
regs->psw.cc = 3;
|
|
if ( regs->psw.fomask )
|
|
ARCH_DEP(program_interrupt) (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION);
|
|
return;
|
|
}
|
|
|
|
/* Set the condition code */
|
|
regs->psw.cc = (S64)regs->GR_G(r1) > 0 ? 2 :
|
|
(S64)regs->GR_G(r1) < 0 ? 1 : 0;
|
|
|
|
} /* end DEF_INST(shift_left_single_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* EB0A SRAG - Shift Right single Long [RSE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(shift_right_single_long)
|
|
{
|
|
int r1, r3; /* Register numbers */
|
|
int b2; /* effective address base */
|
|
VADR effective_addr2; /* effective address */
|
|
U64 n; /* Integer work areas */
|
|
|
|
RSE(inst, execflag, regs, r1, r3, b2, effective_addr2);
|
|
|
|
/* Use rightmost six bits of operand address as shift count */
|
|
n = effective_addr2 & 0x3F;
|
|
|
|
/* Copy and shift the signed value of the R3 register */
|
|
(S64)regs->GR_G(r1) = (n > 62) ?
|
|
((S64)regs->GR_G(r3) < 0 ? -1LL : 0) :
|
|
(S64)regs->GR_G(r3) >> n;
|
|
|
|
/* Set the condition code */
|
|
regs->psw.cc = (S64)regs->GR_G(r1) > 0 ? 2 :
|
|
(S64)regs->GR_G(r1) < 0 ? 1 : 0;
|
|
|
|
} /* end DEF_INST(shift_right_single_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E31C MSGF - Multiply Single Long Fullword [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(multiply_single_long_fullword)
|
|
{
|
|
int r1; /* Value of R field */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
U32 n; /* 32-bit operand values */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Load second operand from operand address */
|
|
n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs );
|
|
|
|
/* Multiply signed operands ignoring overflow */
|
|
(S64)regs->GR_G(r1) *= (S32)n;
|
|
|
|
} /* end DEF_INST(multiply_single_long_fullword) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E30C MSG - Multiply Single Long [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(multiply_single_long)
|
|
{
|
|
int r1; /* Value of R field */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
U64 n; /* 64-bit operand values */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Load second operand from operand address */
|
|
n = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs );
|
|
|
|
/* Multiply signed operands ignoring overflow */
|
|
(S64)regs->GR_G(r1) *= (S64)n;
|
|
|
|
} /* end DEF_INST(multiply_single_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B91C MSGFR - Multiply Single Long Fullword Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(multiply_single_long_fullword_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
/* Multiply signed registers ignoring overflow */
|
|
(S64)regs->GR_G(r1) *= (S32)regs->GR_L(r2);
|
|
|
|
} /* end DEF_INST(multiply_single_long_fullword_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B90C MSGR - Multiply Single Long Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(multiply_single_long_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
/* Multiply signed registers ignoring overflow */
|
|
(S64)regs->GR_G(r1) *= (S64)regs->GR_G(r2);
|
|
|
|
} /* end DEF_INST(multiply_single_long_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* A7x9 LGHI - Load Long Halfword Immediate [RI] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_long_halfword_immediate)
|
|
{
|
|
int r1; /* Register number */
|
|
int opcd; /* Opcode */
|
|
U16 i2; /* 16-bit operand values */
|
|
|
|
RI(inst, execflag, regs, r1, opcd, i2);
|
|
|
|
/* Load operand into register */
|
|
(S64)regs->GR_G(r1) = (S16)i2;
|
|
|
|
} /* end DEF_INST(load_long_halfword_immediate) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* A7xB AGHI - Add Long Halfword Immediate [RI] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(add_long_halfword_immediate)
|
|
{
|
|
int r1; /* Register number */
|
|
int opcd; /* Opcode */
|
|
U16 i2; /* 16-bit immediate op */
|
|
|
|
RI(inst, execflag, regs, r1, opcd, i2);
|
|
|
|
/* Add signed operands and set condition code */
|
|
regs->psw.cc = add_signed_long(&(regs->GR_G(r1)),
|
|
regs->GR_G(r1),
|
|
(S16)i2);
|
|
|
|
/* Program check if fixed-point overflow */
|
|
if ( regs->psw.cc == 3 && regs->psw.fomask )
|
|
ARCH_DEP(program_interrupt) (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION);
|
|
|
|
} /* end DEF_INST(add_long_halfword_immediate) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* A7xD MGHI - Multiply Long Halfword Immediate [RI] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(multiply_long_halfword_immediate)
|
|
{
|
|
int r1; /* Register number */
|
|
int opcd; /* Opcode */
|
|
U16 i2; /* 16-bit operand */
|
|
|
|
RI(inst, execflag, regs, r1, opcd, i2);
|
|
|
|
/* Multiply register by operand ignoring overflow */
|
|
(S64)regs->GR_G(r1) *= (S16)i2;
|
|
|
|
} /* end DEF_INST(multiply_long_halfword_immediate) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* A7xF CGHI - Compare Long Halfword Immediate [RI] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(compare_long_halfword_immediate)
|
|
{
|
|
int r1; /* Register number */
|
|
int opcd; /* Opcode */
|
|
U16 i2; /* 16-bit operand */
|
|
|
|
RI(inst, execflag, regs, r1, opcd, i2);
|
|
|
|
/* Compare signed operands and set condition code */
|
|
regs->psw.cc =
|
|
(S64)regs->GR_G(r1) < (S16)i2 ? 1 :
|
|
(S64)regs->GR_G(r1) > (S16)i2 ? 2 : 0;
|
|
|
|
} /* end DEF_INST(compare_long_halfword_immediate) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B980 NGR - And Register Long [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(and_long_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
/* AND second operand with first and set condition code */
|
|
regs->psw.cc = ( regs->GR_G(r1) &= regs->GR_G(r2) ) ? 1 : 0;
|
|
|
|
} /* end DEF_INST(and_long_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B981 OGR - Or Register Long [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(or_long_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
/* OR second operand with first and set condition code */
|
|
regs->psw.cc = ( regs->GR_G(r1) |= regs->GR_G(r2) ) ? 1 : 0;
|
|
|
|
} /* end DEF_INST(or_long_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B982 XGR - Exclusive Or Register Long [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(exclusive_or_long_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
/* XOR second operand with first and set condition code */
|
|
regs->psw.cc = ( regs->GR_G(r1) ^= regs->GR_G(r2) ) ? 1 : 0;
|
|
|
|
} /* end DEF_INST(exclusive_or_long_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E380 NG - And Long [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(and_long)
|
|
{
|
|
int r1; /* Value of R field */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
U64 n; /* 64-bit operand values */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Load second operand from operand address */
|
|
n = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs );
|
|
|
|
/* AND second operand with first and set condition code */
|
|
regs->psw.cc = ( regs->GR_G(r1) &= n ) ? 1 : 0;
|
|
|
|
} /* end DEF_INST(and_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E381 OG - Or Long [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(or_long)
|
|
{
|
|
int r1; /* Value of R field */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
U64 n; /* 64-bit operand values */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Load second operand from operand address */
|
|
n = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs );
|
|
|
|
/* OR second operand with first and set condition code */
|
|
regs->psw.cc = ( regs->GR_G(r1) |= n ) ? 1 : 0;
|
|
|
|
} /* end DEF_INST(or_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E382 XG - Exclusive Or Long [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(exclusive_or_long)
|
|
{
|
|
int r1; /* Values of R fields */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
U64 n; /* 64-bit operand values */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Load second operand from operand address */
|
|
n = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs );
|
|
|
|
/* XOR second operand with first and set condition code */
|
|
regs->psw.cc = ( regs->GR_G(r1) ^= n ) ? 1 : 0;
|
|
|
|
} /* end DEF_INST(exclusive_or_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B904 LGR - Load Long Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_long_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
/* Copy second operand to first operand */
|
|
regs->GR_G(r1) = regs->GR_G(r2);
|
|
|
|
} /* end DEF_INST(load_long_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B916 LLGFR - Load Logical Long Fullword Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_logical_long_fullword_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
/* Copy second operand to first operand */
|
|
regs->GR_G(r1) = regs->GR_L(r2);
|
|
|
|
} /* end DEF_INST(load_logical_long_fullword_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B914 LGFR - Load Long Fullword Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_long_fullword_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
/* Copy second operand to first operand */
|
|
(S64)regs->GR_G(r1) = (S32)regs->GR_L(r2);
|
|
|
|
} /* end DEF_INST(load_long_fullword_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B90A ALGR - Add Logical Register Long [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(add_logical_long_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
/* Add unsigned operands and set condition code */
|
|
regs->psw.cc = add_logical_long(&(regs->GR_G(r1)),
|
|
regs->GR_G(r1),
|
|
regs->GR_G(r2));
|
|
|
|
} /* end DEF_INST(add_logical_long_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B91A ALGFR - Add Logical Long Fullword Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(add_logical_long_fullword_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
/* Add unsigned operands and set condition code */
|
|
regs->psw.cc = add_logical_long(&(regs->GR_G(r1)),
|
|
regs->GR_G(r1),
|
|
regs->GR_L(r2));
|
|
|
|
} /* end DEF_INST(add_logical_long_fullword_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B91B SLGFR - Subtract Logical Long Fullword Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(subtract_logical_long_fullword_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
/* Subtract unsigned operands and set condition code */
|
|
regs->psw.cc = sub_logical_long(&(regs->GR_G(r1)),
|
|
regs->GR_G(r1),
|
|
regs->GR_L(r2));
|
|
|
|
} /* end DEF_INST(subtract_logical_long_fullword_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B90B SLGR - Subtract Logical Register Long [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(subtract_logical_long_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
/* Subtract unsigned operands and set condition code */
|
|
regs->psw.cc = sub_logical_long(&(regs->GR_G(r1)),
|
|
regs->GR_G(r1),
|
|
regs->GR_G(r2));
|
|
|
|
} /* end DEF_INST(subtract_logical_long_register) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* EF LMD - Load Multiple Disjoint [SS] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_multiple_disjoint)
|
|
{
|
|
int r1, r3; /* Register numbers */
|
|
int b2, b4; /* Base register numbers */
|
|
VADR effective_addr2; /* Operand2 address */
|
|
VADR effective_addr4; /* Operand4 address */
|
|
int i, d; /* Integer work areas */
|
|
BYTE rworkh[64], rworkl[64]; /* High and low halves of new
|
|
values to be loaded */
|
|
|
|
SS(inst, execflag, regs, r1, r3, b2, effective_addr2,
|
|
b4, effective_addr4);
|
|
|
|
/* Calculate the number of bytes to be loaded from each operand */
|
|
d = (((r3 < r1) ? r3 + 16 - r1 : r3 - r1) + 1) * 4;
|
|
|
|
/* Fetch high order half of new register contents from operand 2 */
|
|
ARCH_DEP(vfetchc) ( rworkh, d-1, effective_addr2, b2, regs );
|
|
|
|
/* Fetch low order half of new register contents from operand 4 */
|
|
ARCH_DEP(vfetchc) ( rworkl, d-1, effective_addr4, b4, regs );
|
|
|
|
/* Load registers from work areas */
|
|
for ( i = r1, d = 0; ; )
|
|
{
|
|
/* Load both halves of one register from the work areas */
|
|
FETCH_FW(regs->GR_H(i), rworkh + d);
|
|
FETCH_FW(regs->GR_L(i), rworkl + d);
|
|
d += 4;
|
|
|
|
/* Instruction is complete when r3 register is done */
|
|
if ( i == r3 ) break;
|
|
|
|
/* Update register number, wrapping from 15 to 0 */
|
|
i++; i &= 15;
|
|
}
|
|
|
|
} /* end DEF_INST(load_multiple_disjoint) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* EB96 LMH - Load Multiple High [RSE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_multiple_high)
|
|
{
|
|
int r1, r3; /* Register numbers */
|
|
int b2; /* effective address base */
|
|
VADR effective_addr2; /* effective address */
|
|
int i, d; /* Integer work areas */
|
|
BYTE rwork[64]; /* Character work areas */
|
|
|
|
RSE(inst, execflag, regs, r1, r3, b2, effective_addr2);
|
|
|
|
/* Calculate the number of bytes to be loaded */
|
|
d = (((r3 < r1) ? r3 + 16 - r1 : r3 - r1) + 1) * 4;
|
|
|
|
/* Fetch new register contents from operand address */
|
|
ARCH_DEP(vfetchc) ( rwork, d-1, effective_addr2, b2, regs );
|
|
|
|
/* Load registers from work area */
|
|
for ( i = r1, d = 0; ; )
|
|
{
|
|
/* Load one register from work area */
|
|
FETCH_FW(regs->GR_H(i), rwork + d); d += 4;
|
|
|
|
/* Instruction is complete when r3 register is done */
|
|
if ( i == r3 ) break;
|
|
|
|
/* Update register number, wrapping from 15 to 0 */
|
|
i++; i &= 15;
|
|
}
|
|
|
|
} /* end DEF_INST(load_multiple_high) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* EB04 LMG - Load Multiple Long [RSE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_multiple_long)
|
|
{
|
|
int r1, r3; /* Register numbers */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
int i, d; /* Integer work areas */
|
|
BYTE rwork[128]; /* Register work areas */
|
|
|
|
RSE(inst, execflag, regs, r1, r3, b2, effective_addr2);
|
|
|
|
/* Calculate the number of bytes to be loaded */
|
|
d = (((r3 < r1) ? r3 + 16 - r1 : r3 - r1) + 1) * 8;
|
|
|
|
/* Fetch new control register contents from operand address */
|
|
ARCH_DEP(vfetchc) ( rwork, d-1, effective_addr2, b2, regs );
|
|
|
|
/* Load control registers from work area */
|
|
for ( i = r1, d = 0; ; )
|
|
{
|
|
/* Load one general register from work area */
|
|
FETCH_DW(regs->GR_G(i), rwork + d); d += 8;
|
|
|
|
/* Instruction is complete when r3 register is done */
|
|
if ( i == r3 ) break;
|
|
|
|
/* Update register number, wrapping from 15 to 0 */
|
|
i++; i &= 15;
|
|
}
|
|
|
|
} /* end DEF_INST(load_multiple_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* EB25 STCTG - Store Control Long [RSE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(store_control_long)
|
|
{
|
|
int r1, r3; /* Register numbers */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
int i, d; /* Integer work areas */
|
|
BYTE rwork[128]; /* Register work areas */
|
|
|
|
RSE(inst, execflag, regs, r1, r3, b2, effective_addr2);
|
|
|
|
PRIV_CHECK(regs);
|
|
|
|
FW_CHECK(effective_addr2, regs);
|
|
|
|
#if defined(_FEATURE_ZSIE)
|
|
if(regs->sie_state && (regs->siebk->ic[1] & SIE_IC1_STCTL))
|
|
longjmp(regs->progjmp, SIE_INTERCEPT_INST);
|
|
#endif /*defined(_FEATURE_ZSIE)*/
|
|
|
|
/* Copy control registers into work area */
|
|
for ( i = r1, d = 0; ; )
|
|
{
|
|
/* Copy contents of one control register to work area */
|
|
STORE_DW(rwork + d, regs->CR_G(i)); d += 8;
|
|
|
|
/* Instruction is complete when r3 register is done */
|
|
if ( i == r3 ) break;
|
|
|
|
/* Update register number, wrapping from 15 to 0 */
|
|
i++; i &= 15;
|
|
}
|
|
|
|
/* Store control register contents at operand address */
|
|
ARCH_DEP(vstorec) ( rwork, d-1, effective_addr2, b2, regs );
|
|
|
|
} /* end DEF_INST(store_control_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* EB2F LCTLG - Load Control Long [RSE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_control_long)
|
|
{
|
|
int r1, r3; /* Register numbers */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
int i, d; /* Integer work areas */
|
|
BYTE rwork[128]; /* Register work areas */
|
|
BYTE dism; /* Disabled int subcl mask */
|
|
|
|
RSE(inst, execflag, regs, r1, r3, b2, effective_addr2);
|
|
|
|
PRIV_CHECK(regs);
|
|
|
|
FW_CHECK(effective_addr2, regs);
|
|
|
|
#if defined(_FEATURE_ZSIE)
|
|
if(regs->sie_state)
|
|
{
|
|
U32 n;
|
|
for(i = r1; ; )
|
|
{
|
|
n = 0x8000 >> i;
|
|
if(regs->siebk->lctl_ctl[i < 8 ? 0 : 1] & ((i < 8) ? n >> 8 : n))
|
|
longjmp(regs->progjmp, SIE_INTERCEPT_INST);
|
|
|
|
if ( i == r3 ) break;
|
|
i++; i &= 15;
|
|
}
|
|
}
|
|
#endif /*defined(_FEATURE_ZSIE)*/
|
|
|
|
/* Calculate the number of bytes to be loaded */
|
|
d = (((r3 < r1) ? r3 + 16 - r1 : r3 - r1) + 1) * 8;
|
|
|
|
/* Fetch new control register contents from operand address */
|
|
ARCH_DEP(vfetchc) ( rwork, d-1, effective_addr2, b2, regs );
|
|
|
|
INVALIDATE_AIA(regs);
|
|
|
|
INVALIDATE_AEA_ALL(regs);
|
|
|
|
/* Save disabled I/O subclasses */
|
|
dism = ~regs->CR_LHHCH(6);
|
|
|
|
/* Load control registers from work area */
|
|
for ( i = r1, d = 0; ; )
|
|
{
|
|
/* Load one control register from work area */
|
|
FETCH_DW(regs->CR_G(i), rwork + d); d += 8;
|
|
|
|
/* Instruction is complete when r3 register is done */
|
|
if ( i == r3 ) break;
|
|
|
|
/* Update register number, wrapping from 15 to 0 */
|
|
i++; i &= 15;
|
|
}
|
|
|
|
/* Force I/O interrupt check when enabling an I/O subclass */
|
|
if(dism & regs->CR_LHHCH(6))
|
|
{
|
|
obtain_lock(&sysblk.intlock);
|
|
ON_IC_IOPENDING;
|
|
release_lock(&sysblk.intlock);
|
|
}
|
|
|
|
SET_IC_EXTERNAL_MASK(regs);
|
|
SET_IC_MCK_MASK(regs);
|
|
SET_IC_PER_MASK(regs);
|
|
|
|
RETURN_INTCHECK(regs);
|
|
|
|
} /* end DEF_INST(load_control_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* EB24 STMG - Store Multiple Long [RSE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(store_multiple_long)
|
|
{
|
|
int r1, r3; /* Register numbers */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
int i, d; /* Integer work areas */
|
|
BYTE rwork[128]; /* Register work areas */
|
|
|
|
RSE(inst, execflag, regs, r1, r3, b2, effective_addr2);
|
|
|
|
/* Copy control registers into work area */
|
|
for ( i = r1, d = 0; ; )
|
|
{
|
|
/* Copy contents of one control register to work area */
|
|
STORE_DW(rwork + d, regs->GR_G(i)); d += 8;
|
|
|
|
/* Instruction is complete when r3 register is done */
|
|
if ( i == r3 ) break;
|
|
|
|
/* Update register number, wrapping from 15 to 0 */
|
|
i++; i &= 15;
|
|
}
|
|
|
|
/* Store control register contents at operand address */
|
|
ARCH_DEP(vstorec) ( rwork, d-1, effective_addr2, b2, regs );
|
|
|
|
} /* end DEF_INST(store_multiple_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* EB26 STMH - Store Multiple High [RSE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(store_multiple_high)
|
|
{
|
|
int r1, r3; /* Register numbers */
|
|
int b2; /* effective address base */
|
|
VADR effective_addr2; /* effective address */
|
|
int i, d; /* Integer work area */
|
|
BYTE rwork[64]; /* Register work area */
|
|
|
|
RSE(inst, execflag, regs, r1, r3, b2, effective_addr2);
|
|
|
|
/* Copy register contents into work area */
|
|
for ( i = r1, d = 0; ; )
|
|
{
|
|
/* Copy contents of one register to work area */
|
|
STORE_FW(rwork + d, regs->GR_H(i)); d += 4;
|
|
|
|
/* Instruction is complete when r3 register is done */
|
|
if ( i == r3 ) break;
|
|
|
|
/* Update register number, wrapping from 15 to 0 */
|
|
i++; i &= 15;
|
|
}
|
|
|
|
/* Store register contents at operand address */
|
|
ARCH_DEP(vstorec) ( rwork, d-1, effective_addr2, b2, regs );
|
|
|
|
} /* end DEF_INST(store_multiple_high) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B905 LURAG - Load Using Real Address Long [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_using_real_address_long)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
RADR n; /* Unsigned work */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
PRIV_CHECK(regs);
|
|
|
|
/* R2 register contains operand real storage address */
|
|
n = regs->GR_G(r2) & ADDRESS_MAXWRAP(regs);
|
|
|
|
/* Program check if operand not on doubleword boundary */
|
|
DW_CHECK(n, regs);
|
|
|
|
/* Load R1 register from second operand */
|
|
regs->GR_G(r1) = ARCH_DEP(vfetch8) ( n, USE_REAL_ADDR, regs );
|
|
|
|
} /* end DEF_INST(load_using_real_address_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B925 STURG - Store Using Real Address Long [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(store_using_real_address_long)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
RADR n; /* Unsigned work */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
PRIV_CHECK(regs);
|
|
|
|
/* R2 register contains operand real storage address */
|
|
n = regs->GR_G(r2) & ADDRESS_MAXWRAP(regs);
|
|
|
|
/* Program check if operand not on doubleword boundary */
|
|
DW_CHECK(n, regs);
|
|
|
|
/* Store R1 register at second operand location */
|
|
ARCH_DEP(vstore8) (regs->GR_G(r1), n, USE_REAL_ADDR, regs );
|
|
|
|
#if defined(FEATURE_PER2)
|
|
/* Storage alteration must be enabled for STURA to be recognised */
|
|
if( EN_IC_PER_SA(regs) && EN_IC_PER_STURA(regs) )
|
|
{
|
|
ON_IC_PER_SA(regs) ;
|
|
ON_IC_PER_STURA(regs) ;
|
|
}
|
|
#endif /*defined(FEATURE_PER2)*/
|
|
|
|
} /* end DEF_INST(store_using_real_address_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* 010B TAM - Test Addressing Mode [E] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(test_addressing_mode)
|
|
{
|
|
E(inst, execflag, regs);
|
|
|
|
regs->psw.cc =
|
|
#if defined(FEATURE_ESAME)
|
|
(regs->psw.amode64 << 1) |
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
regs->psw.amode;
|
|
|
|
} /* end DEF_INST(test_addressing_mode) */
|
|
#endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* 010C SAM24 - Set Addressing Mode 24 [E] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(set_addressing_mode_24)
|
|
{
|
|
VADR ia = regs->psw.IA; /* Unupdated instruction addr*/
|
|
|
|
E(inst, execflag, regs);
|
|
|
|
/* Program check if instruction is located above 16MB */
|
|
if (ia > 0xFFFFFFULL)
|
|
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/* Add a mode trace entry when switching in/out of 64 bit mode */
|
|
if((regs->CR(12) & CR12_MTRACE) && regs->psw.amode64)
|
|
ARCH_DEP(trace_ms) (0, regs->psw.IA, regs);
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
regs->psw.amode64 =
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
regs->psw.amode = 0;
|
|
regs->psw.AMASK = AMASK24;
|
|
|
|
} /* end DEF_INST(set_addressing_mode_24) */
|
|
#endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* 010D SAM31 - Set Addressing Mode 31 [E] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(set_addressing_mode_31)
|
|
{
|
|
VADR ia = regs->psw.IA; /* Unupdated instruction addr*/
|
|
|
|
E(inst, execflag, regs);
|
|
|
|
/* Program check if instruction is located above 2GB */
|
|
if (ia > 0x7FFFFFFFULL)
|
|
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/* Add a mode trace entry when switching in/out of 64 bit mode */
|
|
if((regs->CR(12) & CR12_MTRACE) && regs->psw.amode64)
|
|
ARCH_DEP(trace_ms) (0, regs->psw.IA, regs);
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
regs->psw.amode64 = 0;
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
regs->psw.amode = 1;
|
|
regs->psw.AMASK = AMASK31;
|
|
|
|
} /* end DEF_INST(set_addressing_mode_31) */
|
|
#endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* 010E SAM64 - Set Addressing Mode 64 [E] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(set_addressing_mode_64)
|
|
{
|
|
E(inst, execflag, regs);
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/* Add a mode trace entry when switching in/out of 64 bit mode */
|
|
if((regs->CR(12) & CR12_MTRACE) && !regs->psw.amode64)
|
|
ARCH_DEP(trace_ms) (0, regs->psw.IA, regs);
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
regs->psw.amode = regs->psw.amode64 = 1;
|
|
regs->psw.AMASK = AMASK64;
|
|
|
|
} /* end DEF_INST(set_addressing_mode_64) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E324 STG - Store Long [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(store_long)
|
|
{
|
|
int r1; /* Values of R fields */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Store register contents at operand address */
|
|
ARCH_DEP(vstore8) ( regs->GR_G(r1), effective_addr2, b2, regs );
|
|
|
|
} /* end DEF_INST(store_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E502 STRAG - Store Real Address [SSE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(store_real_address)
|
|
{
|
|
int b1, b2; /* Values of base registers */
|
|
VADR effective_addr1,
|
|
effective_addr2; /* Effective addresses */
|
|
U16 xcode; /* Exception code */
|
|
int private; /* 1=Private address space */
|
|
int protect; /* 1=ALE or page protection */
|
|
int stid; /* Segment table indication */
|
|
RADR n; /* 64-bit operand values */
|
|
|
|
SSE(inst, execflag, regs, b1, effective_addr1, b2, effective_addr2);
|
|
|
|
PRIV_CHECK(regs);
|
|
|
|
DW_CHECK(effective_addr1, regs);
|
|
|
|
/* Translate virtual address to real address */
|
|
if (ARCH_DEP(translate_addr) (effective_addr2, b2, regs, ACCTYPE_STRAG,
|
|
&n, &xcode, &private, &protect, &stid))
|
|
ARCH_DEP(program_interrupt) (regs, xcode);
|
|
|
|
/* Store register contents at operand address */
|
|
ARCH_DEP(vstore8) ( n, effective_addr1, b1, regs );
|
|
|
|
} /* end DEF_INST(store_real_address) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E304 LG - Load Long [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_long)
|
|
{
|
|
int r1; /* Value of R field */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Load R1 register from second operand */
|
|
regs->GR_G(r1) = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs );
|
|
|
|
} /* end DEF_INST(load_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E314 LGF - Load Long Fullword [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_long_fullword)
|
|
{
|
|
int r1; /* Value of R field */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Load R1 register from second operand */
|
|
(S64)regs->GR_G(r1) = (S32)ARCH_DEP(vfetch4) ( effective_addr2, b2, regs );
|
|
|
|
} /* end DEF_INST(load_long_fullword) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E315 LGH - Load Long Halfword [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_long_halfword)
|
|
{
|
|
int r1; /* Value of R field */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Load R1 register from second operand */
|
|
(S64)regs->GR_G(r1) = (S16)ARCH_DEP(vfetch2) ( effective_addr2, b2, regs );
|
|
|
|
} /* end DEF_INST(load_long_halfword) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E316 LLGF - Load Logical Long Fullword [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_logical_long_fullword)
|
|
{
|
|
int r1; /* Value of R field */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Load R1 register from second operand */
|
|
regs->GR_G(r1) = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs );
|
|
|
|
} /* end DEF_INST(load_logical_long_fullword) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E317 LLGT - Load Logical Long Thirtyone [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_logical_long_thirtyone)
|
|
{
|
|
int r1; /* Value of R field */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Load R1 register from second operand */
|
|
regs->GR_G(r1) = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs )
|
|
& 0x7FFFFFFF;
|
|
|
|
} /* end DEF_INST(load_logical_long_thirtyone) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B2B2 LPSWE - Load PSW Extended [S] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_program_status_word_extended)
|
|
{
|
|
int b2; /* Base of effective addr */
|
|
U64 effective_addr2; /* Effective address */
|
|
QWORD qword;
|
|
int rc;
|
|
|
|
S(inst, execflag, regs, b2, effective_addr2);
|
|
|
|
PRIV_CHECK(regs);
|
|
|
|
DW_CHECK(effective_addr2, regs);
|
|
|
|
#if defined(_FEATURE_ZSIE)
|
|
if(regs->sie_state && (regs->siebk->ic[1] & SIE_IC1_LPSW))
|
|
longjmp(regs->progjmp, SIE_INTERCEPT_INST);
|
|
#endif /*defined(_FEATURE_ZSIE)*/
|
|
|
|
/* Perform serialization and checkpoint synchronization */
|
|
PERFORM_SERIALIZATION (regs);
|
|
PERFORM_CHKPT_SYNC (regs);
|
|
|
|
/* Fetch new PSW from operand address */
|
|
ARCH_DEP(vfetchc) ( qword, 16-1, effective_addr2, b2, regs );
|
|
|
|
/* Load updated PSW */
|
|
rc = ARCH_DEP(load_psw) ( regs, qword );
|
|
if ( rc )
|
|
ARCH_DEP(program_interrupt) (regs, rc);
|
|
|
|
/* load_psw() has set the ILC to zero. This needs to
|
|
be reset to 4 for an eventual PER event */
|
|
regs->psw.ilc = 4;
|
|
|
|
/* Perform serialization and checkpoint synchronization */
|
|
PERFORM_SERIALIZATION (regs);
|
|
PERFORM_CHKPT_SYNC (regs);
|
|
|
|
RETURN_INTCHECK(regs);
|
|
|
|
} /* end DEF_INST(load_program_status_word_extended) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E303 LRAG - Load Real Address Long [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_real_address_long)
|
|
{
|
|
int r1; /* Register number */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
U16 xcode; /* Exception code */
|
|
int private; /* 1=Private address space */
|
|
int protect; /* 1=ALE or page protection */
|
|
int stid; /* Segment table indication */
|
|
int cc; /* Condition code */
|
|
RADR n; /* 64-bit operand values */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
SIE_MODE_XC_OPEX(regs);
|
|
|
|
PRIV_CHECK(regs);
|
|
|
|
/* Translate the effective address to a real address */
|
|
cc = ARCH_DEP(translate_addr) (effective_addr2, b2, regs,
|
|
ACCTYPE_LRA, &n, &xcode, &private, &protect, &stid);
|
|
|
|
/* If ALET exception or ASCE-type or region translation
|
|
exception, or if the segment table entry is outside the
|
|
table and the entry address exceeds 2GB, set exception
|
|
code in R1 bits 48-63, set bit 32 of R1, and set cc 3 */
|
|
if (cc > 3
|
|
|| (cc == 3 && n > 0x7FFFFFFF))
|
|
{
|
|
regs->GR_L(r1) = 0x80000000 | xcode;
|
|
cc = 3;
|
|
}
|
|
else if (cc == 3) /* && n <= 0x7FFFFFFF */
|
|
{
|
|
/* If segment table entry is outside table and entry
|
|
address does not exceed 2GB, return bits 32-63 of
|
|
the entry address and leave bits 0-31 unchanged */
|
|
regs->GR_L(r1) = n;
|
|
}
|
|
else
|
|
{
|
|
/* Set R1 and condition code as returned by translate_addr */
|
|
regs->GR_G(r1) = n;
|
|
}
|
|
|
|
/* Set condition code */
|
|
regs->psw.cc = cc;
|
|
|
|
} /* end DEF_INST(load_real_address_long) */
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(_900) || defined(FEATURE_ESAME) || defined(FEATURE_ESAME_N3_ESA390)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B2B1 STFL - Store Facilities List [S] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(store_facilities_list)
|
|
{
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
PSA *psa; /* -> Prefixed storage area */
|
|
|
|
S(inst, execflag, regs, b2, effective_addr2);
|
|
|
|
PRIV_CHECK(regs);
|
|
|
|
SIE_INTERCEPT(regs);
|
|
|
|
/* Set the main storage reference and change bits */
|
|
STORAGE_KEY(regs->PX) |= (STORKEY_REF | STORKEY_CHANGE);
|
|
|
|
/* Point to PSA in main storage */
|
|
psa = (void*)(sysblk.mainstor + regs->PX);
|
|
|
|
psa->stfl[0] = 0
|
|
#if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)
|
|
| STFL_0_N3
|
|
#endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/
|
|
#if defined(_900) || defined(FEATURE_ESAME)
|
|
| (sysblk.arch_z900 ? STFL_0_ESAME_INSTALLED : 0)
|
|
#endif /*defined(_900) || defined(FEATURE_ESAME)*/
|
|
#if defined(FEATURE_ESAME)
|
|
| STFL_0_ESAME_ACTIVE
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
;
|
|
psa->stfl[1] = 0;
|
|
psa->stfl[2] = 0
|
|
#if defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2)
|
|
| STFL_2_TRAN_FAC2
|
|
#endif /*defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2)*/
|
|
;
|
|
psa->stfl[3] = 0;
|
|
|
|
} /* end DEF_INST(store_facilities_list) */
|
|
#endif /*defined(_900) || defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_LOAD_REVERSED) && defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B90F LRVGR - Load Reversed Long Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_reversed_long_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
/* Copy second operand to first operand */
|
|
regs->GR_G(r1) = bswap_64(regs->GR_G(r2));
|
|
|
|
} /* end DEF_INST(load_reversed_long_register) */
|
|
#endif /*defined(FEATURE_LOAD_REVERSED) && defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_LOAD_REVERSED)
|
|
/*-------------------------------------------------------------------*/
|
|
/* B91F LRVR - Load Reversed Register [RRE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_reversed_register)
|
|
{
|
|
int r1, r2; /* Values of R fields */
|
|
|
|
RRE(inst, execflag, regs, r1, r2);
|
|
|
|
/* Copy second operand to first operand */
|
|
regs->GR_L(r1) = bswap_32(regs->GR_L(r2));
|
|
|
|
} /* end DEF_INST(load_reversed_register) */
|
|
#endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_LOAD_REVERSED)*/
|
|
|
|
|
|
#if defined(FEATURE_LOAD_REVERSED) && defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E30F LRVG - Load Reversed Long [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_reversed_long)
|
|
{
|
|
int r1; /* Value of R field */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Load R1 register from second operand */
|
|
regs->GR_G(r1) = bswap_64(ARCH_DEP(vfetch8) ( effective_addr2, b2, regs ));
|
|
|
|
} /* end DEF_INST(load_reversed_long) */
|
|
#endif /*defined(FEATURE_LOAD_REVERSED) && defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_LOAD_REVERSED)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E31E LRV - Load Reversed [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_reversed)
|
|
{
|
|
int r1; /* Value of R field */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Load R1 register from second operand */
|
|
regs->GR_L(r1) = bswap_32(ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ));
|
|
|
|
} /* end DEF_INST(load_reversed) */
|
|
#endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_LOAD_REVERSED)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_LOAD_REVERSED)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E31F LRVH - Load Reversed Half [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(load_reversed_half)
|
|
{
|
|
int r1; /* Value of R field */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Load R1 register from second operand */
|
|
regs->GR_LHL(r1) = bswap_16(ARCH_DEP(vfetch2) ( effective_addr2, b2, regs ));
|
|
} /* end DEF_INST(load_reversed_half) */
|
|
#endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_LOAD_REVERSED)*/
|
|
|
|
|
|
#if defined(FEATURE_LOAD_REVERSED) && defined(FEATURE_ESAME)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E32F STRVG - Store Reversed Long [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(store_reversed_long)
|
|
{
|
|
int r1; /* Values of R fields */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Store register contents at operand address */
|
|
ARCH_DEP(vstore8) ( bswap_64(regs->GR_G(r1)), effective_addr2, b2, regs );
|
|
|
|
} /* end DEF_INST(store_reversed_long) */
|
|
#endif /*defined(FEATURE_LOAD_REVERSED) && defined(FEATURE_ESAME)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_LOAD_REVERSED)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E33E STRV - Store Reversed [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(store_reversed)
|
|
{
|
|
int r1; /* Values of R fields */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Store register contents at operand address */
|
|
ARCH_DEP(vstore4) ( bswap_32(regs->GR_L(r1)), effective_addr2, b2, regs );
|
|
|
|
} /* end DEF_INST(store_reversed) */
|
|
#endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_LOAD_REVERSED)*/
|
|
|
|
|
|
#if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_LOAD_REVERSED)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E33F STRVH - Store Reversed Half [RXE] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(store_reversed_half)
|
|
{
|
|
int r1; /* Values of R fields */
|
|
int b2; /* Base of effective addr */
|
|
VADR effective_addr2; /* Effective address */
|
|
|
|
RXE(inst, execflag, regs, r1, b2, effective_addr2);
|
|
|
|
/* Store register contents at operand address */
|
|
ARCH_DEP(vstore2) ( bswap_16(regs->GR_LHL(r1)), effective_addr2, b2, regs );
|
|
|
|
} /* end DEF_INST(store_reversed_half) */
|
|
#endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_LOAD_REVERSED)*/
|
|
|
|
|
|
#if defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E9 PKA - Pack ASCII [SS] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(pack_ascii)
|
|
{
|
|
int len; /* Second operand length */
|
|
int b1, b2; /* Base registers */
|
|
VADR addr1, addr2; /* Effective addresses */
|
|
BYTE source[33]; /* 32 digits + implied sign */
|
|
BYTE result[16]; /* 31-digit packed result */
|
|
int i, j; /* Array subscripts */
|
|
|
|
SS_L(inst, execflag, regs, len, b1, addr1, b2, addr2);
|
|
|
|
/* Program check if operand length (len+1) exceeds 32 bytes */
|
|
if (len > 31)
|
|
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
|
|
|
|
/* Fetch the second operand and right justify */
|
|
memset (source, 0, sizeof(source));
|
|
ARCH_DEP(vfetchc) ( source+31-len, len, addr2, b2, regs );
|
|
|
|
/* Append an implied plus sign */
|
|
source[32] = 0x0C;
|
|
|
|
/* Pack the rightmost 31 digits and sign into the result */
|
|
for (i = 1, j = 0; j < 16; i += 2, j++)
|
|
{
|
|
result[j] = (source[i] << 4) | (source[i+1] & 0x0F);
|
|
}
|
|
|
|
/* Store 16-byte packed decimal result at operand address */
|
|
ARCH_DEP(vstorec) ( result, 16-1, addr1, b1, regs );
|
|
|
|
} /* end DEF_INST(pack_ascii) */
|
|
#endif /*defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2)*/
|
|
|
|
|
|
#if defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E1 PKU - Pack Unicode [SS] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(pack_unicode)
|
|
{
|
|
int len; /* Second operand length */
|
|
int b1, b2; /* Base registers */
|
|
VADR addr1, addr2; /* Effective addresses */
|
|
BYTE source[66]; /* 32 digits + implied sign */
|
|
BYTE result[16]; /* 31-digit packed result */
|
|
int i, j; /* Array subscripts */
|
|
|
|
SS_L(inst, execflag, regs, len, b1, addr1, b2, addr2);
|
|
|
|
/* Program check if byte count (len+1) exceeds 64 or is odd */
|
|
if (len > 63 || (len & 1) == 0)
|
|
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
|
|
|
|
/* Fetch the second operand and right justify */
|
|
memset (source, 0, sizeof(source));
|
|
ARCH_DEP(vfetchc) ( source+63-len, len, addr2, b2, regs );
|
|
|
|
/* Append an implied plus sign */
|
|
source[64] = 0x00;
|
|
source[65] = 0x0C;
|
|
|
|
/* Pack the rightmost 31 digits and sign into the result */
|
|
for (i = 2, j = 0; j < 16; i += 4, j++)
|
|
{
|
|
result[j] = (source[i+1] << 4) | (source[i+3] & 0x0F);
|
|
}
|
|
|
|
/* Store 16-byte packed decimal result at operand address */
|
|
ARCH_DEP(vstorec) ( result, 16-1, addr1, b1, regs );
|
|
|
|
} /* end DEF_INST(pack_unicode) */
|
|
#endif /*defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2)*/
|
|
|
|
|
|
#if defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2)
|
|
/*-------------------------------------------------------------------*/
|
|
/* EA UNPKA - Unpack ASCII [SS] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(unpack_ascii)
|
|
{
|
|
int len; /* First operand length */
|
|
int b1, b2; /* Base registers */
|
|
VADR addr1, addr2; /* Effective addresses */
|
|
BYTE result[32]; /* 32-digit result */
|
|
BYTE source[16]; /* 31-digit packed operand */
|
|
int i, j; /* Array subscripts */
|
|
int cc; /* Condition code */
|
|
|
|
SS_L(inst, execflag, regs, len, b1, addr1, b2, addr2);
|
|
|
|
/* Program check if operand length (len+1) exceeds 32 bytes */
|
|
if (len > 31)
|
|
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
|
|
|
|
/* Fetch the 16-byte second operand */
|
|
ARCH_DEP(vfetchc) ( source, 15, addr2, b2, regs );
|
|
|
|
/* Set high-order result byte to ASCII zero */
|
|
result[0] = 0x30;
|
|
|
|
/* Unpack remaining 31 digits into the result */
|
|
for (j = 1, i = 0; ; i++)
|
|
{
|
|
result[j++] = (source[i] >> 4) | 0x30;
|
|
if (i == 15) break;
|
|
result[j++] = (source[i] & 0x0F) | 0x30;
|
|
}
|
|
|
|
/* Store rightmost digits of result at first operand address */
|
|
ARCH_DEP(vstorec) ( result+31-len, len, addr1, b1, regs );
|
|
|
|
/* Set the condition code according to the sign */
|
|
switch (source[15] & 0x0F) {
|
|
case 0x0A: case 0x0C: case 0x0E: case 0x0F:
|
|
cc = 0; break;
|
|
case 0x0B: case 0x0D:
|
|
cc = 1; break;
|
|
default:
|
|
cc = 3;
|
|
} /* end switch */
|
|
regs->psw.cc = cc;
|
|
|
|
} /* end DEF_INST(unpack_ascii) */
|
|
#endif /*defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2)*/
|
|
|
|
|
|
#if defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2)
|
|
/*-------------------------------------------------------------------*/
|
|
/* E2 UNPKU - Unpack Unicode [SS] */
|
|
/*-------------------------------------------------------------------*/
|
|
DEF_INST(unpack_unicode)
|
|
{
|
|
int len; /* First operand length */
|
|
int b1, b2; /* Base registers */
|
|
VADR addr1, addr2; /* Effective addresses */
|
|
BYTE result[64]; /* 32-digit result */
|
|
BYTE source[16]; /* 31-digit packed operand */
|
|
int i, j; /* Array subscripts */
|
|
int cc; /* Condition code */
|
|
|
|
SS_L(inst, execflag, regs, len, b1, addr1, b2, addr2);
|
|
|
|
/* Program check if byte count (len+1) exceeds 64 or is odd */
|
|
if (len > 63 || (len & 1) == 0)
|
|
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
|
|
|
|
/* Fetch the 16-byte second operand */
|
|
ARCH_DEP(vfetchc) ( source, 15, addr2, b2, regs );
|
|
|
|
/* Set high-order result pair to Unicode zero */
|
|
result[0] = 0x00;
|
|
result[1] = 0x30;
|
|
|
|
/* Unpack remaining 31 digits into the result */
|
|
for (j = 2, i = 0; ; i++)
|
|
{
|
|
result[j++] = 0x00;
|
|
result[j++] = (source[i] >> 4) | 0x30;
|
|
if (i == 15) break;
|
|
result[j++] = 0x00;
|
|
result[j++] = (source[i] & 0x0F) | 0x30;
|
|
}
|
|
|
|
/* Store rightmost digits of result at first operand address */
|
|
ARCH_DEP(vstorec) ( result+63-len, len, addr1, b1, regs );
|
|
|
|
/* Set the condition code according to the sign */
|
|
switch (source[15] & 0x0F) {
|
|
case 0x0A: case 0x0C: case 0x0E: case 0x0F:
|
|
cc = 0; break;
|
|
case 0x0B: case 0x0D:
|
|
cc = 1; break;
|
|
default:
|
|
cc = 3;
|
|
} /* end switch */
|
|
regs->psw.cc = cc;
|
|
|
|
} /* end DEF_INST(unpack_unicode) */
|
|
#endif /*defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2)*/
|
|
|
|
|
|
#if !defined(_GEN_ARCH)
|
|
|
|
#if defined(_ARCHMODE2)
|
|
#define _GEN_ARCH _ARCHMODE2
|
|
#include "esame.c"
|
|
#endif
|
|
|
|
#if defined(_ARCHMODE3)
|
|
#undef _GEN_ARCH
|
|
#define _GEN_ARCH _ARCHMODE3
|
|
#include "esame.c"
|
|
#endif
|
|
|
|
|
|
#endif /*!defined(_GEN_ARCH)*/
|