kerravon86@yahoo.com.au [hercules-390]
2017-10-03 09:48:17 UTC
I posted this about 3 hours ago, and it
still hasn't shown up, so here's a possible
duplicate ...
Hi. I'm having a problem with MVCLE.
This is the first time I've ever used it,
so it could be "operator error".
Here is the instruction:
MVCLE R8,R12,0(R13)
But due to possible macro error, it is possible
the instruction itself is wrong. Here is
the expansion:
DC 0H'0',X'A8',AL.4(R8,R12),SL2(0(R13))
which becomes:
A88CD000
Here are the registers before execution:
8 0000000002000000 9 0000000004000000
C 0000000002000000 D 0000000000000000
And here are the registers after:
8 0000000002001000 9 0000000003FFF000
C 0000000002000000 D 0000000000000000
The memory address I am interested
in is not being cleared:
r 2001000 R:02001000:K:00=02001000 00000000 00000000 00000000
but other memory, such as this:
r 2000000 R:02000000:K:00=00000000 00000000 00000000 00000000
is being cleared (I deliberately set the
first word to non-zero and it got cleared).
I am using a slightly modified Hercules 3.07,
so I first checked the source code to make
sure I hadn't modified something.
I did not see any changes from me, but I
did see this code which looked suspicious:
/* set cpu_length as shortest distance to new page */
if ((addr1 & 0xFFF) > (addr2 & 0xFFF))
cpu_length = 0x1000 - (addr1 & 0xFFF);
else
cpu_length = 0x1000 - (addr2 & 0xFFF);
dstlen=MIN(cpu_length,len1);
srclen=MIN(cpu_length,len2);
copylen=MIN(dstlen,srclen);
(you can see the full 3.07 code below).
The above code seems to truncate the
lengths to a maximum of 4096, which
is what I am seeing.
Further down I see this comment:
/* Adjust length & pointers for this cycle */
dest+=copylen;
dstlen-=copylen;
srclen-=copylen;
But I see no "cycles". ie there is no
"while" loop.
Is the cycle perhaps being done outside
of the MVCLE instruction itself, ie MVCLE
is an interruptable instruction or something
like that? If that is the case, it could well
be one of my modifications that is causing
the fault, but I'd like some hints as to which
one.
Anyway, I did a diff to the 3.13 code, and
see no change in that area:
C:\devel\hercules>diff -w 307.txt 313.txt
54c54
< dest = MADDR (addr1, r1, regs, ACCTYPE_WRITE, regs->psw.pkey);
---
remained undetected for a very long
time.
Could someone desk-check all the
above please? Or give me some
further tests to try?
Thanks. Paul.
/*-------------------------------------------------------------------*/
/* A8 MVCLE - Move Long Extended [RS] */
/*-------------------------------------------------------------------*/
DEF_INST(move_long_extended)
{
int r1, r3; /* Register numbers */
int b2; /* effective address base */
VADR effective_addr2; /* effective address */
int cc; /* Condition code */
VADR addr1, addr2; /* Operand addresses */
GREG len1, len2; /* Operand lengths */
BYTE pad; /* Padding byte */
size_t cpu_length; /* cpu determined length */
size_t copylen; /* Length to copy */
BYTE *dest; /* Maint storage pointers */
size_t dstlen,srclen; /* Page wide src/dst lengths */
RS(inst, regs, r1, r3, b2, effective_addr2);
ODD2_CHECK(r1, r3, regs);
/* Load padding byte from bits 24-31 of effective address */
pad = effective_addr2 & 0xFF;
/* Determine the destination and source addresses */
addr1 = regs->GR(r1) & ADDRESS_MAXWRAP(regs);
addr2 = regs->GR(r3) & ADDRESS_MAXWRAP(regs);
/* Load operand lengths from bits 0-31 of R1+1 and R3+1 */
len1 = GR_A(r1+1, regs);
len2 = GR_A(r3+1, regs);
/* set cpu_length as shortest distance to new page */
if ((addr1 & 0xFFF) > (addr2 & 0xFFF))
cpu_length = 0x1000 - (addr1 & 0xFFF);
else
cpu_length = 0x1000 - (addr2 & 0xFFF);
dstlen=MIN(cpu_length,len1);
srclen=MIN(cpu_length,len2);
copylen=MIN(dstlen,srclen);
/* Set the condition code according to the lengths */
cc = (len1 < len2) ? 1 : (len1 > len2) ? 2 : 0;
/* Obtain destination pointer */
if(len1==0)
{
/* bail out if nothing to do */
regs->psw.cc = cc;
return;
}
dest = MADDR (addr1, r1, regs, ACCTYPE_WRITE, regs->psw.pkey);
if(copylen!=0)
{
/* here if we need to copy data */
BYTE *source;
/* get source frame and copy concurrently */
source = MADDR (addr2, r3, regs, ACCTYPE_READ, regs->psw.pkey);
concpy(regs,dest,source,copylen);
/* Adjust operands */
addr2+=copylen;
len2-=copylen;
addr1+=copylen;
len1-=copylen;
/* Adjust length & pointers for this cycle */
dest+=copylen;
dstlen-=copylen;
srclen-=copylen;
}
if(srclen==0 && dstlen!=0)
{
/* here if we need to pad the destination */
memset(dest,pad,dstlen);
/* Adjust destination operands */
addr1+=dstlen;
len1-=dstlen;
}
/* Update the registers */
SET_GR_A(r1, regs,addr1);
SET_GR_A(r1+1, regs,len1);
SET_GR_A(r3, regs,addr2);
SET_GR_A(r3+1, regs,len2);
/* if len1 != 0 then set CC to 3 to indicate
we have reached end of CPU dependent length */
if(len1>0) cc=3;
regs->psw.cc = cc;
}
still hasn't shown up, so here's a possible
duplicate ...
Hi. I'm having a problem with MVCLE.
This is the first time I've ever used it,
so it could be "operator error".
Here is the instruction:
MVCLE R8,R12,0(R13)
But due to possible macro error, it is possible
the instruction itself is wrong. Here is
the expansion:
DC 0H'0',X'A8',AL.4(R8,R12),SL2(0(R13))
which becomes:
A88CD000
Here are the registers before execution:
8 0000000002000000 9 0000000004000000
C 0000000002000000 D 0000000000000000
And here are the registers after:
8 0000000002001000 9 0000000003FFF000
C 0000000002000000 D 0000000000000000
The memory address I am interested
in is not being cleared:
r 2001000 R:02001000:K:00=02001000 00000000 00000000 00000000
but other memory, such as this:
r 2000000 R:02000000:K:00=00000000 00000000 00000000 00000000
is being cleared (I deliberately set the
first word to non-zero and it got cleared).
I am using a slightly modified Hercules 3.07,
so I first checked the source code to make
sure I hadn't modified something.
I did not see any changes from me, but I
did see this code which looked suspicious:
/* set cpu_length as shortest distance to new page */
if ((addr1 & 0xFFF) > (addr2 & 0xFFF))
cpu_length = 0x1000 - (addr1 & 0xFFF);
else
cpu_length = 0x1000 - (addr2 & 0xFFF);
dstlen=MIN(cpu_length,len1);
srclen=MIN(cpu_length,len2);
copylen=MIN(dstlen,srclen);
(you can see the full 3.07 code below).
The above code seems to truncate the
lengths to a maximum of 4096, which
is what I am seeing.
Further down I see this comment:
/* Adjust length & pointers for this cycle */
dest+=copylen;
dstlen-=copylen;
srclen-=copylen;
But I see no "cycles". ie there is no
"while" loop.
Is the cycle perhaps being done outside
of the MVCLE instruction itself, ie MVCLE
is an interruptable instruction or something
like that? If that is the case, it could well
be one of my modifications that is causing
the fault, but I'd like some hints as to which
one.
Anyway, I did a diff to the 3.13 code, and
see no change in that area:
C:\devel\hercules>diff -w 307.txt 313.txt
54c54
< dest = MADDR (addr1, r1, regs, ACCTYPE_WRITE, regs->psw.pkey);
---
dest = MADDRL (addr1, len1, r1, regs, ACCTYPE_WRITE, regs->psw.pkey);
So if it is indeed a Hercules bug, it hasremained undetected for a very long
time.
Could someone desk-check all the
above please? Or give me some
further tests to try?
Thanks. Paul.
/*-------------------------------------------------------------------*/
/* A8 MVCLE - Move Long Extended [RS] */
/*-------------------------------------------------------------------*/
DEF_INST(move_long_extended)
{
int r1, r3; /* Register numbers */
int b2; /* effective address base */
VADR effective_addr2; /* effective address */
int cc; /* Condition code */
VADR addr1, addr2; /* Operand addresses */
GREG len1, len2; /* Operand lengths */
BYTE pad; /* Padding byte */
size_t cpu_length; /* cpu determined length */
size_t copylen; /* Length to copy */
BYTE *dest; /* Maint storage pointers */
size_t dstlen,srclen; /* Page wide src/dst lengths */
RS(inst, regs, r1, r3, b2, effective_addr2);
ODD2_CHECK(r1, r3, regs);
/* Load padding byte from bits 24-31 of effective address */
pad = effective_addr2 & 0xFF;
/* Determine the destination and source addresses */
addr1 = regs->GR(r1) & ADDRESS_MAXWRAP(regs);
addr2 = regs->GR(r3) & ADDRESS_MAXWRAP(regs);
/* Load operand lengths from bits 0-31 of R1+1 and R3+1 */
len1 = GR_A(r1+1, regs);
len2 = GR_A(r3+1, regs);
/* set cpu_length as shortest distance to new page */
if ((addr1 & 0xFFF) > (addr2 & 0xFFF))
cpu_length = 0x1000 - (addr1 & 0xFFF);
else
cpu_length = 0x1000 - (addr2 & 0xFFF);
dstlen=MIN(cpu_length,len1);
srclen=MIN(cpu_length,len2);
copylen=MIN(dstlen,srclen);
/* Set the condition code according to the lengths */
cc = (len1 < len2) ? 1 : (len1 > len2) ? 2 : 0;
/* Obtain destination pointer */
if(len1==0)
{
/* bail out if nothing to do */
regs->psw.cc = cc;
return;
}
dest = MADDR (addr1, r1, regs, ACCTYPE_WRITE, regs->psw.pkey);
if(copylen!=0)
{
/* here if we need to copy data */
BYTE *source;
/* get source frame and copy concurrently */
source = MADDR (addr2, r3, regs, ACCTYPE_READ, regs->psw.pkey);
concpy(regs,dest,source,copylen);
/* Adjust operands */
addr2+=copylen;
len2-=copylen;
addr1+=copylen;
len1-=copylen;
/* Adjust length & pointers for this cycle */
dest+=copylen;
dstlen-=copylen;
srclen-=copylen;
}
if(srclen==0 && dstlen!=0)
{
/* here if we need to pad the destination */
memset(dest,pad,dstlen);
/* Adjust destination operands */
addr1+=dstlen;
len1-=dstlen;
}
/* Update the registers */
SET_GR_A(r1, regs,addr1);
SET_GR_A(r1+1, regs,len1);
SET_GR_A(r3, regs,addr2);
SET_GR_A(r3+1, regs,len2);
/* if len1 != 0 then set CC to 3 to indicate
we have reached end of CPU dependent length */
if(len1>0) cc=3;
regs->psw.cc = cc;
}