summaryrefslogtreecommitdiffstatshomepage
path: root/docs/source/techspecs/m6502.rst
diff options
context:
space:
mode:
Diffstat (limited to 'docs/source/techspecs/m6502.rst')
-rw-r--r--docs/source/techspecs/m6502.rst24
1 files changed, 12 insertions, 12 deletions
diff --git a/docs/source/techspecs/m6502.rst b/docs/source/techspecs/m6502.rst
index dbc7a0a02a5..c4cb45f5cea 100644
--- a/docs/source/techspecs/m6502.rst
+++ b/docs/source/techspecs/m6502.rst
@@ -21,7 +21,7 @@ The 6502 family
The MOS 6502 family has been large and productive. A large number of variants exist, varying on bus sizes, I/O, and even opcodes. Some offshots (g65c816, hu6280) even exist that live elsewhere in the mame tree. The final class hierarchy is this:
::
-
+
6502
|
+------+--------+--+--+-------+-------+
@@ -35,8 +35,8 @@ The MOS 6502 family has been large and productive. A large number of variants ex
65ce02 65sc02
|
4510
-
-
+
+
The 6510 adds an up to 8 bits I/O port, with the 6510t, 7501 and 8502 being software-identical variants with different pin count (hence I/O count), die process (NMOS, HNMOS, etc) and clock support.
@@ -181,7 +181,7 @@ The generated code
A code generator is used to support interrupting and restarting an instruction in the middle. This is done through a two-level state machine with updates only at the boundaries. More precisely, inst_state tells you which main state you're in. It's equal to the opcode byte when 0-255, and 0xff00 means reset. It's always valid and used by instructions like rmb. inst_substate indicates at which step we are in an instruction, but it set only when an instruction has been interrupted. Let's go back to the asl <abs> code:
-|
+|
| asl_aba
| TMP = read_pc();
| TMP = set_h(TMP, read_pc());
@@ -190,7 +190,7 @@ A code generator is used to support interrupting and restarting an instruction i
| TMP2 = do_asl(TMP2);
| write(TMP, TMP2);
| prefetch();
-|
+|
The complete generated code is:
@@ -226,11 +226,11 @@ The complete generated code is:
| }
| inst_substate = 0;
| }
-|
+|
One can see that the initial switch() restarts the instruction at the appropriate substate, that icount is updated after each access, and upon reaching 0 the instruction is interrupted and the substate updated. Since most instructions are started from the beginning a specific variant is generated for when inst_substate is known to be 0:
-|
+|
| void m6502_device::asl_aba_full()
| {
| if(icount == 0) { inst_substate = 1; return; }
@@ -253,7 +253,7 @@ One can see that the initial switch() restarts the instruction at the appropriat
| prefetch();
| icount--;
| }
-|
+|
That variant removes the switch, avoiding a costly computed branch and also an inst_substate write. There is in addition a fair chance that the decrement-test with zero pair is compiled into something efficient.
@@ -265,7 +265,7 @@ The execute main call ends up very simple:
| {
| if(inst_substate)
| do_exec_partial();
-|
+|
| while(icount > 0) {
| if(inst_state < 0x100) {
| PPC = NPC;
@@ -342,10 +342,10 @@ A modern try/catch costs nothing if an exception is not thrown. Using this the c
| icount -= waiting_cycles;
| waiting_cycles = 0;
| }
-|
+|
| if(icount > 0 && inst_substate)
| do_exec_partial();
-|
+|
| while(icount > 0) {
| if(inst_state < 0x100) {
| PPC = NPC;
@@ -355,7 +355,7 @@ A modern try/catch costs nothing if an exception is not thrown. Using this the c
| }
| do_exec_full();
| }
-|
+|
| waiting_cycles = -icount;
| icount = 0;
| }