more unofficial opcodes? AHX (blargg's instr_timing)

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
more unofficial opcodes? AHX (blargg's instr_timing)
by on (#167968)
I'm adding all the unofficial opcodes requested by the test rom "instr_timing" by blargg, but... it's testing a few unstable or "not recommend to use" unofficial opcodes... like AHX. From this 6502 page, description says...
Code:
Combinations of STA/STX/STY:

AHX {adr} = stores A&X&H into {adr}
SHX {adr} = stores X&H into {adr}
SHY {adr} = stores Y&H into {adr}

note: sometimes the &H drops off. Also page boundary crossing will not work as expected (the bank where the value is stored may be equal to the value stored).


OK, but wtf is this "H" value???
Re: more unofficial opcodes? AHX (blargg's instr_timing)
by on (#167969)
High byte of the address specified.

The only actually unstable instructions are ones that have the feedback path between SB↔A. The rest seem to be just bizarre.

SHX and SHY are also referred to as SXA and SYA; see the discussion from a previous time.
Re: more unofficial opcodes? AHX (blargg's instr_timing)
by on (#167972)
I spent ages trying to figure those three opcodes out. The only accurate explanations I found were in the thread lidnariq just linked to.

EDIT: I am slow today.
Re: more unofficial opcodes? AHX (blargg's instr_timing)
by on (#168006)
What's the timing diagrama and operations of the opcodes 9C and 9E? I tried what was discussed before, but still fails the test ROM.

EDIT: I can't get a pass yet. Here's the source:
Code:
//ADDRESSING MODE DECODING
   OPADDR(UNABY) /* Absolute with Y [unofficial] */
      offset  = _readvalue(cpu->PC); cpu->PC++;  //2nd
      offsetH = _readvalue(cpu->PC);             //3rd
      offset += cpu->Y; cpu->PC++;
      _readvalue(offset|(offsetH << 8));      //4th*
      if(offset & 0x100) {
         offset &= 0xFF;
         offsetH++;
      } offset = (offset&0xFF)|(offsetH << 8); /* effective address */
   ADDREND

//OPCODE OPERATION

CPUOP(SHY1)
  writevalue(offset, cpu->Y & ( (offset>>8)+1 ) );
OPEND

CPUOP(SHX1)
  writevalue(offset, cpu->X & ( (offset>>8)+1 ) );
OPEND
Re: more unofficial opcodes? AHX (blargg's instr_timing)
by on (#168014)
Zepper wrote:
writevalue(offset, cpu->Y & ( (offset>>8)+1 ) );
H is only incremented if it needs to be. If L+Y < 256 it's just ANDed with H.
Re: more unofficial opcodes? AHX (blargg's instr_timing)
by on (#168052)
If it helps, this is my code. My emulator passes all of blargg's CPU test ROMs.
Code:
// opcode and data are loaded with the first two bytes of the instruction, respectively, by this point
// pc still points to the second byte, which is why both of these instructions start with pc++
// one of cpu_read() or cpu_write() is executed for every bus cycle; the two calls to cpu_read() that ignore the result are dummy reads
// the continues skip execution of the big switch statement for the other instructions - SHX and SHY are so bizzare I special-cased them

if(opcode == 0x9C) // *SHY
{
   pc++;
   address = (unsigned)data + x;
   data = cpu_read(state, pc++, clock++);
   cpu_read(state, (uint16_t)((address & 0xFF) + ((unsigned)data << 8)), clock++);

   if(address > 0xFF)
   {
      address += (unsigned)(data & y) << 8;
   }
   else
   {
      address += (unsigned)data << 8;
   }

   data = y & (uint8_t)(data + 1);
   cpu_write(state, (uint16_t)address, data, clock++);
   continue;
}

if(opcode == 0x9E) // *SHX
{
   pc++;
   address = (unsigned)data + y;
   data = cpu_read(state, pc++, clock++);
   cpu_read(state, (uint16_t)((address & 0xFF) + ((unsigned)data << 8)), clock++);

   if(address > 0xFF)
   {
      address += (unsigned)(data & x) << 8;
   }
   else
   {
      address += (unsigned)data << 8;
   }

   data = x & (uint8_t)(data + 1);
   cpu_write(state, (uint16_t)address, data, clock++);
   continue;
}
Re: more unofficial opcodes? AHX (blargg's instr_timing)
by on (#168072)
Finally. :lol:
Thank you so much.