NOTE: Not quite up to date with latest changes in StellaIn fetcher mode, the cartridge will dynamically generate 6502 code to implement a specialized instruction set. Every instruction will be 16 bits, and will take 2 to 4 cycles to execute. Instructions will be assigned 4-5 character mnemonics to distinguish them from 6507 opcodes. Opcodes ending with "+" may have an "L" or "J" suffix to specify that they should do "Loop-test" or "Jump-loop" (see below) in addition to their normal function.
The JX10 Fetcher itself keeps three pieces of state information, all of them addresses: the next JX10 instruction, the fetcher group 0 table, the and fetcher group 1 table. All other state is manged by performing read-modify-write operations on the data in the fetcher tables, or memory pointed at by such data; any of these latter changes will be directly visible to the target application.
REST+ | 3 cycles | JMP $1010
| This instruction takes 3 cycles to execute. A REST instruction must be done at least once every 4,000 cycles or the Atari may malfunction. It translates into JMP $1010.
| QUIT addr | (EXITS) | JMP addr
| Generates an "JMP a" instruction and returns to normal code execution.
| LIMA value LIMX value LIMY value | 2 cycles | LDA #value LDX #value LDY #value
| Load A, X, or Y with an 8-bit immediate value
| LDFA group,fetcher,inc LDFX group,fetcher,inc LDFY group,fetcher,inc | 2 cycles | LDA #data LDX #data LDY #data
| Load A, X, or Y from fetcher #f of group #g and increment it by i. (lda #imm, etc.)
| SDRA+ addr SDRX+ addr SDRY+ addr SDRQ+ addr | 3 cycles | STA addr STX addr STY addr SAX addr
| Store A, X, Y, or (A&X) to specified TIA address
| SSDA+ addr SSDX+ addr SSDY+ addr SSDQ+ addr | 4 cycles | STA.w addr STX.w addr STY.w addr SAX.w addr
| As above, but takes 4 cycles.
| SDFR group,fetcher,inc | 3 cycles | STA addr STX addr STY addr SAX addr
| Get a byte from fetcher #f or group #g, increment it by i, generate a STA, STX, STY, or SAX instruction. Use top two bits of fetched value to select instruction; remaining 6 bits for address.
| SSFR group,fetcher,inc | 4 cycles | STA.w addr STX.w addr STY.w addr SAX.w addr
| As above, but takes 4 cycles (sta abs, etc.)
| TSTS addr,g,f | 3 cycles | BIT addr
| Read specified address and store the result to RAM pointed at by the specified fetcher (single-increment mode only). Useful for collision detection.
| TSTI addr,group,fetcher | 3 cycles | BIT addr
| Read the specified address and increment the upper byte of the indicated fetcher if bit 7 is set, and/or the lower byte if bit 6 is set. Useful for paddles. |
|
The system has two fetcher-pointers. To perform a fetch-retrieval (e.g. for "LDFA") the system selects one of the pointers using the "g" bit. It then performs the following logic:
addr1 = ptr + f*2 addr2 = memw[addr1] dat = mem[addr2] generate opcode from dat if i<>max then addr2 += i else addr3 = memw[addr1+2] dat = mem[addr3], and update flags if dat was zero addr3++ else dat-- mem[addr3]=dat endif if addr3 is odd then addr2++ endif memw[addr1] = addr2
|
Loop-test and Jump-loop behavior:
dat = mem[fetchptr0-4] if dat=0 fetchptr0 = memw[fetchptr0 - 2] fetchptr1 = memw[fetchptr0-8] ' Use new value of fp0 virtpc = memw[fetchotr0-6] else dat-- memw[fetchptr0-4] = dat dat = mem[fetchptr1-4] if dat=0 fetchptr1 = memw[fetchptr1 - 2] else dat-- memw[fetchptr1-4] = dat endif if (is jump-loop instruction) virtpc = memw[fetchptr1-6] endif endif
|
JX10 Banking
Notes
- Hexadecimal constants are preceded by a dollarsign. Within a hex constant, "L" means any digit 0-7, "H" means any digit 8-F, "J" means any odd digit, "N" means any even digit, and "X" means any digit.
- Certain operations are explicitly described as "forbidden". The effect of forbidden operations may vary between different versions of the ARM code; it is recommended that emulation stop if code performs a forbidden operation.
- There is going to be a "super-fetcher" mode, details TBD, which behaves totally differently from what's described here; any emulator design must be able to switch between normal mode and super-fetcher mode.
Atari Programming
There are eight code banks, distinguished by bits 13-15 of the address. Cartridge code execution is only permited at an address of $JHXX, and RIOT RAM code execution is only permitted at $V8HX. Except as provided below, any JMP, JSR, or RTS will cause a bank switch to the bank specified by the top three bits:
Bank 0 | $1HXX | RAM $1HXX
|
Bank 1 | $3HXX | ROM $0HXX
|
Bank 2 | $5HXX | ROM $1LXX
|
Bank 3 | $7HXX | ROM $1HXX
|
Bank 4 | $9HXX | ROM $2LXX
|
Bank 5 | $BHXX | ROM $2HXX
|
Bank 6 | $DHXX | ROM $3LXX
|
Bank 7 | $FHXX | ROM $3HXX
|
Jumping into RIOT RAM will also trigger a bank switch based upon the upper address bits (e.g. a jump to $08HX will switch to bank 0, $28HX will switch to bank 1, etc.)
Restrictions:
- A JMP or JSR instruction which starts at address N must not jump to an address that is a multiple of 8K bytes from N+2 or N+3, except that a JMP instruction may target the next address in sequence in the same bank.
- Any data fetches from $JHXX must be in the same bank as the code performing them (this restriction applies even when code is running from RIOT RAM; e.g., if RIOT RAM is entered via "JMP $4880", it may may access ROM at $5800-$5FFF, but may not access $1800-$1FFF, $3800-$3FFF, etc.
There are eight switchable data-banking areas, located at $JLXX (i.e. $1000-$17FF, $3000-$37FF, etc.) Each zone is controlled via various hot-spots at $V200-$VF7F. The $1000-$17FF zone is controlled by various hot-spots at $0200-$0F7F, the $3000-$37FF zone is controlled by hot-spots at $2200-$2F7F, etc. Hot-spots are as follows. Note that access to any addresses in the range $V200-$VFFF other than those listed below is forbidden (future functions will likely be added).
Hot-spots (more will follow):
$V000-$V0FF | Zero-page trigger (used to determine bank for (ZP,X) and (ZP),Y address
|
$V100-$V1FF | Stack trigger (used to determine bank for JSR or RTS address)
|
$V280-$V2FF | RIOT registers (no banking action)
|
$V400-$V4FF | Set LSB of banking address (MSB unaffected)
|
$V500-$V5FF | Set MSB of banking address (LSB unaffected)
|
$V600-$V601 | Set bank mode (values below)
|
$V700-$v71F | Map bank to RAM at $0000-$1F00 (LSB cleared)
|
$V880-$V8FF | Executable RIOT RAM
|
$V900-$V97F | Map bank to ROM at $0000-$7F00 (LSB cleared)
|
$VC00-$VCFF | Add $0000-$00FF to bank address
|
$VD00-$VDFF | Subtract $0000-$00FF from bank address
|
$VE00-$VE1F | Add $0000-$1F00 to bank address
|
$VE40-$VE5F | Subtract $0000-$1F00 from bank address
|
Banking modes (more will follow):
0 | Access ROM (read-only; writes forbidden)
|
1 | Access RAM (reads or ST* instructions; read-modify-write forbidden)
|
Implementation Notes
The implementation needs to keep track of the address and mode for each of the eight code banks. It also needs to keep a 16-bit variable called
"LastCodeAddr" and a 32-bit variable called "RecentCode".
Addresses are divided into a few groups. Note that most of the hot-spots are treated similarly; for simplicity, they are simply called "hot-spot" below. All addresses given are physical 13-bit address-bus addresses. An emulator may check upper bits to ensure they are as expected.
- $0000-$00FF
- Wait until address is seen greater than $01FF. Then set RecentCode to ((RecentCode shl 8) or data)
- $0100-$01FF
- If RecentCode[15..8] is $60, set RecentCode to $00004C00 and clear LastCodeAddr. If RecentCode[15..8] is $20, set RecentCode to $0000004C (leave RecentAddr alone). If neither condition applies, clear RecentCode. In any case, wait until address is seen greater than $01FF and handle RecentCode as with $00XX.
- General hot-spot
- Use RecentCode[7..5] to select a one of eight banks, and apply hot-spot behavior to that bank.
- $0880-$08FF
- Banking behavior is like $1800-$1FFF.
- $1000-$17FF
- Use RecentCode[7..5] to select one of eight banks, and treat according to that bank mode. If RAM, if RecentCode[23-16] is $80-$9F, handle as a write; otherwise handle as a read.
- $1800-$1FFF
- If address does matches LastCodeAddr or LastCodeAddr+1, set RecentCode to ((RecentCode shl 8) or data). Otherwise, if RecentCode[23..16] is 0x4C, set code bank based on RecentCode[7..5]; if address hadn't matched, clear RecentCode.
Super-Fetcher mode (preview)
In super-fetcher mode, all addresses $JXXX will be treated identically. The cartridge will maintain its own program counter, and execute two-byte super-instructions. Each super-instruction will generate the data for one or more bus cycles. Some typical super-instructions would be "Load accomulator from fetcher 19", "Store X in COLUP1", and "stuff a 6507 'JMP $1000' instruction. Note that disassembly via normal means will be totally meaningless.