SWTP6800: Corrected flag setting errors (Richard Brinegar)

This commit is contained in:
Bill Beech 2020-04-28 14:02:03 -07:00
parent 3a38d38ce7
commit 6e6706f2a4

View file

@ -26,6 +26,7 @@
MODIFICATIONS: MODIFICATIONS:
23 Apr 15 -- Modified to use simh_debug 23 Apr 15 -- Modified to use simh_debug
21 Apr 20 -- Richard Brinegar numerous fixes for flag errors
NOTES: NOTES:
cpu Motorola M6800 CPU cpu Motorola M6800 CPU
@ -65,10 +66,10 @@
Invalid mamory address (if MTRAP is set on CPU) Invalid mamory address (if MTRAP is set on CPU)
2. Interrupts. 2. Interrupts.
There are 4 types of interrupt, and in effect they do a There are 4 types of interrupt, and in effect they do a
hardware CALL instruction to one of 4 possible high memory addresses. hardware CALL instruction to one of 4 possible high memory addresses.
3. Non-existent memory. 3. Non-existent memory.
On the SWTP 6800, reads to non-existent memory On the SWTP 6800, reads to non-existent memory
return 0FFH, and writes are ignored. return 0FFH, and writes are ignored.
*/ */
@ -146,6 +147,7 @@ int32 get_ext_addr(void);
int32 get_flag(int32 flag); int32 get_flag(int32 flag);
void condevalVa(int32 op1, int32 op2); void condevalVa(int32 op1, int32 op2);
void condevalVs(int32 op1, int32 op2); void condevalVs(int32 op1, int32 op2);
void condevalHa(int32 op1, int32 op2);
/* external routines */ /* external routines */
@ -343,7 +345,7 @@ t_stat sim_instr (void)
case 0x01: /* NOP */ case 0x01: /* NOP */
break; break;
case 0x06: /* TAP */ case 0x06: /* TAP */
CCR = A; CCR = A | CCR_ALWAYS_ON;
break; break;
case 0x07: /* TPA */ case 0x07: /* TPA */
A = CCR; A = CCR;
@ -377,18 +379,19 @@ t_stat sim_instr (void)
case 0x10: /* SBA */ case 0x10: /* SBA */
op1 = A; op1 = A;
A = A - B; A = A - B;
COND_SET_FLAG_C(A);
A &= 0xFF;
COND_SET_FLAG_N(A); COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A); COND_SET_FLAG_Z(A);
COND_SET_FLAG_C(A); condevalVs(op1, B);
condevalVs(B, op1);
A &= 0xFF;
break; break;
case 0x11: /* CBA */ case 0x11: /* CBA */
lo = A - B; lo = A - B;
COND_SET_FLAG_C(lo);
lo &= 0xFF ;
COND_SET_FLAG_N(lo); COND_SET_FLAG_N(lo);
COND_SET_FLAG_Z(lo); COND_SET_FLAG_Z(lo);
COND_SET_FLAG_C(lo); condevalVs(A, B);
condevalVs(B, A);
break; break;
case 0x16: /* TAB */ case 0x16: /* TAB */
B = A; B = A;
@ -398,42 +401,36 @@ t_stat sim_instr (void)
break; break;
case 0x17: /* TBA */ case 0x17: /* TBA */
A = B; A = B;
COND_SET_FLAG_N(B); COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(B); COND_SET_FLAG_Z(A);
CLR_FLAG(VF); CLR_FLAG(VF);
break; break;
case 0x19: /* DAA */ case 0x19: /* DAA */
DAR = A & 0x0F; DAR = A & 0x0F;
op1 = get_flag(CF); if ((DAR > 9) || get_flag(HF)) {
if (DAR > 9 || get_flag(CF)) { DAR += 6 ;
DAR += 6; A = (A & 0xF0) + DAR;
A &= 0xF0; COND_SET_FLAG(DAR & 0x10, HF);
A |= (DAR & 0x0F);
COND_SET_FLAG(DAR & 0x10,CF);
} }
DAR = (A >> 4) & 0x0F; DAR = (A >> 4) & 0x0F;
if (DAR > 9 || get_flag(CF)) { if ((DAR > 9) || get_flag(CF)) {
DAR += 6; DAR =+ 6;
if (get_flag(CF)) A = (A & 0x0F) | (DAR << 4) | 0x100;
DAR++;
A &= 0x0F;
A |= (DAR << 4);
} }
COND_SET_FLAG(op1,CF); COND_SET_FLAG_C(A);
if ((DAR << 4) & 0x100) A &= 0xFF;
SET_FLAG(CF);
COND_SET_FLAG_N(A); COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A); COND_SET_FLAG_Z(A);
A &= 0xFF;
break; break;
case 0x1B: /* ABA */ case 0x1B: /* ABA */
op1 = A ;
A += B; A += B;
COND_SET_FLAG_H(A); COND_SET_FLAG_C(A);
A &= 0xFF;
condevalHa(op1, B);
COND_SET_FLAG_N(A); COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A); COND_SET_FLAG_Z(A);
COND_SET_FLAG_C(A); condevalVa(op1, B);
condevalVa(A, B);
A &= 0xFF;
break; break;
case 0x20: /* BRA rel */ case 0x20: /* BRA rel */
go_rel(1); go_rel(1);
@ -538,10 +535,10 @@ t_stat sim_instr (void)
PC = CPU_BD_get_mword(0xFFFA) & ADDRMASK; PC = CPU_BD_get_mword(0xFFFA) & ADDRMASK;
break; break;
case 0x40: /* NEG A */ case 0x40: /* NEG A */
op1 = A; COND_SET_FLAG_V(A == 0x80);
A = (0 - A) & 0xFF; A = (0 - A);
condevalVa(A, op1); COND_SET_FLAG_C(A);
COND_SET_FLAG(A,CF); A &= 0xFF;
COND_SET_FLAG_N(A); COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A); COND_SET_FLAG_Z(A);
break; break;
@ -573,7 +570,7 @@ t_stat sim_instr (void)
COND_SET_FLAG(A & 0x01,CF); COND_SET_FLAG(A & 0x01,CF);
lo = A & 0x80; lo = A & 0x80;
A = (A >> 1) & 0xFF; A = (A >> 1) & 0xFF;
A |= lo; A |= lo;
COND_SET_FLAG_N(A); COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A); COND_SET_FLAG_Z(A);
COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF)); COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF));
@ -622,10 +619,10 @@ t_stat sim_instr (void)
SET_FLAG(ZF); SET_FLAG(ZF);
break; break;
case 0x50: /* NEG B */ case 0x50: /* NEG B */
op1 = B; COND_SET_FLAG_V(B == 0x80);
B = (0 - B) & 0xFF; B = (0 - B);
condevalVa(B, op1); COND_SET_FLAG_C(B);
COND_SET_FLAG(B,CF); B &= 0xFF;
COND_SET_FLAG_N(B); COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B); COND_SET_FLAG_Z(B);
break; break;
@ -658,7 +655,7 @@ t_stat sim_instr (void)
COND_SET_FLAG(B & 0x01,CF); COND_SET_FLAG(B & 0x01,CF);
lo = B & 0x80; lo = B & 0x80;
B = (B >> 1) & 0xFF; B = (B >> 1) & 0xFF;
B |= lo; B |= lo;
COND_SET_FLAG_N(B); COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B); COND_SET_FLAG_Z(B);
COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF)); COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF));
@ -709,10 +706,11 @@ t_stat sim_instr (void)
case 0x60: /* NEG ind */ case 0x60: /* NEG ind */
DAR = get_indir_addr(); DAR = get_indir_addr();
op1 = CPU_BD_get_mbyte(DAR); op1 = CPU_BD_get_mbyte(DAR);
lo = (0 - op1) & 0xFF; COND_SET_FLAG_V(op1 == 0x80);
lo = (0 - op1);
COND_SET_FLAG_C(lo);
lo &= 0xFF;
CPU_BD_put_mbyte(DAR, lo); CPU_BD_put_mbyte(DAR, lo);
condevalVs(lo, op1);
COND_SET_FLAG(lo,CF);
COND_SET_FLAG_N(lo); COND_SET_FLAG_N(lo);
COND_SET_FLAG_Z(lo); COND_SET_FLAG_Z(lo);
break; break;
@ -763,7 +761,7 @@ t_stat sim_instr (void)
DAR = get_indir_addr(); DAR = get_indir_addr();
lo = CPU_BD_get_mbyte(DAR); lo = CPU_BD_get_mbyte(DAR);
COND_SET_FLAG(lo & 0x80,CF); COND_SET_FLAG(lo & 0x80,CF);
lo <<= 1; lo = (lo << 1) & 0xFF;
CPU_BD_put_mbyte(DAR, lo); CPU_BD_put_mbyte(DAR, lo);
COND_SET_FLAG_N(lo); COND_SET_FLAG_N(lo);
COND_SET_FLAG_Z(lo); COND_SET_FLAG_Z(lo);
@ -774,9 +772,8 @@ t_stat sim_instr (void)
lo = CPU_BD_get_mbyte(DAR); lo = CPU_BD_get_mbyte(DAR);
hi = get_flag(CF); hi = get_flag(CF);
COND_SET_FLAG(lo & 0x80,CF); COND_SET_FLAG(lo & 0x80,CF);
lo <<= 1; lo = (lo << 1) &0xFF;
if (hi) if (hi) lo |= 0x01;
lo |= 0x01;
CPU_BD_put_mbyte(DAR, lo); CPU_BD_put_mbyte(DAR, lo);
COND_SET_FLAG_N(lo); COND_SET_FLAG_N(lo);
COND_SET_FLAG_Z(lo); COND_SET_FLAG_Z(lo);
@ -820,12 +817,10 @@ t_stat sim_instr (void)
case 0x70: /* NEG ext */ case 0x70: /* NEG ext */
DAR = get_ext_addr(); DAR = get_ext_addr();
op1 = CPU_BD_get_mbyte(DAR); op1 = CPU_BD_get_mbyte(DAR);
COND_SET_FLAG_V(op1 == 0x80) ;
COND_SET_FLAG(op1 != 0, CF);
lo = (0 - op1) & 0xFF; lo = (0 - op1) & 0xFF;
CPU_BD_put_mbyte(DAR, lo); CPU_BD_put_mbyte(DAR, lo);
condevalVs(lo, op1);
CLR_FLAG(CF);
if (lo)
SET_FLAG(CF);
COND_SET_FLAG_N(lo); COND_SET_FLAG_N(lo);
COND_SET_FLAG_Z(lo); COND_SET_FLAG_Z(lo);
break; break;
@ -878,7 +873,7 @@ t_stat sim_instr (void)
DAR = get_ext_addr(); DAR = get_ext_addr();
lo = CPU_BD_get_mbyte(DAR); lo = CPU_BD_get_mbyte(DAR);
COND_SET_FLAG(lo & 0x80,CF); COND_SET_FLAG(lo & 0x80,CF);
lo <<= 1; lo = (lo << 1) & 0xFF;
CPU_BD_put_mbyte(DAR, lo); CPU_BD_put_mbyte(DAR, lo);
COND_SET_FLAG_N(lo); COND_SET_FLAG_N(lo);
COND_SET_FLAG_Z(lo); COND_SET_FLAG_Z(lo);
@ -889,9 +884,8 @@ t_stat sim_instr (void)
lo = CPU_BD_get_mbyte(DAR); lo = CPU_BD_get_mbyte(DAR);
hi = get_flag(CF); hi = get_flag(CF);
COND_SET_FLAG(lo & 0x80,CF); COND_SET_FLAG(lo & 0x80,CF);
lo <<= 1; lo = (lo << 1) & 0xFF;
if (hi) if (hi) lo |= 0x01;
lo |= 0x01;
CPU_BD_put_mbyte(DAR, lo); CPU_BD_put_mbyte(DAR, lo);
COND_SET_FLAG_N(lo); COND_SET_FLAG_N(lo);
COND_SET_FLAG_Z(lo); COND_SET_FLAG_Z(lo);
@ -934,31 +928,33 @@ t_stat sim_instr (void)
SET_FLAG(ZF); SET_FLAG(ZF);
break; break;
case 0x80: /* SUB A imm */ case 0x80: /* SUB A imm */
op1 = get_dir_addr(); lo = get_dir_addr();
A = A - op1; op1 = A;
COND_SET_FLAG_N(A); A = A - lo;
COND_SET_FLAG_C(A); COND_SET_FLAG_C(A);
condevalVs(A, op1);
A &= 0xFF; A &= 0xFF;
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A); COND_SET_FLAG_Z(A);
condevalVs(op1, lo);
break; break;
case 0x81: /* CMP A imm */ case 0x81: /* CMP A imm */
op1 = get_dir_addr(); op1 = get_dir_addr();
lo = A - op1; lo = A - op1;
COND_SET_FLAG_N(lo);
COND_SET_FLAG_C(lo); COND_SET_FLAG_C(lo);
condevalVs(lo, op1);
lo &= 0xFF; lo &= 0xFF;
COND_SET_FLAG_N(lo);
COND_SET_FLAG_Z(lo); COND_SET_FLAG_Z(lo);
condevalVs(A, op1);
break; break;
case 0x82: /* SBC A imm */ case 0x82: /* SBC A imm */
op1 = get_dir_addr(); lo = get_dir_addr() + get_flag(CF);
A = A - op1 - get_flag(CF); op1 = A;
COND_SET_FLAG_N(A); A = A - lo;
COND_SET_FLAG_C(A); COND_SET_FLAG_C(A);
condevalVs(A, op1);
A &= 0xFF; A &= 0xFF;
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A); COND_SET_FLAG_Z(A);
condevalVs(op1, lo);
break; break;
case 0x84: /* AND A imm */ case 0x84: /* AND A imm */
A = (A & get_dir_addr()) & 0xFF; A = (A & get_dir_addr()) & 0xFF;
@ -985,14 +981,15 @@ t_stat sim_instr (void)
COND_SET_FLAG_Z(A); COND_SET_FLAG_Z(A);
break; break;
case 0x89: /* ADC A imm */ case 0x89: /* ADC A imm */
op1 = get_dir_addr(); lo = get_dir_addr() + get_flag(CF);
A = A + op1 + get_flag(CF); op1 = A;
COND_SET_FLAG_H(A); A = A + lo;
COND_SET_FLAG_N(A);
COND_SET_FLAG_C(A); COND_SET_FLAG_C(A);
condevalVa(A, op1);
A &= 0xFF; A &= 0xFF;
condevalHa(op1, lo);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A); COND_SET_FLAG_Z(A);
condevalVa(op1, lo);
break; break;
case 0x8A: /* ORA A imm */ case 0x8A: /* ORA A imm */
A = (A | get_dir_addr()) & 0xFF; A = (A | get_dir_addr()) & 0xFF;
@ -1001,14 +998,15 @@ t_stat sim_instr (void)
COND_SET_FLAG_Z(A); COND_SET_FLAG_Z(A);
break; break;
case 0x8B: /* ADD A imm */ case 0x8B: /* ADD A imm */
op1 = get_dir_addr(); lo = get_dir_addr();
A = A + op1; op1 = A;
COND_SET_FLAG_H(A); A = A + lo;
COND_SET_FLAG_N(A);
COND_SET_FLAG_C(A); COND_SET_FLAG_C(A);
condevalVa(A, op1);
A &= 0xFF; A &= 0xFF;
condevalHa(op1, lo);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A); COND_SET_FLAG_Z(A);
condevalVa(op1, lo);
break; break;
case 0x8C: /* CPX imm */ case 0x8C: /* CPX imm */
op1 = IX - get_ext_addr(); op1 = IX - get_ext_addr();
@ -1029,13 +1027,14 @@ t_stat sim_instr (void)
CLR_FLAG(VF); CLR_FLAG(VF);
break; break;
case 0x90: /* SUB A dir */ case 0x90: /* SUB A dir */
op1 = get_dir_val(); lo = get_dir_val();
A = A - op1; op1 = A;
COND_SET_FLAG_N(A); A = A - lo;
COND_SET_FLAG_C(A); COND_SET_FLAG_C(A);
condevalVs(A, op1);
A &= 0xFF; A &= 0xFF;
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A); COND_SET_FLAG_Z(A);
condevalVs(op1, lo);
break; break;
case 0x91: /* CMP A dir */ case 0x91: /* CMP A dir */
op1 = get_dir_val(); op1 = get_dir_val();
@ -1047,13 +1046,13 @@ t_stat sim_instr (void)
COND_SET_FLAG_Z(lo); COND_SET_FLAG_Z(lo);
break; break;
case 0x92: /* SBC A dir */ case 0x92: /* SBC A dir */
op1 = get_dir_val(); lo = get_dir_val() + get_flag(CF);
A = A - op1 - get_flag(CF); A = A - lo;
COND_SET_FLAG_N(A);
COND_SET_FLAG_C(A); COND_SET_FLAG_C(A);
condevalVs(A, op1);
A &= 0xFF; A &= 0xFF;
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A); COND_SET_FLAG_Z(A);
condevalVs(op1, lo);
break; break;
case 0x94: /* AND A dir */ case 0x94: /* AND A dir */
A = (A & get_dir_val()) & 0xFF; A = (A & get_dir_val()) & 0xFF;
@ -1086,14 +1085,15 @@ t_stat sim_instr (void)
COND_SET_FLAG_Z(A); COND_SET_FLAG_Z(A);
break; break;
case 0x99: /* ADC A dir */ case 0x99: /* ADC A dir */
op1 = get_dir_val(); lo = get_dir_val() + get_flag(CF);
A = A + op1 + get_flag(CF); op1 = A;
COND_SET_FLAG_H(A); A = A + lo;
COND_SET_FLAG_N(A);
COND_SET_FLAG_C(A); COND_SET_FLAG_C(A);
condevalVa(A, op1);
A &= 0xFF; A &= 0xFF;
condevalHa(op1, lo);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A); COND_SET_FLAG_Z(A);
condevalVa(op1, lo);
break; break;
case 0x9A: /* ORA A dir */ case 0x9A: /* ORA A dir */
A = (A | get_dir_val()) & 0xFF; A = (A | get_dir_val()) & 0xFF;
@ -1102,14 +1102,15 @@ t_stat sim_instr (void)
COND_SET_FLAG_Z(A); COND_SET_FLAG_Z(A);
break; break;
case 0x9B: /* ADD A dir */ case 0x9B: /* ADD A dir */
op1 = get_dir_val(); lo = get_dir_val();
A = A + op1; op1 = A;
COND_SET_FLAG_H(A); A = A + lo;
COND_SET_FLAG_N(A);
COND_SET_FLAG_C(A); COND_SET_FLAG_C(A);
condevalVa(A, op1);
A &= 0xFF; A &= 0xFF;
condevalHa(op1, lo);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A); COND_SET_FLAG_Z(A);
condevalVa(op1, lo);
break; break;
case 0x9C: /* CPX dir */ case 0x9C: /* CPX dir */
op1 = IX - CPU_BD_get_mword(get_dir_addr()); op1 = IX - CPU_BD_get_mword(get_dir_addr());
@ -1130,13 +1131,14 @@ t_stat sim_instr (void)
CLR_FLAG(VF); CLR_FLAG(VF);
break; break;
case 0xA0: /* SUB A ind */ case 0xA0: /* SUB A ind */
op1 = get_indir_val(); lo = get_indir_val();
A = A - op1; op1 = A;
COND_SET_FLAG_N(A); A = A - lo;
COND_SET_FLAG_C(A); COND_SET_FLAG_C(A);
condevalVs(A, op1);
A &= 0xFF; A &= 0xFF;
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A); COND_SET_FLAG_Z(A);
condevalVs(op1, lo);
break; break;
case 0xA1: /* CMP A ind */ case 0xA1: /* CMP A ind */
op1 = get_indir_val(); op1 = get_indir_val();
@ -1148,13 +1150,13 @@ t_stat sim_instr (void)
COND_SET_FLAG_Z(lo); COND_SET_FLAG_Z(lo);
break; break;
case 0xA2: /* SBC A ind */ case 0xA2: /* SBC A ind */
op1 = get_indir_val(); lo = get_indir_val() + get_flag(CF);
A = A - op1 - get_flag(CF); A = A - lo;
COND_SET_FLAG_N(A);
COND_SET_FLAG_C(A); COND_SET_FLAG_C(A);
condevalVs(A, op1);
A &= 0xFF; A &= 0xFF;
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A); COND_SET_FLAG_Z(A);
condevalVs(op1, lo);
break; break;
case 0xA4: /* AND A ind */ case 0xA4: /* AND A ind */
A = (A & get_indir_val()) & 0xFF; A = (A & get_indir_val()) & 0xFF;
@ -1187,14 +1189,15 @@ t_stat sim_instr (void)
COND_SET_FLAG_Z(A); COND_SET_FLAG_Z(A);
break; break;
case 0xA9: /* ADC A ind */ case 0xA9: /* ADC A ind */
op1 = get_indir_val(); lo = get_indir_val() + get_flag(CF);
A = A + op1 + get_flag(CF); op1 = A;
COND_SET_FLAG_H(A); A = A + lo;
COND_SET_FLAG_N(A);
COND_SET_FLAG_C(A); COND_SET_FLAG_C(A);
condevalVa(A, op1);
A &= 0xFF; A &= 0xFF;
condevalHa(op1, lo);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A); COND_SET_FLAG_Z(A);
condevalVa(op1, lo);
break; break;
case 0xAA: /* ORA A ind */ case 0xAA: /* ORA A ind */
A = (A | get_indir_val()) & 0xFF; A = (A | get_indir_val()) & 0xFF;
@ -1203,14 +1206,15 @@ t_stat sim_instr (void)
COND_SET_FLAG_Z(A); COND_SET_FLAG_Z(A);
break; break;
case 0xAB: /* ADD A ind */ case 0xAB: /* ADD A ind */
op1 = get_indir_val(); lo = get_indir_val();
A = A + op1; op1 = A;
COND_SET_FLAG_H(A); A = A + lo;
COND_SET_FLAG_N(A);
COND_SET_FLAG_C(A); COND_SET_FLAG_C(A);
condevalVa(A, op1);
A &= 0xFF; A &= 0xFF;
condevalHa(op1, lo);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A); COND_SET_FLAG_Z(A);
condevalVa(op1, lo);
break; break;
case 0xAC: /* CPX ind */ case 0xAC: /* CPX ind */
op1 = (IX - get_indir_addr()) & ADDRMASK; op1 = (IX - get_indir_addr()) & ADDRMASK;
@ -1236,13 +1240,14 @@ t_stat sim_instr (void)
CLR_FLAG(VF); CLR_FLAG(VF);
break; break;
case 0xB0: /* SUB A ext */ case 0xB0: /* SUB A ext */
op1 = get_ext_val(); lo = get_ext_val();
A = A - op1; op1 = A;
COND_SET_FLAG_N(A); A = A - lo;
COND_SET_FLAG_C(A); COND_SET_FLAG_C(A);
condevalVs(A, op1);
A &= 0xFF; A &= 0xFF;
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A); COND_SET_FLAG_Z(A);
condevalVs(op1, lo);
break; break;
case 0xB1: /* CMP A ext */ case 0xB1: /* CMP A ext */
op1 = get_ext_val(); op1 = get_ext_val();
@ -1254,13 +1259,14 @@ t_stat sim_instr (void)
COND_SET_FLAG_Z(lo); COND_SET_FLAG_Z(lo);
break; break;
case 0xB2: /* SBC A ext */ case 0xB2: /* SBC A ext */
op1 = get_ext_val(); lo = get_ext_val() + get_flag(CF);
A = A - op1 - get_flag(CF); op1 = A;
COND_SET_FLAG_N(A); A = A - lo;
COND_SET_FLAG_C(A); COND_SET_FLAG_C(A);
condevalVs(A, op1);
A &= 0xFF; A &= 0xFF;
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A); COND_SET_FLAG_Z(A);
condevalVs(op1, lo);
break; break;
case 0xB4: /* AND A ext */ case 0xB4: /* AND A ext */
A = (A & get_ext_val()) & 0xFF; A = (A & get_ext_val()) & 0xFF;
@ -1293,14 +1299,15 @@ t_stat sim_instr (void)
COND_SET_FLAG_Z(A); COND_SET_FLAG_Z(A);
break; break;
case 0xB9: /* ADC A ext */ case 0xB9: /* ADC A ext */
op1 = get_ext_val(); lo = get_ext_val() + get_flag(CF);
A = A + op1 + get_flag(CF); op1 = A;
COND_SET_FLAG_H(A); A = A + lo;
COND_SET_FLAG_N(A);
COND_SET_FLAG_C(A); COND_SET_FLAG_C(A);
condevalVa(A, op1);
A &= 0xFF; A &= 0xFF;
condevalHa(op1, lo);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A); COND_SET_FLAG_Z(A);
condevalVa(op1, lo);
break; break;
case 0xBA: /* ORA A ext */ case 0xBA: /* ORA A ext */
A = (A | get_ext_val()) & 0xFF; A = (A | get_ext_val()) & 0xFF;
@ -1309,14 +1316,15 @@ t_stat sim_instr (void)
COND_SET_FLAG_Z(A); COND_SET_FLAG_Z(A);
break; break;
case 0xBB: /* ADD A ext */ case 0xBB: /* ADD A ext */
op1 = get_ext_val(); lo = get_ext_val();
A = A + op1; op1 = A;
COND_SET_FLAG_H(A); A = A + lo;
COND_SET_FLAG_N(A);
COND_SET_FLAG_C(A); COND_SET_FLAG_C(A);
condevalVa(A, op1);
A &= 0xFF; A &= 0xFF;
condevalHa(op1, lo);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A); COND_SET_FLAG_Z(A);
condevalVa(op1, lo);
break; break;
case 0xBC: /* CPX ext */ case 0xBC: /* CPX ext */
op1 = (IX - CPU_BD_get_mword(get_ext_addr()));// & ADDRMASK; op1 = (IX - CPU_BD_get_mword(get_ext_addr()));// & ADDRMASK;
@ -1342,13 +1350,14 @@ t_stat sim_instr (void)
CLR_FLAG(VF); CLR_FLAG(VF);
break; break;
case 0xC0: /* SUB B imm */ case 0xC0: /* SUB B imm */
op1 = get_dir_addr(); lo = get_dir_addr();
B = B - op1; op1 = B;
COND_SET_FLAG_N(B); B = B - lo;
COND_SET_FLAG_C(B); COND_SET_FLAG_C(B);
condevalVs(B, op1);
B &= 0xFF; B &= 0xFF;
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B); COND_SET_FLAG_Z(B);
condevalVs(op1, lo);
break; break;
case 0xC1: /* CMP B imm */ case 0xC1: /* CMP B imm */
op1 = get_dir_addr(); op1 = get_dir_addr();
@ -1360,13 +1369,13 @@ t_stat sim_instr (void)
COND_SET_FLAG_Z(lo); COND_SET_FLAG_Z(lo);
break; break;
case 0xC2: /* SBC B imm */ case 0xC2: /* SBC B imm */
op1 = get_dir_addr(); lo = get_dir_addr() + get_flag(CF);
B = B - op1 - get_flag(CF); B = B - lo;
COND_SET_FLAG_N(B);
COND_SET_FLAG_C(B); COND_SET_FLAG_C(B);
condevalVs(B, op1);
B &= 0xFF; B &= 0xFF;
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B); COND_SET_FLAG_Z(B);
condevalVs(op1, lo);
break; break;
case 0xC4: /* AND B imm */ case 0xC4: /* AND B imm */
B = (B & get_dir_addr()) & 0xFF; B = (B & get_dir_addr()) & 0xFF;
@ -1393,14 +1402,14 @@ t_stat sim_instr (void)
COND_SET_FLAG_Z(B); COND_SET_FLAG_Z(B);
break; break;
case 0xC9: /* ADC B imm */ case 0xC9: /* ADC B imm */
op1 = get_dir_addr(); lo = get_dir_addr() + get_flag(CF);
B = B + op1 + get_flag(CF); B = B + lo;
COND_SET_FLAG_H(B);
COND_SET_FLAG_N(B);
COND_SET_FLAG_C(B); COND_SET_FLAG_C(B);
condevalVa(B, op1);
B &= 0xFF; B &= 0xFF;
condevalHa(op1, lo);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B); COND_SET_FLAG_Z(B);
condevalVa(op1, lo);
break; break;
case 0xCA: /* ORA B imm */ case 0xCA: /* ORA B imm */
B = (B | get_dir_addr()) & 0xFF; B = (B | get_dir_addr()) & 0xFF;
@ -1409,14 +1418,15 @@ t_stat sim_instr (void)
COND_SET_FLAG_Z(B); COND_SET_FLAG_Z(B);
break; break;
case 0xCB: /* ADD B imm */ case 0xCB: /* ADD B imm */
op1 = get_dir_addr(); lo = get_dir_addr();
B = B + op1; op1 = B;
COND_SET_FLAG_H(B); B = B + lo;
COND_SET_FLAG_N(B);
COND_SET_FLAG_C(B); COND_SET_FLAG_C(B);
condevalVa(B, op1);
B &= 0xFF; B &= 0xFF;
condevalHa(op1, lo);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B); COND_SET_FLAG_Z(B);
condevalVa(op1, lo);
break; break;
case 0xCE: /* LDX imm */ case 0xCE: /* LDX imm */
IX = get_ext_addr(); IX = get_ext_addr();
@ -1425,30 +1435,32 @@ t_stat sim_instr (void)
CLR_FLAG(VF); CLR_FLAG(VF);
break; break;
case 0xD0: /* SUB B dir */ case 0xD0: /* SUB B dir */
op1 = get_dir_val(); lo = get_dir_val();
B = B - op1; op1 = B;
COND_SET_FLAG_N(B); B = B - lo;
COND_SET_FLAG_C(B); COND_SET_FLAG_C(B);
condevalVs(B, op1);
B &= 0xFF; B &= 0xFF;
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B); COND_SET_FLAG_Z(B);
condevalVs(op1, lo);
break; break;
case 0xD1: /* CMP B dir */ case 0xD1: /* CMP B dir */
op1 = get_dir_val(); lo = get_dir_val();
lo = B - op1; op1 = B - lo;
COND_SET_FLAG_N(lo); COND_SET_FLAG_C(op1);
COND_SET_FLAG_Z(lo); op1 &= 0xFF;
COND_SET_FLAG_C(lo); COND_SET_FLAG_N(op1);
condevalVs(B, op1); COND_SET_FLAG_Z(op1);
condevalVs(B, lo);
break; break;
case 0xD2: /* SBC B dir */ case 0xD2: /* SBC B dir */
op1 = get_dir_val(); lo = get_dir_val() + get_flag(CF);
B = B - op1 - get_flag(CF); B = B - lo;
COND_SET_FLAG_N(B);
COND_SET_FLAG_C(B); COND_SET_FLAG_C(B);
condevalVs(B, op1);
B &= 0xFF; B &= 0xFF;
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B); COND_SET_FLAG_Z(B);
condevalVs(op1, lo);
break; break;
case 0xD4: /* AND B dir */ case 0xD4: /* AND B dir */
B = (B & get_dir_val()) & 0xFF; B = (B & get_dir_val()) & 0xFF;
@ -1481,14 +1493,15 @@ t_stat sim_instr (void)
COND_SET_FLAG_Z(B); COND_SET_FLAG_Z(B);
break; break;
case 0xD9: /* ADC B dir */ case 0xD9: /* ADC B dir */
op1 = get_dir_val(); lo = get_dir_val() + get_flag(CF);
B = B + op1 + get_flag(CF); op1 = B;
COND_SET_FLAG_H(B); B = B + lo;
COND_SET_FLAG_N(B);
COND_SET_FLAG_C(B); COND_SET_FLAG_C(B);
condevalVa(B, op1);
B &= 0xFF; B &= 0xFF;
condevalHa(op1, lo);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B); COND_SET_FLAG_Z(B);
condevalVa(op1, lo);
break; break;
case 0xDA: /* ORA B dir */ case 0xDA: /* ORA B dir */
B = (B | get_dir_val()) & 0xFF; B = (B | get_dir_val()) & 0xFF;
@ -1497,14 +1510,15 @@ t_stat sim_instr (void)
COND_SET_FLAG_Z(B); COND_SET_FLAG_Z(B);
break; break;
case 0xDB: /* ADD B dir */ case 0xDB: /* ADD B dir */
op1 = get_dir_val(); lo = get_dir_val();
B = B + op1; op1 = B;
COND_SET_FLAG_H(B); B = B + lo;
COND_SET_FLAG_N(B);
COND_SET_FLAG_C(B); COND_SET_FLAG_C(B);
condevalVa(B, op1);
B &= 0xFF; B &= 0xFF;
condevalHa(op1, lo);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B); COND_SET_FLAG_Z(B);
condevalVa(op1, lo);
break; break;
case 0xDE: /* LDX dir */ case 0xDE: /* LDX dir */
IX = CPU_BD_get_mword(get_dir_addr()); IX = CPU_BD_get_mword(get_dir_addr());
@ -1519,13 +1533,14 @@ t_stat sim_instr (void)
CLR_FLAG(VF); CLR_FLAG(VF);
break; break;
case 0xE0: /* SUB B ind */ case 0xE0: /* SUB B ind */
op1 = get_indir_val(); lo = get_indir_val();
B = B - op1; op1 = B;
COND_SET_FLAG_N(B); B = B - lo;
COND_SET_FLAG_C(B); COND_SET_FLAG_C(B);
condevalVs(B, op1);
B &= 0xFF; B &= 0xFF;
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B); COND_SET_FLAG_Z(B);
condevalVs(op1, lo);
break; break;
case 0xE1: /* CMP B ind */ case 0xE1: /* CMP B ind */
op1 = get_indir_val(); op1 = get_indir_val();
@ -1537,13 +1552,14 @@ t_stat sim_instr (void)
COND_SET_FLAG_Z(lo); COND_SET_FLAG_Z(lo);
break; break;
case 0xE2: /* SBC B ind */ case 0xE2: /* SBC B ind */
op1 = get_indir_val(); lo = get_indir_val() + get_flag(CF);
B = B - op1 - get_flag(CF); op1 = B;
COND_SET_FLAG_N(B); B = B - lo;
COND_SET_FLAG_C(B); COND_SET_FLAG_C(B);
condevalVs(B, op1);
B &= 0xFF; B &= 0xFF;
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B); COND_SET_FLAG_Z(B);
condevalVs(op1, lo);
break; break;
case 0xE4: /* AND B ind */ case 0xE4: /* AND B ind */
B = (B & get_indir_val()) & 0xFF; B = (B & get_indir_val()) & 0xFF;
@ -1576,14 +1592,15 @@ t_stat sim_instr (void)
COND_SET_FLAG_Z(B); COND_SET_FLAG_Z(B);
break; break;
case 0xE9: /* ADC B ind */ case 0xE9: /* ADC B ind */
op1 = get_indir_val(); lo = get_indir_val() + get_flag(CF);
B = B + op1 + get_flag(CF); op1 = B;
COND_SET_FLAG_H(B); B = B + lo;
COND_SET_FLAG_N(B);
COND_SET_FLAG_C(B); COND_SET_FLAG_C(B);
condevalVa(B, op1);
B &= 0xFF; B &= 0xFF;
condevalHa(op1, lo);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B); COND_SET_FLAG_Z(B);
condevalVa(op1, lo);
break; break;
case 0xEA: /* ORA B ind */ case 0xEA: /* ORA B ind */
B = (B | get_indir_val()) & 0xFF; B = (B | get_indir_val()) & 0xFF;
@ -1592,14 +1609,15 @@ t_stat sim_instr (void)
COND_SET_FLAG_Z(B); COND_SET_FLAG_Z(B);
break; break;
case 0xEB: /* ADD B ind */ case 0xEB: /* ADD B ind */
op1 = get_indir_val(); lo = get_indir_val();
B = B + op1; op1 = B;
COND_SET_FLAG_H(B); B = B + lo;
COND_SET_FLAG_N(B);
COND_SET_FLAG_C(B); COND_SET_FLAG_C(B);
condevalVa(B, op1);
B &= 0xFF; B &= 0xFF;
condevalHa(op1, lo);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B); COND_SET_FLAG_Z(B);
condevalVa(op1, lo);
break; break;
case 0xEE: /* LDX ind */ case 0xEE: /* LDX ind */
IX = CPU_BD_get_mword(get_indir_addr()); IX = CPU_BD_get_mword(get_indir_addr());
@ -1614,13 +1632,14 @@ t_stat sim_instr (void)
CLR_FLAG(VF); CLR_FLAG(VF);
break; break;
case 0xF0: /* SUB B ext */ case 0xF0: /* SUB B ext */
op1 = get_ext_val(); lo = get_ext_val();
B = B - op1; op1 = B;
COND_SET_FLAG_N(B); B = B - lo;
COND_SET_FLAG_C(B); COND_SET_FLAG_C(B);
condevalVs(B, op1);
B &= 0xFF; B &= 0xFF;
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B); COND_SET_FLAG_Z(B);
condevalVs(op1, lo);
break; break;
case 0xF1: /* CMP B ext */ case 0xF1: /* CMP B ext */
op1 = get_ext_val(); op1 = get_ext_val();
@ -1632,13 +1651,13 @@ t_stat sim_instr (void)
COND_SET_FLAG_Z(lo); COND_SET_FLAG_Z(lo);
break; break;
case 0xF2: /* SBC B ext */ case 0xF2: /* SBC B ext */
op1 = get_ext_val(); lo = get_ext_val() + get_flag(CF);
B = B - op1 - get_flag(CF); B = B - lo;
COND_SET_FLAG_N(B);
COND_SET_FLAG_C(B); COND_SET_FLAG_C(B);
condevalVs(B, op1);
B &= 0xFF; B &= 0xFF;
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B); COND_SET_FLAG_Z(B);
condevalVs(op1, lo);
break; break;
case 0xF4: /* AND B ext */ case 0xF4: /* AND B ext */
B = (B & get_ext_val()) & 0xFF; B = (B & get_ext_val()) & 0xFF;
@ -1671,14 +1690,15 @@ t_stat sim_instr (void)
COND_SET_FLAG_Z(B); COND_SET_FLAG_Z(B);
break; break;
case 0xF9: /* ADC B ext */ case 0xF9: /* ADC B ext */
op1 = get_ext_val(); lo = get_ext_val() + get_flag(CF);
B = B + op1 + get_flag(CF); op1 = B;
COND_SET_FLAG_H(B); B = B + lo;
COND_SET_FLAG_N(B);
COND_SET_FLAG_C(B); COND_SET_FLAG_C(B);
condevalVa(B, op1);
B &= 0xFF; B &= 0xFF;
condevalHa(op1, lo);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B); COND_SET_FLAG_Z(B);
condevalVa(op1, lo);
break; break;
case 0xFA: /* ORA B ext */ case 0xFA: /* ORA B ext */
B = (B | get_ext_val()) & 0xFF; B = (B | get_ext_val()) & 0xFF;
@ -1687,14 +1707,15 @@ t_stat sim_instr (void)
COND_SET_FLAG_Z(B); COND_SET_FLAG_Z(B);
break; break;
case 0xFB: /* ADD B ext */ case 0xFB: /* ADD B ext */
op1 = get_ext_val(); lo = get_ext_val();
B = B + op1; op1 = B;
COND_SET_FLAG_H(B); B = B + lo;
COND_SET_FLAG_N(B);
COND_SET_FLAG_C(B); COND_SET_FLAG_C(B);
condevalVa(B, op1);
B &= 0xFF; B &= 0xFF;
condevalHa(op1, lo);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B); COND_SET_FLAG_Z(B);
condevalVa(op1, lo);
break; break;
case 0xFE: /* LDX ext */ case 0xFE: /* LDX ext */
IX = CPU_BD_get_mword(get_ext_addr()); IX = CPU_BD_get_mword(get_ext_addr());
@ -1856,7 +1877,7 @@ int32 get_indir_val(void)
int32 get_indir_addr(void) int32 get_indir_addr(void)
{ {
int32 temp; int32 temp;
temp = (fetch_byte(1) + IX) & ADDRMASK; temp = (fetch_byte(1) + IX) & ADDRMASK;
return temp; return temp;
} }
@ -1892,18 +1913,32 @@ int32 get_flag(int32 flg)
void condevalVa(int32 op1, int32 op2) void condevalVa(int32 op1, int32 op2)
{ {
if (get_flag(CF)) { if (((op1 & 0x80) == (op2 & 0x80)) &&
COND_SET_FLAG_V((op1 & op2 & 0x80) || (((op1 | op2) & 0x80) == 0)); (((op1 + op2) & 0x80) != (op1 & 0x80)))
} SET_FLAG(VF);
else
CLR_FLAG(VF);
} }
/* test and set V for subtraction */ /* test and set V for subtraction */
void condevalVs(int32 op1, int32 op2) void condevalVs(int32 op1, int32 op2)
{ {
if (get_flag(CF)) { if (((op1 & 0x80) != (op2 & 0x80)) &&
COND_SET_FLAG_V(op1 & op2 & 0x80); (((op1 - op2) & 0x80) == (op2 & 0x80)))
} SET_FLAG(VF);
else
CLR_FLAG(VF);
}
/* test and set H for addition */
void condevalHa(int32 op1, int32 op2)
{
if (((op1 & 0x0f) + (op2 & 0x0f)) & 0x10)
SET_FLAG(HF);
else
CLR_FLAG(HF);
} }
/* calls from the simulator */ /* calls from the simulator */
@ -1925,7 +1960,7 @@ t_stat m6800_reset (DEVICE *dptr)
/* This is the dumper/loader. This command uses the -h to signify a /* This is the dumper/loader. This command uses the -h to signify a
hex dump/load vice a binary one. If no address is given to load, it hex dump/load vice a binary one. If no address is given to load, it
takes the address from the hex record or the current PC for binary. takes the address from the hex record or the current PC for binary.
*/ */
@ -1939,7 +1974,7 @@ t_stat sim_load (FILE *fileref, CONST char *cptr, CONST char *fnam, int flag)
CPU_BD_put_mbyte(addr, i); CPU_BD_put_mbyte(addr, i);
addr++; addr++;
cnt++; cnt++;
} // end while } // end while
printf ("%d Bytes loaded.\n", cnt); printf ("%d Bytes loaded.\n", cnt);
return (SCPE_OK); return (SCPE_OK);
} }
@ -1995,7 +2030,7 @@ t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw)
else if (inst1 == 0x70 || inst1 == 0xb0 || inst1 == 0xF0) // ext operand else if (inst1 == 0x70 || inst1 == 0xb0 || inst1 == 0xF0) // ext operand
fprintf(of, " $%02X%02X", val[1], val[2]); fprintf(of, " $%02X%02X", val[1], val[2]);
return (-(oplen[inst] - 1)); return (-(oplen[inst] - 1));
} else } else
return SCPE_ARG; return SCPE_ARG;
} }