Anonymous

Contended memory: Difference between revisions

From Sinclair Wiki
m
IO → I/O as per Zilog Z80 and Spectrum BASIC manuals and Wikipedia
m (IO → I/O as per Zilog Z80 and Spectrum BASIC manuals and Wikipedia)
Line 1: Line 1:
'''Contended memory''' is a quirk of the ZX Spectrum's hardware design which means that it is on average slower to access those memory areas which are shared with the ULA than it is to access other memory areas. This occurs because the RAM cannot be read by two devices (the ULA and the processor) at once, and the ULA is given higher priority so it can drawn the screen correctly. Therefore, programs which access this "contended memory" (which is from 0x4000 to 0x7fff on the 48K machine, which is the actual 16K version) or try to read from an IO port where the result is provided by the ULA (any port with the low bit reset on the 48K machine) will be slowed if the ULA is reading the screen. This effect occurs only when the actual screen is being drawn; when the border is being drawn or the TV is in either horizontal or vertical refresh, the ULA does not need to access memory and therefore no delays occur.
'''Contended memory''' is a quirk of the ZX Spectrum's hardware design which means that it is on average slower to access those memory areas which are shared with the ULA than it is to access other memory areas. This occurs because the RAM cannot be read by two devices (the ULA and the processor) at once, and the ULA is given higher priority so it can drawn the screen correctly. Therefore, programs which access this "contended memory" (which is from 0x4000 to 0x7fff on the 48K machine, which is the actual 16K version) or try to read from an I/O port where the result is provided by the ULA (any port with the low bit reset on the 48K machine) will be slowed if the ULA is reading the screen. This effect occurs only when the actual screen is being drawn; when the border is being drawn or the TV is in either horizontal or vertical refresh, the ULA does not need to access memory and therefore no delays occur.


== General principles ==
== General principles ==


In order for the ULA to be able to access the memory it needs without problems being caused by the Z80 attempting to access the memory at the same time, the ULA arranges for the Z80 to be temporarily paused if the Z80 attempts to access the appropriate memory or IO ports; the exact details of which memory is affected and at which times is given in the [[#Details|Details]] section below. For memory access, this happens on the first tstate (T1) of any instruction fetch, memory read or memory write operation.<ref>http://www.zxdesign.info/memContRevision.shtml</ref> For IO operations, this can happen on all tstates; see the [[Contended IO]] article for the specifics. The [[#Instruction breakdown|table below]] gives the pattern of contention that is applied for each opcode, which is essentially equivalent to when T1 operations happen in each instruction.
In order for the ULA to be able to access the memory it needs without problems being caused by the Z80 attempting to access the memory at the same time, the ULA arranges for the Z80 to be temporarily paused if the Z80 attempts to access the appropriate memory or I/O ports; the exact details of which memory is affected and at which times is given in the [[#Details|Details]] section below. For memory access, this happens on the first tstate (T1) of any instruction fetch, memory read or memory write operation.<ref>http://www.zxdesign.info/memContRevision.shtml</ref> For I/O operations, this can happen on all tstates; see the [[Contended I/O]] article for the specifics. The [[#Instruction breakdown|table below]] gives the pattern of contention that is applied for each opcode, which is essentially equivalent to when T1 operations happen in each instruction.


== Details  ==
== Details  ==
Line 187: Line 187:
* The undocumented variants of the doubly shifted DDCB and FDCB opcodes have the same timings as the documented versions.
* The undocumented variants of the doubly shifted DDCB and FDCB opcodes have the same timings as the documented versions.
* In some read-modify-write operations (like INC (HL)), the write operation is always the last one. That may be important to know the exact point in which video is updated, for example. In such instructions that point is annotated for clarity as "(write)" after the address.
* In some read-modify-write operations (like INC (HL)), the write operation is always the last one. That may be important to know the exact point in which video is updated, for example. In such instructions that point is annotated for clarity as "(write)" after the address.
* Access to I/O ports is treated differently to access to memory; full details are given [[Contended IO]]. The delays specified there should be applied when an I/O port is accessed; this is designated by "IO" in the table below.
* Access to I/O ports is treated differently to access to memory; full details are given [[Contended I/O]]. The delays specified there should be applied when an I/O port is accessed; this is designated by "I/O" in the table below.


In the table below, contention patterns which differ on the +2A/+3 are shown in '''bold''' in the '+3 ULA' column, with sections of 48K-specific contention shown in '''bold''' in the '48K/128K ULA' column.  T-state counts associated with the 48K-specific contention still apply to the +2A/+3 pattern, but the contention itself does not.  With 48K-contention excluded, the timings in both columns are identical.
In the table below, contention patterns which differ on the +2A/+3 are shown in '''bold''' in the '+3 ULA' column, with sections of 48K-specific contention shown in '''bold''' in the '48K/128K ULA' column.  T-state counts associated with the 48K-specific contention still apply to the +2A/+3 pattern, but the contention itself does not.  With 48K-contention excluded, the timings in both columns are identical.
Line 411: Line 411:
|-
|-
| IN A,(n)
| IN A,(n)
| rowspan=2 | pc:4,pc+1:3,IO
| rowspan=2 | pc:4,pc+1:3,I/O
| rowspan=2 | pc:4,pc+1:3,IO
| rowspan=2 | pc:4,pc+1:3,I/O
|-
|-
| OUT (n),A
| OUT (n),A
|-
|-
| IN r,(C)
| IN r,(C)
| rowspan=2 | pc:4,pc+1:4,IO
| rowspan=2 | pc:4,pc+1:4,I/O
| rowspan=2 | pc:4,pc+1:4,IO
| rowspan=2 | pc:4,pc+1:4,I/O
|-
|-
| OUT (C),r
| OUT (C),r
Line 439: Line 439:
|-
|-
| INI/INIR
| INI/INIR
| rowspan=2 | pc:4,pc+1:4,'''ir''':1,IO,hl:3,['''hl''':1 ×5]
| rowspan=2 | pc:4,pc+1:4,'''ir''':1,I/O,hl:3,['''hl''':1 ×5]
| rowspan=2 | '''pc:4,pc+1:5,IO,hl:3,[5]'''
| rowspan=2 | '''pc:4,pc+1:5,I/O,hl:3,[5]'''
|-
|-
| IND/INDR
| IND/INDR
|-
|-
| OUTI/OTIR
| OUTI/OTIR
| rowspan=2 | pc:4,pc+1:4,'''ir''':1,hl:3,IO,['''bc''':1 ×5]
| rowspan=2 | pc:4,pc+1:4,'''ir''':1,hl:3,I/O,['''bc''':1 ×5]
| rowspan=2 | '''pc:4,pc+1:5,hl:3,IO,[5]'''
| rowspan=2 | '''pc:4,pc+1:5,hl:3,I/O,[5]'''
|-
|-
| OUTD/OTDR
| OUTD/OTDR