EASy68K
http://www.easy68k.com/EASy68Kforum/

ADDX -(A0),-(A0)
http://www.easy68k.com/EASy68Kforum/viewtopic.php?f=8&t=1092
Page 1 of 1

Author:  profkelly [ Thu Apr 05, 2012 1:20 pm ]
Post subject:  ADDX -(A0),-(A0)

The addressing mode is not behaving correctly. The pre-decrement should be progressive.

Pre: A0 is $1002
$1000: 01 02 00

Post: A0 should be $1000
$1000: 03 02 00

Author:  clive [ Thu Apr 05, 2012 2:00 pm ]
Post subject: 

Seems to impact ADDX.W and ADDX.L also, but not a similar MOVE.W

ADDX is one of the few logic operations that permits EA, EA addressing.

I guess CMPM, ABCD, SBCD, SUBX would be worth a look also.

..

SUBX fails
ABCD fails
SBCD fails

CMPM only has (Ax)+, (Ax)+ behaviour, need to check if (A0)+,(A0)+ operates as expected

CMPM.B (A0)+,(A0)+ advances A0 by two, but seems to set Z when the subsequent values are not the same, using A0 and A1 to point to A0+1 does not set Z. Need to check on real silicon, but this appears to be wrong.

CMPM fails

Author:  clive [ Thu Apr 05, 2012 7:04 pm ]
Post subject: 

Here's a fix for CMPM
Code:
int   CMPM()
{
long   size;
int   Rx, Ry;

if (decode_size(&size))
  return (BAD_INST);

Rx = a_reg((inst >> 9) & 0x07);

Ry = a_reg(inst & 0x07);

mem_req ( (int) A[Ry], size, &source);

if (size == BYTE_MASK)
   A[Ry]++;
else if (size == WORD_MASK)
   A[Ry] += 2;
else if (size == LONG_MASK)
   A[Ry] += 4;

mem_req ( (int) A[Rx], size, &dest);

if (size == BYTE_MASK)
   A[Rx]++;
else if (size == WORD_MASK)
   A[Rx] += 2;
else if (size == LONG_MASK)
   A[Rx] += 4;

put (&result, dest - source, size);

/* now set the condition codes according to the result */
cc_update (N_A, GEN, GEN, CASE_2, CASE_6, source, dest, result, size, 0);

inc_cyc ( (size == LONG_MASK) ? 20 : 12);

return SUCCESS;
}

Author:  clive [ Thu Apr 05, 2012 7:09 pm ]
Post subject: 

For ADDX

Code:
int   ADDX()
{
  long   size;
  int   Rx, Ry;

  if (decode_size(&size)) return (BAD_INST);

  Rx = (inst >> 9) & 0x0007;
  Ry = inst & 0x0007;

  /* perform the ADDX operation */
  if (inst & 0x0008)
          {
          Rx = a_reg (Rx);
          Ry = a_reg (Ry);

          if (size == BYTE_MASK)
             A[Ry]--;
          else if (size == WORD_MASK)
             A[Ry] -= 2;
          else if (size == LONG_MASK)
             A[Ry] -= 4;

          mem_req ((int) A[Ry], size, &source);

          if (size == BYTE_MASK)
            A[Rx]--;
          else if (size == WORD_MASK)
            A[Rx] -= 2;
          else if (size == LONG_MASK)
            A[Rx] -= 4;

          mem_req ((int) A[Rx], size, &dest);

          put ((long *)&memory[A[a_reg(Rx)]], source + dest + ((SR & xbit) >> 4), size);
          mem_req ((int) A[Rx], size, &result);
          }
  else
          {
          source = D[Ry] & size;
          dest = D[Rx] & size;
          put (&D[Rx], source + dest + ((SR & xbit) >> 4), size);
          result = D[Rx] & size;
          }

  cc_update (GEN, GEN, CASE_1, CASE_1, CASE_5, source, dest, result, size, 0);

  if (size == LONG_MASK)
     inc_cyc ( (inst & 0x0008) ? 30 : 8);
  else
     inc_cyc ( (inst & 0x0008) ? 18 : 4);

  return SUCCESS;

}

Author:  clive [ Thu Apr 05, 2012 7:14 pm ]
Post subject: 

ABCD, SBCD
Code:
//-------------------------------------------------------
// perform the ABCD operation
int   ABCD()
{
  int   Rx, Ry, carry, temp_result;

  Rx = (inst >> 9) & 0x0007;
  Ry = inst & 0x0007;

  if (inst & 0x0008) // Rx & Ry are address registers used in predecrement mode
  {
    Rx = a_reg(Rx);
    Ry = a_reg(Ry);

    A[Ry]--;

    //source = memory[A[Ry]];     //ck 4-2006 replace with below
    mem_req ((int)A[Ry], BYTE_MASK, &source); // cause bus error on bad access

    A[Rx]--;

    //dest = memory[A[Rx]];      //ck 4-2006 replace with below
    mem_req ((int)A[Rx], BYTE_MASK, &dest);

  }
  else      // Rx & Ry are data registers
  {
    source = D[Ry] & BYTE_MASK;
    dest = D[Rx] & BYTE_MASK;
  }

  // perform the ABCD operation
  result = ((SR & xbit) >> 4) + (source & 0xf) + (dest & 0xf);
  if (result > 9)
  {
    result = result - 10;
    carry = 1;
  }
  else
    carry = 0;
  temp_result = ((source >> 4) & 0xf) + ((dest >> 4) & 0xf) + carry;
  if (temp_result > 9)
  {
    temp_result = temp_result - 10;
    carry = 1;
  }
  else
    carry = 0;

  result = result + (temp_result << 4);

  if (inst & 0x0008)
    put ((long *)&memory[A[Rx]], result, (long) BYTE_MASK);
  else
    put (&D[Rx], result, (long) BYTE_MASK);
  if (carry)
    SR = SR | cbit;
  else
    SR = SR & ~cbit;

  cc_update (GEN, UND, CASE_1, UND, N_A, source, dest, result, (long) BYTE_MASK, 0);

  inc_cyc ( (inst & 0x0008) ? 18 : 6);

  return SUCCESS;
}



//-------------------------------------------------------
// perform the SUB operation
int   SBCD()
{
  int   Rx, Ry, borrow, temp_result;

  Rx = (inst >> 9) & 0x0007;
  Ry = inst & 0x0007;

  if (inst & 0x0008) //Rx & Ry are address registers used in predecrement mode
  {
    Rx = a_reg(Rx);
    Ry = a_reg(Ry);

    A[Ry]--;

    //source = memory[A[Ry]];     //ck 4-2006 replace with below
    mem_req ((int)A[Ry], BYTE_MASK, &source); // cause bus error on bad access

    A[Rx]--;

    //dest = memory[A[Rx]];      //ck 4-2006 replace with below
    mem_req ((int)A[Rx], BYTE_MASK, &dest);
  }
  else
  {              // Rx & Ry are data registers
    source = D[Ry];
    dest = D[Rx];
  }

  // perform the SBCD operation
  result = (dest & 0xf) - (source & 0xf) - ((SR & xbit) >> 4);
  if (result < 0)
  {
    result = result + 10;
    borrow = 1;
  }
  else
    borrow = 0;
  temp_result = ((dest >> 4) & 0xf) - ((source >> 4) & 0xf) - borrow;
  if (temp_result < 0)
  {
    temp_result = temp_result + 10;
    borrow = 1;
  }
  else
    borrow = 0;
  result = result + (temp_result << 4);

  if (inst & 0x0008)
    put ((long *)&memory[A[Rx]], result, (long) BYTE_MASK);
  else
    put (&D[Rx], result, (long) BYTE_MASK);

  if (borrow)
    SR = SR | cbit;
  else
    SR = SR & ~cbit;

  cc_update (GEN, UND, CASE_1, UND, N_A, source, dest, result, (long) BYTE_MASK, 0);

  inc_cyc ( (inst & 0x0008) ? 18 : 6);

  return SUCCESS;
}

Author:  clive [ Thu Apr 05, 2012 7:20 pm ]
Post subject: 

SUBX
Code:
int   SUBX()
{
  long   size;
  int   Rx, Ry;

  if (decode_size(&size))
    return (BAD_INST);

  Ry = (inst >> 9) & 0x0007;
  Rx = inst & 0x0007;

  /* perform the SUBX operation */
  if (inst & 0x0008)
          {
          Rx = a_reg(Rx);
          Ry = a_reg(Ry);

  /* Handle pre-decrements in a linear fashion to permit correct function
      of -(A0),-(A0) type examples */

          if (size == LONG_MASK)
                  A[Rx] -= 4;
          else if (size == WORD_MASK)
                  A[Rx] -= 2;
          else
                  A[Rx]--;

          mem_req ( (int) A[Rx], size, &source);

          if (size == LONG_MASK)
                  A[Ry] -= 4;
          else if (size == WORD_MASK)
                  A[Ry] -= 2;
          else
                  A[Ry]--;

          mem_req ( (int) A[Ry], size, &dest);
          put ((long *)&memory[A[Ry]], dest - source - ((SR & xbit)>> 4), size);
          mem_req ( (int) A[Ry], size, &result);
          }
  else
          {
          source = D[Rx] & size;
          dest = D[Ry] & size;
          put (&D[Ry], dest - source - ((SR & xbit) >> 4), size);
          result = D[Ry] & size;
          }

  cc_update (GEN, GEN, CASE_1, CASE_2, CASE_6, source, dest, result, size, 0);

  if (size == LONG_MASK)
     inc_cyc ( (inst & 0x0008) ? 30 : 8);
  else
     inc_cyc ( (inst & 0x0008) ? 18 : 4);

  return SUCCESS;
}

Author:  profkelly [ Fri Apr 06, 2012 10:02 pm ]
Post subject: 

Corrected in EASy68K v5.12.0

Author:  clive [ Fri Apr 06, 2012 10:15 pm ]
Post subject: 

Super, will download the new build.

Later:
CMPM, ABCD, ADDX, SBCD, SUBX appear happier now.

Page 1 of 1 All times are UTC
Powered by phpBB® Forum Software © phpBB Group
http://www.phpbb.com/