1
0
mirror of https://github.com/rcornwell/sims.git synced 2026-01-20 09:54:47 +00:00

IBM360: Fixed decimal instructions and Edit Mark. Thanks to Marcus Watts's help.

This commit is contained in:
Richard Cornwell 2019-01-31 23:43:31 -05:00
parent 3b6ef4935c
commit d1b1cf56e5

View File

@ -117,7 +117,7 @@ uint32 execp_error; /* Translation error */
#define IRC_SIGNIF 0x000e /* Significance error */
#define IRC_FPDIV 0x000f /* Floating pointer divide */
#define IRC_SEG 0x0010 /* Segment translation */
#define IRC_PAGE 0x0011 /* Pagre translation */
#define IRC_PAGE 0x0011 /* Page translation */
#define AMASK 0x00ffffff /* Mask address bits */
#define MSIGN 0x80000000 /* Minus sign */
@ -346,10 +346,10 @@ void storepsw(uint32 addr, uint16 ircode) {
* Translate an address from virtual to physical.
*/
int TransAddr(uint32 va, uint32 *pa) {
uint32 seg;
uint32 page;
uint32 entry;
uint32 addr;
uint32 seg;
uint32 page;
uint32 entry;
uint32 addr;
/* Check address in range */
va &= AMASK;
@ -432,9 +432,9 @@ int TransAddr(uint32 va, uint32 *pa) {
* success.
*/
int ReadFull(uint32 addr, uint32 *data) {
uint32 temp;
int offset;
uint8 k;
uint32 temp;
int offset;
uint8 k;
/* Ignore high order bits */
addr &= AMASK;
@ -525,8 +525,8 @@ int ReadHalf(uint32 addr, uint32 *data) {
}
int WriteFull(uint32 addr, uint32 data) {
int offset;
uint8 k;
int offset;
uint8 k;
/* Ignore high order bits */
addr &= AMASK;
if (addr >= MEMSIZE) {
@ -614,9 +614,9 @@ int WriteFull(uint32 addr, uint32 data) {
}
int WriteByte(uint32 addr, uint32 data) {
uint32 mask;
uint8 k;
int offset;
uint32 mask;
uint8 k;
int offset;
/* Ignore high order bits */
addr &= AMASK;
@ -652,7 +652,7 @@ int WriteByte(uint32 addr, uint32 data) {
}
int WriteHalf(uint32 addr, uint32 data) {
uint32 mask;
uint32 mask;
uint8 k;
int offset;
int o;
@ -738,8 +738,10 @@ sim_instr(void)
uint32 addr2;
uint8 op;
uint8 fill;
uint8 digit;
uint8 reg;
uint8 reg1;
uint8 zone;
uint16 irq;
int e1, e2;
int temp, temp2;
@ -1904,19 +1906,19 @@ save_dbl:
break;
addr1--;
addr2--;
src2 = (flags & ASCII)? 0x50 : 0xf0;
zone = (flags & ASCII)? 0x50 : 0xf0;
while(reg != 0 && reg1 != 0) {
if (ReadByte(addr2, &dest))
goto supress;
addr2--;
reg--;
src1 = (dest & 0xf) | src2;
src1 = (dest & 0xf) | zone;
if (WriteByte(addr1, src1))
goto supress;
addr1--;
reg1--;
if (reg1 != 0) {
src1 = ((dest >> 4) & 0xf) | src2;
src1 = ((dest >> 4) & 0xf) | zone;
if (WriteByte(addr1, src1))
goto supress;
addr1--;
@ -1924,7 +1926,7 @@ save_dbl:
}
};
while(reg1 != 0) {
if (WriteByte(addr1, src2))
if (WriteByte(addr1, zone))
break;
addr1--;
reg1--;
@ -2036,56 +2038,83 @@ save_dbl:
case OP_EDMK:
if (ReadByte(addr1, &src1))
break;
fill = src1;
addr1++;
src2 = 0;
src1 = 1;
zone = (flags & ASCII) ? 0x50: 0xf0;
fill = digit = (uint8)src1;
temp = 0; /* Hold zero flag */
e2 = 0; /* Significance indicator */
e1 = 1; /* Need another source char */
cc = 0;
while(reg != 0) {
uint8 t;
uint32 temp;
if (ReadByte(addr1, &temp))
break;
t = temp;
if (src1) {
if (ReadByte(addr2, &dest))
break;
addr2--;
reg --;
}
if (t == 0x21) {
src2 = 1;
t = 0x20;
if (op == OP_EDMK)
regs[1] = addr1;
}
if (t == 0x20) {
if (src2 || (dest >> (4*src1)) & 0xf) {
t = (dest >> (4*src1)) & 0xf;
t |= (flags & ASCII)?0x5:0xf;
if (!src2) {
src2 = 1;
if (op == OP_EDMK)
regs[1] = addr1;
for (;;) {
uint8 t;
switch(digit) {
case 0x21: /* Signficance starter */
case 0x20: /* Digit selector */
/* If we have not run out of source, grab next pair */
if (e1) {
if (ReadByte(addr2, &src2))
break;
addr2++;
/* Check if valid */
if (src2 > 0xa0) {
storepsw(OPPSW, IRC_DATA);
goto supress;
}
if (t & 0xf)
cc = 2;
} else
t = fill;
if (WriteByte(addr1, t))
break;
} else if (t == 0x22) {
src2 = 0;
t = fill;
if (WriteByte(addr1, t))
break;
}
/* Split apart. */
t = (src2 >> 4) & 0xf;
e1 = !e1;
src2 = (src2 & 0xf) << 4; /* Prepare for next trip */
/* Doing Edit and have seperator */
if (op == OP_EDMK && !e2 && t) {
regs[1] &= 0xff000000;
regs[1] |= addr1 & AMASK;
}
/* Found none zero */
if (t)
temp = 2; /* Set positive */
/* Select digit or fill */
if (t || e2)
digit = zone | t;
else
digit = fill;
if (src1 == 0x21 || t)
e2 = 1;
/* If sign, update status */
if (!e1) { /* Check if found sign */
switch(src2) {
case 0xa0: /* Minus */
case 0xc0:
case 0xe0:
case 0xf0:
e2 = 0;
/* Fall through */
case 0xb0:
case 0xd0:
e1 = 1;
}
}
break;
case 0x22: /* Field separator */
e2 = 0;
digit = fill;
temp = 0; /* Set zero */
break;
default: /* Anything else */
if (!e2)
digit = fill;
}
addr1--;
if (WriteByte(addr1, digit))
break;
addr1++;
if (reg == 0)
break;
reg --;
src1 = !src1;
};
dest &= 0xf;
if (cc != 0 && (dest == 0xd || dest == 0xb))
if (ReadByte(addr1, &src1))
break;
digit = src1;
}
cc = temp;
if (e2 && cc == 2)
cc = 1;
break;
@ -2750,6 +2779,10 @@ int dec_load(uint8 *data, uint32 addr, uint len, int *sign)
data[j++] = t;
addr--;
}
// fprintf(stderr, "Load : ");
// for (i = 31; i >= 0; i--) {
// fprintf(stderr, "%x", data[i]);
// }
/* Check if sign valid and return it */
if (data[0] == 0xB || data[0] == 0xD)
*sign = 1;
@ -2757,6 +2790,7 @@ int dec_load(uint8 *data, uint32 addr, uint len, int *sign)
err = 1;
else
*sign = 0;
// fprintf(stderr, " s=%d l=%d\n\r", *sign, len);
if (err) {
storepsw(OPPSW, IRC_DATA);
return 1;
@ -2788,6 +2822,11 @@ int dec_store(uint8 *data, uint32 addr, uint len, int sign)
return 1;
addr--;
}
// fprintf(stderr, "Store: ");
// for (i = 31; i >= 0; i--) {
// fprintf(stderr, "%x", data[i]);
// }
// fprintf(stderr, "\n\r");
return 0;
}
@ -2820,7 +2859,9 @@ dec_add(int op, uint32 addr1, uint8 len1, uint32 addr2, uint8 len2)
if (dec_load(b, addr2, (int)len2, &sb))
return;
len = 2*(len+1);
if (op & 1)
sb = !sb;
len = 2*(len+1)+1;
/* On all but ZAP load first operand */
if ((op & 3) != 0) {
if (dec_load(a, addr1, (int)len1, &sa))
@ -2830,18 +2871,13 @@ dec_add(int op, uint32 addr1, uint8 len1, uint32 addr2, uint8 len2)
memset(a, 0, 32);
sa = 0;
}
if (op & 1) {
if (sa == sb)
addsub = 1;
} else {
if (sa != sb)
addsub = 1;
}
if (sa != sb)
addsub = 1;
cy = addsub;
zero = 1;
/* Add numbers together */
for (i = 1; i < len; i++) {
acc = a[i] + ((addsub)? (0x9 - b[i]):b[i]) + cy;
acc = b[i] + ((addsub)? (0x9 - a[i]):a[i]) + cy;
if (acc > 0x9)
acc += 0x6;
a[i] = acc & 0xf;
@ -2849,6 +2885,11 @@ dec_add(int op, uint32 addr1, uint8 len1, uint32 addr2, uint8 len2)
if ((acc & 0xf) != 0)
zero = 0;
}
// fprintf(stderr, "add: ");
// for (i = 31; i >= 0; i--) {
// fprintf(stderr, "%x", a[i]);
// }
// fprintf(stderr, " as=%d cy=%d z=%d\n\r", addsub, cy, zero);
if (cy) {
if (addsub)
sa = !sa;
@ -2857,7 +2898,7 @@ dec_add(int op, uint32 addr1, uint8 len1, uint32 addr2, uint8 len2)
} else {
if (addsub) {
/* We need to recomplent the result */
sa = !sa;
// sa = !sa;
cy = 1;
zero = 1;
for (i = 1; i < len; i++) {
@ -2871,12 +2912,17 @@ dec_add(int op, uint32 addr1, uint8 len1, uint32 addr2, uint8 len2)
}
}
}
// fprintf(stderr, "sum: ");
// for (i = 31; i >= 0; i--) {
// fprintf(stderr, "%x", a[i]);
// }
// fprintf(stderr, " as=%d cy=%d z=%d ov=%d\n\r", addsub, cy, zero,ov);
if (zero && !ov)
sa = 0;
cc = 0;
if (zero) /* Really not zero */
cc = (sa)? 2: 1;
if ((op & 3) == 1) {
if (!zero) /* Really not zero */
cc = (sa)? 1: 2;
if ((op & 3) != 1) {
if (!zero && !ov) {
/* Start at len1 and go to len2 and see if any non-zero digits */
for (i = (len1+1)*2; i < len; i++) {
@ -2909,7 +2955,7 @@ dec_mul(int op, uint32 addr1, uint8 len1, uint32 addr2, uint8 len2)
int len;
if (len2 > 7 || len2 >= len1) {
fprintf(stderr, "Spec DecMP len=%x len=%x\n\r", len1, len2);
//fprintf(stderr, "Spec DecMP len=%x len=%x\n\r", len1, len2);
storepsw(OPPSW, IRC_SPEC);
return;
}
@ -2921,7 +2967,7 @@ fprintf(stderr, "Spec DecMP len=%x len=%x\n\r", len1, len2);
len1 = (len1 + 1) * 2;
len2 = (len2 + 1) * 2;
/* Verify that we have len2 zeros at start of a */
for (i = len1; i > len2; i--) {
for (i = len1 - len2; i < len1; i++) {
if (a[i] != 0) {
storepsw(OPPSW, IRC_DATA);
return;
@ -2929,13 +2975,14 @@ fprintf(stderr, "Spec DecMP len=%x len=%x\n\r", len1, len2);
}
sa ^= sb; /* Compute sign */
/* Start at end and work backwards */
for (j = len2; j > 1; j--) {
for (j = len1-len2; j > 0; j--) {
mul = a[j];
a[j] = 0;
// fprintf(stderr, "add m=%d %d: ", mul, j);
while(mul != 0) {
/* Add numbers together */
/* Add multiplier to multiplican */
cy = 0;
for (i = j, k = 1; i <= len1; i++, k--) {
for (i = j, k = 1; i < len1; i++, k++) {
acc = a[i] + b[k] + cy;
if (acc > 0x9)
acc += 0x6;
@ -2944,6 +2991,10 @@ fprintf(stderr, "Spec DecMP len=%x len=%x\n\r", len1, len2);
}
mul--;
}
// for (i = 31; i >= 0; i--) {
// fprintf(stderr, "%x", a[i]);
// }
// fprintf(stderr, "cy=%d\n\r", cy);
}
dec_store(a, addr1, len, sa);
}
@ -2956,7 +3007,8 @@ dec_div(int op, uint32 addr1, uint8 len1, uint32 addr2, uint8 len2)
uint8 c[32];
int i;
int j;
int k;
int k, x;
int o;
uint8 acc;
uint8 cy;
int sa, sb;
@ -2964,7 +3016,7 @@ dec_div(int op, uint32 addr1, uint8 len1, uint32 addr2, uint8 len2)
int len;
if (len2 > 7 || len2 >= len1) {
fprintf(stderr, "Spec DecDP len=%x len=%x\n\r", len1, len2);
//fprintf(stderr, "Spec DecDP len=%x len=%x\n\r", len1, len2);
storepsw(OPPSW, IRC_SPEC);
return;
}
@ -2972,21 +3024,18 @@ fprintf(stderr, "Spec DecDP len=%x len=%x\n\r", len1, len2);
return;
if (dec_load(a, addr1, (int)len1, &sa))
return;
/* Add numbers together */
for (i = 1; i <= len; i++) {
acc = a[i] + ((op)? (0x9 - b[i]):b[i]) + cy;
if (acc > 0x9)
acc += 0x6;
a[i] = acc & 0xf;
cy = (acc >> 4) & 0xf;
}
memset(c, 0, 32);
len = (int)len1;
len1 = (len1 + 1) * 2;
len2 = (len2 + 1) * 2;
sb ^= sa; /* Compute sign */
for (j = len2; j > 1; j--) {
// fprintf(stderr, "div 1=%d 2=%d\n\r", len1, len2);
for (j = len1 - len2; j > 0; j--) {
q = 0;
do {
/* Subtract divisor */
cy = 1;
for (i = j, k = 1; i <= len1; i++, k--) {
for (i = j, k = 1; k < len2; i++, k++) {
c[i] = a[i]; /* Save if we divide too far */
acc = a[i] + (0x9 - b[k]) + cy;
if (acc > 0x9)
@ -2994,23 +3043,48 @@ fprintf(stderr, "Spec DecDP len=%x len=%x\n\r", len1, len2);
a[i] = acc & 0xf;
cy = (acc >> 4) & 0xf;
}
if (cy) {
a[i] = q;
memcpy(a, c, 32); /* Restore the result */
if (q > 9) {
/* Plus one more digit */
if (i < 32) {
acc = a[i] + 9 + cy;
if (acc > 0x9)
acc += 0x6;
a[i] = acc & 0xf;
cy = (acc >> 4) & 0xf;
}
// fprintf(stderr, "div q=%d %d: ", q, j);
// for (x = 31; x >= 0; x--) {
// fprintf(stderr, "%x", a[x]);
// }
// fprintf(stderr, " cy=%d\n\r", cy);
/* If no borrow, so we are done with this digit */
if (!cy) {
/* It is a no-no to have non-zero digit above size */
if (q > 0 && (i+1) >= len1) {
storepsw(OPPSW, IRC_DECDIV);
return;
}
a[i+1] = q; /* Save quotient digit */
for (i = j; k > 1; i++, k--)
a[i] = c[i]; /* Restore previous */
// fprintf(stderr, "div r=%d %d: ", q, j);
// for (x = 31; x >= 0; x--) {
// fprintf(stderr, "%x", a[x]);
// }
// fprintf(stderr, "\n\r");
} else {
q++;
}
} while(cy == 0);
if (q > 9) {
storepsw(OPPSW, IRC_DECDIV);
return;
}
} while(cy != 0);
}
/* Set sign of quotient */
if (sb) {
a[len2+1] = ((flags & ASCII)? 0xb : 0xd);
a[len2] = ((flags & ASCII)? 0xb : 0xd);
} else {
a[len2+1] = ((flags & ASCII)? 0xa : 0xc);
a[len2] = ((flags & ASCII)? 0xa : 0xc);
}
dec_store(a, addr1, len, sa);
}