Fix and optimize TR instruction

git-svn-id: file:///home/jj/hercules.svn/trunk@4546 956126f8-22a0-4046-8f4a-272fa8102e63
This commit is contained in:
Greg Smith
2008-01-24 00:59:03 +00:00
parent 8ccb5880ca
commit 71b5b2c94a
2 changed files with 62 additions and 44 deletions

View File

@@ -1,3 +1,4 @@
23 Jan 2008 Fix and optimize TR instruction - Greg
23 Jan 2008 Modifications for VS9 C++ 2008 Express by Charlie Brint - Roger Bowler
21 Jan 2008 Activate ETF3 and ETF2/ETF3-Enhancements in ESA/390 mode - Roger Bowler
21 Jan 2008 Permit Extended-Translation-Facility-3 to be activated in S/370 and ESA/390 modes - Roger Bowler

View File

@@ -32,6 +32,9 @@
/*-------------------------------------------------------------------*/
// $Log$
// Revision 1.117 2007/12/30 17:48:21 bernard
// Anoter UTF xlate error
//
// Revision 1.116 2007/12/30 09:09:51 bernard
// Some errors in UTF translation
//
@@ -1563,60 +1566,74 @@ U16 h2; /* 16-bit operand values */
/*-------------------------------------------------------------------*/
DEF_INST(translate)
{
int l; /* Lenght byte */
int len, len2 = -1; /* Lengths */
int b1, b2; /* Values of base field */
VADR effective_addr1,
effective_addr2; /* Effective address */
U32 n; /* 32-bit operand values */
BYTE sbyte; /* Byte work areas */
int d; /* Integer work areas */
int h; /* Integer work areas */
int i; /* Integer work areas */
BYTE cwork[256]; /* Character work areas */
int i, b, n; /* Work variables */
VADR addr1, addr2; /* Effective addresses */
BYTE *dest, *dest2 = NULL, *tab, *tab2; /* Mainstor pointers */
SS_L(inst, regs, l, b1, effective_addr1,
b2, effective_addr2);
SS_L(inst, regs, len, b1, addr1, b2, addr2);
/* If operand 1 crosses a page, make sure both pages are accessable */
if((effective_addr1 & PAGEFRAME_PAGEMASK) !=
((effective_addr1 + l) & PAGEFRAME_PAGEMASK))
ARCH_DEP(validate_operand) (effective_addr1, b1, l, ACCTYPE_WRITE_SKP, regs);
/* Get destination pointer */
dest = MADDR (addr1, b1, regs, ACCTYPE_WRITE, regs->psw.pkey);
/* Fetch first operand into work area */
ARCH_DEP(vfetchc) ( cwork, l, effective_addr1, b1, regs );
/* Determine the second operand range by scanning the
first operand to find the bytes with the highest
and lowest values */
for ( i = 0, d = 255, h = 0; i <= l; i++ )
/* Get pointer to next page if destination crosses a boundary */
if (CROSS2K (addr1, len))
{
if (cwork[i] < d) d = cwork[i];
if (cwork[i] > h) h = cwork[i];
len2 = len;
len = 0x7FF - (addr1 & 0x7FF);
len2 -= (len + 1);
dest2 = MADDR ((addr1+len+1) & ADDRESS_MAXWRAP(regs),
b1, regs, ACCTYPE_WRITE, regs->psw.pkey);
}
n = (effective_addr2 + d) & ADDRESS_MAXWRAP(regs);
/* If operand 2 crosses a page, make sure both pages are accessable */
if((n & PAGEFRAME_PAGEMASK) !=
((n + (h-d)) & PAGEFRAME_PAGEMASK))
ARCH_DEP(validate_operand) (n, b2, h-d, ACCTYPE_READ, regs);
/* Process first operand from left to right, refetching
second operand and storing the result byte by byte
to ensure correct handling of overlapping operands */
for ( i = 0; i <= l; i++ )
/* Fast path if table does not cross a boundary */
if (NOCROSS2K (addr2, 255))
{
/* Fetch byte from second operand */
n = (effective_addr2 + cwork[i]) & ADDRESS_MAXWRAP(regs);
sbyte = ARCH_DEP(vfetchb) ( n, b2, regs );
tab = MADDR (addr2, b2, regs, ACCTYPE_READ, regs->psw.pkey);
/* Perform translate function */
for (i = 0; i <= len; i++)
dest[i] = tab[dest[i]];
for (i = 0; i <= len2; i++)
dest2[i] = tab[dest2[i]];
}
else
{
n = 0x800 - (addr2 & 0x7FF);
b = dest[0];
/* Store result at first operand address */
ARCH_DEP(vstoreb) ( sbyte, effective_addr1, b1, regs );
/* Referenced part of the table may or may not span boundary */
if (b < n)
{
tab = MADDR (addr2, b2, regs, ACCTYPE_READ, regs->psw.pkey);
for (i = 1; i <= len && b < n; i++)
b = dest[i];
for (i = 0; i <= len2 && b < n; i++)
b = dest2[i];
tab2 = b < n
? NULL
: MADDR ((addr2+n) & ADDRESS_MAXWRAP(regs),
b2, regs, ACCTYPE_READ, regs->psw.pkey);
}
else
{
tab2 = MADDR ((addr2+n) & ADDRESS_MAXWRAP(regs),
b2, regs, ACCTYPE_READ, regs->psw.pkey);
for (i = 1; i <= len && b >= n; i++)
b = dest[i];
for (i = 0; i <= len2 && b >= n; i++)
b = dest2[i];
tab = b >= n
? NULL
: MADDR (addr2, b2, regs, ACCTYPE_READ, regs->psw.pkey);
}
/* Increment first operand address */
effective_addr1++;
effective_addr1 &= ADDRESS_MAXWRAP(regs);
} /* end for(i) */
/* Perform translate function */
for (i = 0; i <= len; i++)
dest[i] = dest[i] < n ? tab[dest[i]] : tab2[dest[i]-n];
for (i = 0; i <= len2; i++)
dest2[i] = dest2[i] < n ? tab[dest2[i]] : tab2[dest2[i]-n];
} /* Translate table spans a boundary */
}