User Tools

Site Tools


base:6510_8502_undocumented_commands

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

base:6510_8502_undocumented_commands [2015-04-17 04:30] (current)
Line 1: Line 1:
 +====== 6510/8502 Undocumented Commands ======
 +
 +<​code>​
 +         -- A brief explanation about what may happen while
 +                using don't care states.
 +
 +
 +        ANE $8B         A = (A | #$EE) & X & #byte
 +                        same as
 +                        A = ((A & #$11 & X) | ( #$EE & X)) & #byte
 +
 +                        In real 6510/8502 the internal parameter #$11
 +                        may occasionally be #$10, #$01 or even #$00.
 +                        This occurs when the video chip starts DMA
 +                        between the opcode fetch and the parameter fetch
 +                        of the instruction. ​ The value probably depends
 +                        on the data that was left on the bus by the VIC-II.
 +
 +        LXA $AB         ​C=Lehti: ​  A = X = ANE
 +                        Alternate: A = X = (A & #byte)
 +
 +                        TXA and TAX have to be responsible for these.
 +
 +        SHA $93,​$9F ​    Store (A & X & (ADDR_HI + 1))
 +        SHX $9E         Store (X & (ADDR_HI + 1))
 +        SHY $9C         Store (Y & (ADDR_HI + 1))
 +        SHS $9B         SHA and TXS, where X is replaced by (A & X).
 +
 +                        Note: The value to be stored is copied also
 +                        to ADDR_HI if page boundary is crossed.
 +
 +        SBX $CB         Carry and Decimal flags are ignored but the
 +                        Carry flag will be set in substraction. This
 +                        is due to the CMP command, which is executed
 +                        instead of the real SBC.
 +
 +        ARR $6B         This instruction first performs an AND
 +                        between the accumulator and the immediate
 +                        parameter, then it shifts the accumulator to
 +                        the right. However, this is not the whole
 +                        truth. See the description below.
 +
 +Many undocumented commands do not use AND between registers, the CPU
 +just throws the bytes to a bus simultaneously and lets the
 +open-collector drivers perform the AND. I.e. the command called '​SAX',​
 +which is in the STORE section (opcodes $A0...$BF), stores the result
 +of (A & X) by this way.
 +
 +More fortunate is its opposite, '​LAX'​ which just loads a byte
 +simultaneously into both A and X.
 +
 +
 +        $6B  ARR
 +
 +This instruction seems to be a harmless combination of AND and ROR at
 +first sight, but it turns out that it affects the V flag and also has
 +a special kind of decimal mode. This is because the instruction has
 +inherited some properties of the ADC instruction ($69) in addition to
 +the ROR ($6A).
 +
 +In Binary mode (D flag clear), the instruction effectively does an AND
 +between the accumulator and the immediate parameter, and then shifts
 +the accumulator to the right, copying the C flag to the 8th bit. It
 +sets the Negative and Zero flags just like the ROR would. The ADC code
 +shows up in the Carry and oVerflow flags. The C flag will be copied
 +from the bit 6 of the result (which doesn'​t seem too logical), and the
 +V flag is the result of an Exclusive OR operation between the bit 6
 +and the bit 5 of the result. ​ This makes sense, since the V flag will
 +be normally set by an Exclusive OR, too.
 +
 +In Decimal mode (D flag set), the ARR instruction first performs the
 +AND and ROR, just like in Binary mode. The N flag will be copied from
 +the initial C flag, and the Z flag will be set according to the ROR
 +result, as expected. The V flag will be set if the bit 6 of the
 +accumulator changed its state between the AND and the ROR, cleared
 +otherwise.
 +
 +Now comes the funny part. If the low nybble of the AND result,
 +incremented by its lowmost bit, is greater than 5, the low nybble in
 +the ROR result will be incremented by 6. The low nybble may overflow
 +as a consequence of this BCD fixup, but the high nybble won't be
 +adjusted. The high nybble will be BCD fixed in a similar way. If the
 +high nybble of the AND result, incremented by its lowmost bit, is
 +greater than 5, the high nybble in the ROR result will be incremented
 +by 6, and the Carry flag will be set. Otherwise the C flag will be
 +cleared.
 +
 +To help you understand this description,​ here is a C routine that
 +illustrates the ARR operation in Decimal mode:
 +
 +        unsigned
 +           ​A, ​ /* Accumulator */
 +           AL, /* low nybble of accumulator */
 +           AH, /* high nybble of accumulator */
 +
 +           ​C, ​ /* Carry flag */
 +           ​Z, ​ /* Zero flag */
 +           ​V, ​ /* oVerflow flag */
 +           ​N, ​ /* Negative flag */
 +
 +           ​t, ​ /* temporary value */
 +           ​s; ​ /* value to be ARRed with Accumulator */
 +
 +        t = A & s;                      /* Perform the AND. */
 +
 +        AH = t >> 4;                    /* Separate the high */
 +        AL = t & 15;                    /* and low nybbles. */
 +
 +        N = C;                          /* Set the N and */
 +        Z = !(A = (t >> 1) | (C << 7)); /* Z flags traditionally */
 +        V = (t ^ A) & 64;               /* and V flag in a weird way. */
 +
 +        if (AL + (AL & 1) > 5)          /* BCD "​fixup"​ for low nybble. */
 +          A = (A & 0xF0) | ((A + 6) & 0xF);
 +
 +        if (C = AH + (AH & 1) > 5)      /* Set the Carry flag. */
 +          A = (A + 0x60) & 0xFF;        /* BCD "​fixup"​ for high nybble. */
 +
 +
 +
 +        $CB  SBX   X <- (A & X) - Immediate
 +
 +The '​SBX'​ ($CB) may seem to be very complex operation, even though it
 +is a combination of the subtraction of accumulator and parameter, as
 +in the '​CMP'​ instruction,​ and the command '​DEX'​. As a result, both A
 +and X are connected to ALU but only the subtraction takes place. Since
 +the comparison logic was used, the result of subtraction should be
 +normally ignored, but the '​DEX'​ now happily stores to X the value of
 +(A & X) - Immediate. ​ That is why this instruction does not have any
 +decimal mode, and it does not affect the V flag. Also Carry flag will
 +be ignored in the subtraction but set according to the result.
 +
 + ​Proof:​
 +
 +begin 644 vsbx
 +M`0@9$,​D'​GL(H-#,​IJC(U-JS"​*#​0T*:​HR-@```*D`H#​V1*Z`_D2N@09$KJ0>​%
 +M^QBE^VEZJ+$KH#​F1*ZD`2"​BI`*(`RP`(:​-B@.5$K*4#​P`E@`H#​VQ*SAI`)$K
 +JD-Z@/​[$K:​0"​1*Y#​4J2X@TO\XH$&​Q*VD`D2N0Q,;​[$+188/​_^]_:​_OK>​V
 +`
 +end
 +
 + and
 +
 +begin 644 sbx
 +M`0@9$,​D'​GL(H-#,​IJC(U-JS"​*#​0T*:​HR-@```'​BI`*!-D2N@3Y$KH%&​1*ZD#​
 +MA?​L8I?​M*2)`#​J1@LJ3B@29$K:​$J0`ZGX+*G8R)$K&/​BXJ?​2B8\L)AOP(:​(7]
 +MV#​B@3;​$KH$\Q*Z!1\2L(1?​SP`0!H1?​TIM]#​XH$VQ*SAI`)$KD,​N@3[$K:​0"​1
 +9*Y#​!J2X@TO\XH%&​Q*VD`D2N0L<;​[$))88-#​X
 +`
 +end
 +
 +These test programs show if your machine is compatible with ours
 +regarding the opcode $CB. The first test, vsbx, proves that SBX does
 +not affect the V flag. The latter one, sbx, proves the rest of our
 +theory. The vsbx test tests 33554432 SBX combinations (16777216
 +different A, X and Immediate combinations,​ and two different V flag
 +states), and the sbx test doubles that amount (16777216*4 D and C flag
 +combinations). Both tests have run successfully on a C64 and a Vic20.
 +They ought to run on C16, +4 and the PET series as well. The tests
 +stop with BRK, if the opcode $CB does not work as expected. Successful
 +operation ends in RTS. As the tests are very slow, they print dots on
 +the screen while running so that you know that the machine has not
 +jammed. On computers running at 1 MHz, the first test prints
 +approximately one dot every four seconds and a total of 2048 dots,
 +whereas the second one prints half that amount, one dot every seven
 +seconds.
 +
 +If the tests fail on your machine, please let us know your processor'​s
 +part number and revision. If possible, save the executable (after it
 +has stopped with BRK) under another name and send it to us so that we
 +know at which stage the program stopped.
 +
 +The following program is a Commodore 64 executable that Marko M"​akel"​a
 +developed when trying to find out how the V flag is affected by SBX.
 +(It was believed that the SBX affects the flag in a weird way, and
 +this program shows how SBX sets the flag differently from SBC.)  You
 +may find the subroutine at $C150 useful when researching other
 +undocumented instructions'​ flags. Run the program in a machine
 +language monitor, as it makes use of the BRK instruction. The result
 +tables will be written on pages $C2 and $C3.
 +
 +begin 644 sbx-c100
 +M`,​%XH`",#​L&,​$,&,​$L&​XJ8*B@LL7AOL(:​(7\N#​BM#​L$M$,'​M$L$(Q?​OP`B@`
 +M:​$7\\`,​@4,'​N#​L'​0U.X0P=#/​SB#​0[A+!T,<​``````````````)BJ\!>​M#​L$M
 +L$,'​=_\'​0":​T2P=W_PM`!8,​K0Z:​T.P2T0P9D`PID`!*T2P9D`PYD`!<​C0Y``M
 +`
 +end
 +
 +
 +Other undocumented instructions usually cause two preceding opcodes
 +being executed. However '​NOP'​ seems to completely disappear from '​SBC'​
 +code $EB.
 +
 +The most difficult to comprehend are the rest of the instructions
 +located on the '​$0B'​ line.
 +
 +All the instructions located at the positive (left) side of this line
 +should rotate either memory or the accumulator,​ but the addressing
 +mode turns out to be immediate! No problem. Just read the operand, let
 +it be ANDed with the accumulator and finally use accumulator
 +addressing mode for the instructions above them.
 +
 +RELIGION_MODE_ON
 +/* This part of the document is not accurate. ​ You can
 +   read it as a fairy tale, but do not count on it when
 +   ​performing your own measurements. */
 +
 +The rest two instructions on the same line, called '​ANE'​ and '​LXA'​
 +($8B and $AB respectively) often give quite unpredictable results.
 +However, the most usual operation is to store ((A | #$ee) & X & #$nn)
 +to accumulator. Note that this does not work reliably in a real 64!
 +In the Commodore 128 the opcode $8B uses values 8C, CC, EE, and
 +occasionally 0C and 8E for the OR instead of EE,EF,FE and FF used in
 +the C64. With a C128 running at 2 MHz #$EE is always used.  Opcode $AB
 +does not cause this OR taking place on 8502 while 6510 always performs
 +it. Note that this behaviour depends on processor and/or video chip
 +revision.
 +
 +Let's take a closer look at $8B (6510).
 +
 +        A <- X & D & (A | VAL)
 +
 +        where VAL comes from this table:
 +
 +       X high   D high  D low   VAL
 +        even     ​even ​   ---    $EE (1)
 +        even     ​odd ​    ​--- ​   $EE
 +        odd      even    ---    $EE
 +        odd      odd      0     $EE
 +        odd      odd     not 0  $FE (2)
 +
 +(1) If the bottom 2 bits of A are both 1, then the LSB of the result may
 +    be 0. The values of X and D are different every time I run the test.
 +    This appears to be very rare.
 +(2) VAL is $FE most of the time. Sometimes it is $EE - it seems to be random,
 +    not related to any of the data. This is much more common than (1).
 +
 +  In decimal mode, VAL is usually $FE.
 +
 +
 +Two different functions have been discovered for LAX, opcode $AB. One
 +is A = X = ANE (see above) and the other, encountered with 6510 and
 +8502, is less complicated A = X = (A & #byte). However, according to
 +what is reported, the version altering only the lowest bits of each
 +nybble seems to be more common.
 +
 +What happens, is that $AB loads a value into both A and X, ANDing the
 +low bit of each nybble with the corresponding bit of the old
 +A. However, there are exceptions. Sometimes the low bit is cleared
 +even when A contains a '​1',​ and sometimes other bits are cleared. The
 +exceptions seem random (they change every time I run the test). Oops -
 +that was in decimal mode. Much the same with D=0.
 +
 +What causes the randomness? ​ Probably it is that it is marginal logic
 +levels - when too much wired-anding goes on, some of the signals get
 +very close to the threshold. Perhaps we're seeing some of them step
 +over it. The low bit of each nybble is special, since it has to cope
 +with carry differently (remember decimal mode). We never see a '​0'​
 +turn into a '​1'​.
 +
 +Since these instructions are unpredictable,​ they should not be used.
 +
 +There is still very strange instruction left, the one named SHA/X/Y,
 +which is the only one with only indexed addressing modes. Actually,
 +the commands '​SHA',​ '​SHX'​ and '​SHY'​ are generated by the indexing
 +algorithm.
 +
 +While using indexed addressing, effective address for page boundary
 +crossing is calculated as soon as possible so it does not slow down
 +operation. As a result, in the case of SHA/X/Y, the address and data
 +are processed at the same time making AND between them to take place.
 +Thus, the value to be stored by SAX, for example, is in fact (A & X &
 +(ADDR_HI + 1)).  On page boundary crossing the same value is copied
 +also to high byte of the effective address.
 +
 +RELIGION_MODE_OFF
 +</​code>​
  
base/6510_8502_undocumented_commands.txt ยท Last modified: 2015-04-17 04:30 (external edit)