Overview
Memory Map
I/O Map
Open Bus
Cartridge
ROM Header
Hardware Architecture
System Reset
About
Change Colors
System Components
CPU - V30MZ/V Series Microprocessor
DMA - Direct Memory Access
LCD Panel
Sound
Keypad
Serial EEPROM
RTC - Real-Time Clock
The WonderSwan memory bus is 20 bits wide and is organized by memory type:
0x00000 - 0x0FFFF |
WRAM |
0x10000 - 0x1FFFF |
Cartridge SRAM |
0x20000 - 0x2FFFF |
Cartridge ROM bank 0 |
0x30000 - 0x3FFFF |
Cartridge ROM bank 1 |
0x40000 - 0xFFFFF |
Cartridge ROM bank EX |
Because the CPU registers are 16-bit and the bus is 20-bit, multiple registers are needed to represent a complete physical address. This is achieved through the use of the segment registers.
When constructing a physical address, one register is used normally as a 16-bit value called the offset. A second value called the segment is then produced by taking the value in the appropriate segment register and shifting it left 4 bits. This shifted segment value is then added to the offset to produce the final 20-bit physical address.
Physical addresses are a maximum of 20 bits wide. If the computation of a
physical address exceeds 0xFFFFF
, the value will wrap back
around to 0x00000
and continue up from there.
If a 16-bit memory access is performed on an odd offset (the lowest bit is
set), it is silently converted into two 8-bit accesses instead. In this
situation, one additional CPU cycle is spent. The
physical address is computed independently
for each byte, with the offset being incremented for the second byte before
incorporating the bits from the segment. For this reason, any 16-bit access
with an offset of 0xFFFF
will access two non-consecutive bytes
in memory.
WRAM is built-in, general-purpose working memory. The size of WRAM varies depending on whether or not color mode is enabled:
• Disabled | 16 KiB |
• Enabled | 64 KiB |
WRAM is further organized as follows:
0x00000 - 0x003FF |
Exception vectors |
0x00400 - 0x01FFF |
Scratch memory |
0x02000 - 0x03FFF |
Characters |
0x04000 - 0x0BFFF [color]
|
Characters |
0x0C000 - 0x0FDFF [color]
|
Scratch memory |
0x0FE00 - 0x0FFFF [color]
|
Color palettes |
[color] | These addresses are only available in color mode. When accessed on the monochrome model or on a color model with color mode disabled, they function as open bus. |
Some cartridges contain save RAM (SRAM), which is volatile memory that is
typically made persistent via a battery for use with games requiring save
functionality. SRAM is partitioned into 64 KiB banks, one of which is mapped
onto the memory bus at any given time in the SRAM address range
0x10000
- 0x1FFFF
.
Memory mapping for SRAM is managed through the following I/O ports:
0xC1 | Byte | RAM_BANK | RAM bank (shadow of lower byte) |
0xD0 | Byte |
RAM_BANK_L [2003]
|
RAM bank (lower byte) |
0xD1 | Byte |
RAM_BANK_H [2003]
|
RAM bank (upper byte) |
[2003] | These ports are only available on the 2003 mapper. |
All 8 bits of RAM_BANK
and RAM_BANK_L
, and the
lowest 2 bits of RAM_BANK_H
, can be managed by the program. The
upper 6 bits of RAM_BANK_H
are clear when read.
On the 2001 mapper, the bank setting is 8-bit and is
taken from RAM_BANK
. On the 2003 mapper, RAM_BANK
is a mirror of RAM_BANK_L
, and the bank setting is 10-bit and is
formed by the combination of RAM_BANK_H
for the high bits and
RAM_BANK_L
for the low bits.
When accessing SRAM, the 20-bit physical
address is transformed into a 32-bit offset into the cartridge memory.
The lower 16 bits of the cartridge offset are taken from the lower 16 bits of
the physical address. The upper 16 bits of the cartridge offset are taken
from RAM_BANK
or RAM_BANK_H
and
RAM_BANK_L
as described above.
The implementation silently converts word accesses in the cartridge SRAM range into consecutive pairs of byte accesses, adding one additional CPU cycle in the process. The SRAM interface is 8-bit, so it cannot be used with the DMA feature.
During system reset, these ports are initialized
with 0xFF
. After mirroring, this corresponds to the last bank of
SRAM data.
Read-only memory (ROM) is non-volatile cartridge memory that serves as the
source for data assets and program code. ROM is partitioned into 64 KiB
banks, up to 14 of which are mapped onto the memory bus at any given time in
the ROM address ranges 0x20000
- 0xFFFF
.
Memory mapping for the 0x20000
- 0x2FFFF
and
0x30000
- 0x3FFFF
address ranges is managed through
the following I/O ports:
0xC2 | Byte | ROM_BANK_0 | ROM bank #0 (shadow of lower byte) |
0xC3 | Byte | ROM_BANK_1 | ROM bank #1 (shadow of lower byte) |
0xD2 | Byte |
ROM_BANK_0_L [2003]
|
ROM bank #0 (lower byte) |
0xD3 | Byte |
ROM_BANK_0_H [2003]
|
ROM bank #0 (upper byte) |
0xD4 | Byte |
ROM_BANK_1_L [2003]
|
ROM bank #1 (lower byte) |
0xD5 | Byte |
ROM_BANK_1_H [2003]
|
ROM bank #1 (upper byte) |
[2003] | These ports are only available on the 2003 mapper. |
All 8 bits of all six ports can be managed by the program. The
"_0
" ports control which ROM bank is mapped to the
0x20000
- 0x2FFFF
address range and the
"_1
" ports control which ROM bank is mapped to the
0x30000
- 0x3FFFF
address range.
On the 2001 mapper, the bank setting is 8-bit and is
taken from ROM_BANK_0
or ROM_BANK_1
. On the 2003
mapper, ROM_BANK_0
and ROM_BANK_1
are mirrors of
ROM_BANK_0_L
and ROM_BANK_1_L
respectively, and the
bank setting is 16-bit and is formed by the combination of the appropriate
"_H" port for the high bits and the "_L" port for the low bits.
When accessing ROM in these ranges, the 20-bit
physical address is transformed into a
32-bit offset into the cartridge memory. The lower 16 bits of the cartridge
offset are taken from the lower 16 bits of the physical address. The upper 16
bits of the cartridge offset are taken from the corresponding
"ROM_BANK_
" or "_H
" and "_L
" ports as
described above.
During system reset, these ports are initialized
with 0xFF
. After mirroring, this corresponds to the last bank of
ROM data.
Memory mapping for the 0x40000
- 0xFFFFF
address
range is managed through the following port:
0xC0 | Byte | LINEAR_ADDR_OFF | Linear address offset |
7 | 0 | ||||||
Bank | |||||||
8 |
Bank | R/W | The high-order bits of the active bank indexes. |
All 20 bits of the physical address contribute to the memory offset into
cartridge ROM for this address range. Additional offset bits beginning with
bit 20 are taken from LINEAR_ADDR_OFF
for a total of 28 bits.
During system reset, this port is initialized
with 0xFF
. After mirroring, this corresponds to the last 12
banks of ROM data.
The WonderSwan I/O bus is 8 bits wide. The program accesses it through the IN and OUT instructions.
If a 16-bit port access is performed on an odd address (the lowest bit is set), it is silently converted into two 8-bit accesses instead. In this situation, one additional CPU cycle is spent.
The following I/O ports are available:
0x00 | Word | DISPLAY_CTRL | Display control |
0x02 | Byte | LCD_LINE | Drawing line position |
0x03 | Byte | LCD_INTERRUPT | Drawing line interrupt |
0x04 | Byte | SPR_AREA | SPR character definition area specification |
0x05 | Byte | SPR_START_NO | SPR drawing first character number |
0x06 | Byte | SPR_CNT | Number of SPR characters |
0x07 | Byte | SCR_AREA | SCR character definition area specification |
0x08 | Byte | SCR2_WIN_X1 | SCR2 Window upper left (X axis) |
0x09 | Byte | SCR2_WIN_Y1 | SCR2 Window upper left (Y axis) |
0x0A | Byte | SCR2_WIN_X2 | SCR2 lower right of window (X axis) |
0x0B | Byte | SCR2_WIN_Y2 | SCR2 lower right of window (Y axis) |
0x0C | Byte | SPR_WIN_X1 | SPR window upper left (X axis) |
0x0D | Byte | SPR_WIN_Y1 | SPR window upper left (Y axis) |
0x0E | Byte | SPR_WIN_X2 | SPR window bottom right (X axis) |
0x0F | Byte | SPR_WIN_Y2 | SPR window bottom right (Y axis) |
0x10 | Byte | SCR1_SCRL_X | SCR1 scroll (X axis) |
0x11 | Byte | SCR1_SCRL_Y | SCR1 scroll (Y axis) |
0x12 | Byte | SCR2_SCRL_X | SCR2 scroll (X axis) |
0x13 | Byte | SCR2_SCRL_Y | SCR2 scroll (Y axis) |
0x14 | Byte | LCD_IF_CTRL | LCD interface control |
0x15 | Byte | LCD_SEG_DATA | Segment display data |
0x16 | Byte | LCD_VTOTAL [note] | LCD total line count |
0x17 | Byte | LCD_VSYNC [note] | LCD back porch line count |
0x1A | Byte | LCD_VOLUME [note] | LCD volume status |
0x1C | Byte | LCD_GRAY_01 | LCD LUT #0/#1 |
0x1D | Byte | LCD_GRAY_23 | LCD LUT #2/#3 |
0x1E | Byte | LCD_GRAY_45 | LCD LUT #4/#5 |
0x1F | Byte | LCD_GRAY_67 | LCD LUT #6/#7 |
0x20 | Word | SCR_LUT_0 | SCR character LUT #0 |
0x22 | Word | SCR_LUT_1 | SCR character LUT #1 |
0x24 | Word | SCR_LUT_2 | SCR character LUT #2 |
0x26 | Word | SCR_LUT_3 | SCR character LUT #3 |
0x28 | Word | SCR_LUT_4 | SCR character LUT #4 |
0x2A | Word | SCR_LUT_5 | SCR character LUT #5 |
0x2C | Word | SCR_LUT_6 | SCR character LUT #6 |
0x2E | Word | SCR_LUT_7 | SCR character LUT #7 |
0x30 | Word | SPR_LUT_0 | SPR character LUT #0 |
0x32 | Word | SPR_LUT_1 | SPR character LUT #1 |
0x34 | Word | SPR_LUT_2 | SPR character LUT #2 |
0x36 | Word | SPR_LUT_3 | SPR character LUT #3 |
0x38 | Word | SPR_LUT_4 | SPR character LUT #4 |
0x3A | Word | SPR_LUT_5 | SPR character LUT #5 |
0x3C | Word | SPR_LUT_6 | SPR character LUT #6 |
0x3E | Word | SPR_LUT_7 | SPR character LUT #7 |
0x40 | Word | GDMA_SOURCE_L [color] | General-purpose DMA source address (lower 16 bits) |
0x42 | Word | GDMA_SOURCE_H [color] | General-purpose DMA source address (upper 4 bits) |
0x44 | Word | GDMA_DESTINATION [color] | General-purpose DMA destination address |
0x46 | Word | GDMA_COUNTER [color] | General-purpose DMA data transfer amount |
0x48 | Byte | GDMA_CTRL [color] | General purpose DMA control |
0x4A | Word | SDMA_SOURCE_L [color] | Sound DMA source address (lower 16 bits) |
0x4C | Word | SDMA_SOURCE_H [color] | Sound DMA source address (upper 4 bits) |
0x4E | Word | SDMA_COUNTER_L [color] | Sound DMA data transfer amount (lower 16 bits) |
0x50 | Word | SDMA_COUNTER_H [color] | Sound DMA data transfer amount (upper 4 bits) |
0x52 | Byte | SDMA_CTRL [color] | Sound DMA control |
0x60 | Byte | SYSTEM_CTRL2 [color] | System control 2 |
0x62 | Byte | SYSTEM_CTRL3 [color] | System control 3 |
0x64 | Word | HYPERV_L [color, note] | Left channel Hyper Voice |
0x66 | Word | HYPERV_R [color, note] | Right channel Hyper Voice |
0x68 | Byte | HYPERV_SL [color, note] | Left channel Hyper Voice input |
0x69 | Byte | HYPERV_SR [color, note] | Right channel Hyper Voice input |
0x6A | Word | HYPERV_CTRL [color] | Hyper Voice Control |
0x80 | Word | SND_FREQ_1 | Sound channel 1 frequency |
0x82 | Word | SND_FREQ_2 | Sound channel 2 frequency |
0x84 | Word | SND_FREQ_3 | Sound channel 3 frequency |
0x86 | Word | SND_FREQ_4 | Sound channel 4 frequency |
0x88 | Byte | SND_VOL_1 | Sound channel 1 volume |
0x89 | Byte | SND_VOL_2 | Sound channel 2 volume |
0x8A | Byte | SND_VOL_3 | Sound channel 3 volume |
0x8B | Byte | SND_VOL_4 | Sound channel 4 volume |
0x8C | Byte | SND_SWEEP | Sound channel 3 sweep amount |
0x8D | Byte | SND_SWEEP_TIME | Sound channel 3 sweep step time |
0x8E | Byte | SND_NOISE_CTRL | Sound channel 4 noise control |
0x8F | Byte | SND_WAVERAM | Sound waveform definition area specification |
0x90 | Byte | SND_CH_CTRL | Sound channel control |
0x91 | Byte | SND_OUT_CTRL | Sound output control |
0x92 | Word | SND_RANDOM | Pseudo-random number |
0x94 | Byte | SND_VOL_CH2 | Sound channel 2 voice volume |
0x96 | Word | SND_OUT_R [note] | Right channel sound output |
0x98 | Word | SND_OUT_L [note] | Left channel sound output |
0x9A | Word | SND_OUT_M [note] | Internal speaker sound output |
0xA0 | Byte | SYSTEM_CTRL1 | System control 1 |
0xA2 | Word | TIMER_CTRL | Timer control |
0xA4 | Word | H_BLANK_TIMER | H-Blank timer reload |
0xA6 | Word | V_BLANK_TIMER | V-Blank timer reload |
0xA8 | Word | H_BLANK_COUNTER | H-Blank timer count |
0xAA | Word | V_BLANK_COUNTER | V-Blank timer count |
0xB0 | Byte | INT_VECTOR | Interrupt vector |
0xB1 | Byte | SERIAL_DATA | Send/receive data |
0xB2 | Byte | INT_ENABLE | Interrupt enable |
0xB3 | Byte | SERIAL_STATUS | Serial communication status |
0xB4 | Byte | INT_CAUSE | Interrupt status |
0xB5 | Byte | KEY_SCAN | Key scan |
0xB6 | Byte | INT_CAUSE_CLEAR | Interrupt acknowledge |
0xB7 | Byte | INT_NMI_CTRL | NMI control |
0xBA | Word | IN_SERIAL_DATA | Internal serial ROM data |
0xBC | Word | IN_SERIAL_COM | Internal serial ROM command address |
0xBE | Word | IN_SERIAL_CTRL | Internal serial ROM control |
0xC0 | Byte | LINEAR_ADDR_OFF | Linear address offset |
0xC1 | Byte | RAM_BANK | RAM bank (shadow of lower byte) |
0xC2 | Byte | ROM_BANK_0 | ROM bank #0 (shadow of lower byte) |
0xC3 | Byte | ROM_BANK_1 | ROM bank #1 (shadow of lower byte) |
0xC4 | Word | CART_SERIAL_DATA [2001, note] | Cartridge serial ROM data |
0xC6 | Word | CART_SERIAL_COM [2001, note] | Cartridge serial ROM command address |
0xC8 | Byte | CART_SERIAL_CTRL [2001, note] | Cartridge serial ROM status |
0xCA | Byte | RTC_CTRL [2003] | RTC control |
0xCB | Byte | RTC_DATA [2003] | RTC data |
0xCC | Byte | IO_CTRL [2003] |
I/O port control |
0xCD | Byte | IO_SCAN [2003] |
I/O port scan |
0xCE | Byte | MEMORY_CTRL [2003] |
Memory control |
0xCF | Byte |
LINEAR_ADDR_OFF ′
[2003]
|
(Mirror of linear address offset) |
0xD0 | Byte | RAM_BANK_L [2003] | RAM bank (lower byte) |
0xD1 | Byte | RAM_BANK_H [2003] | RAM bank (upper byte) |
0xD2 | Byte | ROM_BANK_0_L [2003] | ROM bank #0 (lower byte) |
0xD3 | Byte | ROM_BANK_0_H [2003] | ROM bank #0 (upper byte) |
0xD4 | Byte | ROM_BANK_1_L [2003] | ROM bank #1 (lower byte) |
0xD5 | Byte | ROM_BANK_1_H [2003] | ROM bank #1 (upper byte) |
[note] | These ports' official names are not known. |
[color] | These ports are only available in color mode. |
[2001] | These ports are only available on the 2001 mapper. |
[2003] | These ports are only available on the 2003 mapper. |
If a port that is not available on the monochrome model is accessed on a
color model with color mode disabled, no action
will be taken when written and the value 0x90
is always read,
simulating the open bus behavior of the monochrome
model.
The following port address ranges are handled by the following components:
0x00 - 0xB7
| Console SoC |
0xB8 - 0xBF
| Internal EEPROM |
0xC0 - 0xFF
| Cartridge |
In most cases, word-size ports can be used with multiple byte accesses. The exception is the internal EEPROM on the monochrome model. Accessing odd internal EEPROM port addresses as bytes will function as open bus, while even port addresses function normally. On color models, byte accesses on odd port addresses function normally even when color mode is disabled.
The implementation silently converts word accesses in the cartridge range into consecutive pairs of byte accesses, adding one additional CPU cycle in the process.
Although the I/O bus is 8 bits wide, the CPU is capable of specifying 16-bit
port addresses. Accessing port addresses greater than 0xFF
has
the following behaviors:
• | If bit 8 of the port address is set, the access functions as open bus. |
• |
If the lowest 8 bits of the port address are 0x00B8 or
greater, the access functions as open bus.
|
▪ | If the access is not filtered as open bus by one of the above conditions, it functions as a mirror of the lowest 8 bits of the port address. |
Editor's Note: Port addresses not listed above have no known significance. They are assumed to function as open bus.
When a memory or I/O access is attempted on an address that has no corresponding functionality, nothing happens and the default response of the applicable bus takes effect. This occurrence is known as "open bus".
Open bus occurs in the following situations:
• |
The extended WRAM region at memory addresses 0x04000 -
0x0FFFF is accessed by the monochrome model or a color model
with color mode disabled.
|
• | An unmapped I/O port is accessed. |
• | An I/O port introduced in WonderSwan Color is accessed by the monochrome model or a color model with color mode disabled. |
Writing or outputting to open bus has no effect. Reading or inputting from
open bus returns a predetermined value. The open bus value is always
0x90
on the monochrome model, and undefined on color models.
On color models with color mode disabled, memory and I/O addresses that are
available only when color mode is enabled will simulate the open bus behavior
of the monochrome model: they will not respond to writes and they will always
read the value 0x90
.
Editor's Note: Research is needed to determine the exact open bus values for
color models. It is known that they tend to read as 0x00
unless
color mode is disabled and the port address is 0x4000
or
greater, when they tend to return 0x90
instead. There may be
other circumstances that influence the open bus value.
The cartridge inserts into the back of the WonderSwan unit and provides the program and save data for a software title.
The following diagram depicts the pin configuration of the cartridge as seen looking at the face of the cartridge with the label upright:
The pins have the following significance:
1. | Ground | 17. | Data 6 | 33. | Address 16 | ||
2. | Address 15 | 18. | Data 5 | 34. | Data 8 | ||
3. | Address 10 | 19. | Data 4 | 35. | Data 9 | ||
4. | Address 11 | 20. | Data 3 | 36. | Data 10 | ||
5. | Address 9 | 21. | Data 2 | 37. | Data 11 | ||
6. | Address 8 | 22. | Data 1 | 38. | Data 12 | ||
7. | Address 13 | 23. | Data 0 | 39. | Data 13 | ||
8. | Address 14 | 24. | +3V DC | 40. | Reset | ||
9. | Address 12 | 25. | +3V DC | 41. | MBC | ||
10. | Address 7 | 26. | Address 0 | 42. | Memory/IO | ||
11. | Address 6 | 27. | Address 1 | 43. | Read enable | ||
12. | Address 5 | 28. | Address 2 | 44. | Write enable | ||
13. | Address 4 | 29. | Address 3 | 45. | Cartridge select | ||
14. | Data 15 | 30. | Address 19 | 46. | Interrupt request | ||
15. | Data 14 | 31. | Address 18 | 47. | Serial clock | ||
16. | Data 7 | 32. | Address 17 | 48. | Ground |
Pin signals are +3V DC.
The MBC pin is used to authenticate the cartridge's mapper chip on reset using serial communication. The serial clock pin provides a 384 KHz reference signal for this communication as well as communication with an EEPROM if present.
When accessing memory, the Memory/IO pin is +3V and all 20 address pins specify the memory address. When accessing I/O, the Memory/IO pin is 0V, address pins 0 through 7 specify the lower 8 bits of the port address, address pins 8 through 15 are 0V, and address pins 16 through 19 contain a copy of port address bits 4 through 7 respectively.
Reads and writes will only be accepted while both the the cartridge select pin and the corresponding "enable" pin are 0V.
Editor's Note: Research is needed to determine the authentication protocol on pin 41.
The cartridge supports an interrupt that the
program can use to respond to cartridge activity. For information regarding
software setup, see Managing
Interrupts. The cartridge interrupt is called CASETTE
and
has the relative vector index +2.
All WonderSwan cartridges contain a logic circuit that is responsible for selecting banks of cartridge memory to make available to the CPU, and to perform ancillary I/O tasks. These chips are called mappers and two versions were distributed called "2001" and "2003" after their model numbers.
I/O ports with address 0xC0
and greater
are handled by the cartridge mapper. Accessing a port address not supported
by a mapper results in open bus behavior.
The 2001 mapper supports the following I/O ports:
0xC0 | Byte | LINEAR_ADDR_OFF | Linear address offset |
0xC1 | Byte | RAM_BANK | RAM bank |
0xC2 | Byte | ROM_BANK_0 | ROM bank #0 |
0xC3 | Byte | ROM_BANK_1 | ROM bank #1 |
0xC4 | Word | CART_SERIAL_DATA | Cartridge serial ROM data |
0xC6 | Word | CART_SERIAL_COM | Cartridge serial ROM command address |
0xC8 | Byte | CART_SERIAL_CTRL | Cartridge serial ROM status |
The 2003 mapper supports the following I/O ports:
0xC0 | Byte | LINEAR_ADDR_OFF | Linear address offset |
0xC1 | Byte | RAM_BANK | RAM bank (shadow of lower byte) |
0xC2 | Byte | ROM_BANK_0 | ROM bank #0 (shadow of lower byte) |
0xC3 | Byte | ROM_BANK_1 | ROM bank #1 (shadow of lower byte) |
0xCA | Byte | RTC_CTRL | RTC control |
0xCB | Byte | RTC_DATA | RTC data |
0xCC | Byte | IO_CTRL | I/O port control |
0xCD | Byte | IO_SCAN | I/O port scan |
0xCE | Byte | MEMORY_CTRL | Memory control |
0xCF | Byte |
LINEAR_ADDR_OFF ′
|
(Mirror of linear address offset) |
0xD0 | Byte | RAM_BANK_L | RAM bank (lower byte) |
0xD1 | Byte | RAM_BANK_H | RAM bank (upper byte) |
0xD2 | Byte | ROM_BANK_0_L | ROM bank #0 (lower byte) |
0xD3 | Byte | ROM_BANK_0_H | ROM bank #0 (upper byte) |
0xD4 | Byte | ROM_BANK_1_L | ROM bank #1 (lower byte) |
0xD5 | Byte | ROM_BANK_1_H | ROM bank #1 (upper byte) |
At reset, memory addresses FFFF:0000
- FFFF:000F
must contain specific kinds of data. Due to the banking behavior of the
cartridge mapper, these addresses correspond to
the last 16 bytes in cartridge ROM. The significance of
these addresses is described below.
FFFF:0000 - FFFF:0004
|
Entry point |
FFFF:0005 | Maintenance |
FFFF:0006 | Publisher ID |
FFFF:0007 | Color |
FFFF:0008 | Game ID |
FFFF:0009 | Game version |
FFFF:000A | ROM size |
FFFF:000B | Save type |
FFFF:000C - FFFF:000D |
Flags |
FFFF:000E - FFFF:000F |
Checksum |
The entry point is the address of the first instruction executed by the
CPU. The console boot program requires this to be a 32-bit
immediate BR instruction with an
0xEA
opcode or else the system will not boot.
The maintenance byte has the following format:
7 | 6 | 4 | 3 | 0 | |||
Boot |
? | Unknown | |||||
1 | 3 | 4 |
? | The significance of these bits is not known. |
Boot | If set on a color model, the boot program will bypass any custom boot screen in internal EEPROM and supply a default boot screen instead. |
Unknown | If any of these bits is set, the console will not boot. Their purpose is not known. |
BANDAI maintains a list of publisher IDs that is beyond the scope of this document.
The color field may be one of the following values:
0x00 | Software is monochrome |
0x01 | Software supports color |
The game ID is the binary-coded decimal representation of the last two digits of the product's SKU.
The game version byte has the following format:
7 | 6 | 0 | |||||
NP |
Version | ||||||
1 | 7 |
NP | If set, the boot program will not set the internal EEPROM into write-protected mode. |
Version | Software minor version number. |
ROM size indicates read-only memory present in the cartridge. It has the following known values:
0x02 | 4 Mbit | 512 KiB |
0x03 | 8 Mbit | 1 MiB |
0x04 | 16 Mbit | 2 MiB |
0x05 | 24 Mbit | 3 MiB |
0x06 | 32 Mbit | 4 MiB |
0x07 | 48 Mbit | 6 MiB |
0x08 | 64 Mbit | 8 MiB |
0x09 | 128 Mbit | 16 MiB |
Save type indicates persistent memory present in the cartridge. It has the following known values:
0x00 | None | ||
0x01 | SRAM | 64 Kbit | 8 KiB |
0x02 | SRAM | 256 Kbit | 32 KiB |
0x03 | SRAM | 1 Mbit | 128 KiB |
0x04 | SRAM | 2 Mbit | 256 KiB |
0x05 | SRAM | 4 Mbit | 512 KiB |
0x10 | EEPROM | 1 Kbit | 128 B |
0x20 | EEPROM | 16 Kbit | 2 KiB |
0x50 | EEPROM | 8 Kbit | 1 KiB |
The following flags are known:
15 | 9 | 8 | 7 | 3 | 2 | 1 | 0 | ||||||||
? | RTC |
? | Spd |
Bus |
Vert |
||||||||||
7 | 1 | 5 | 1 | 1 | 1 |
? | The significance of these bits is not known. |
RTC | RTC availability: absent if clear, present if set. |
Spd | ROM access speed: 3 cycles if clear, 1 cycle if set. |
Bus | ROM bus size: 16-bit if clear, 8-bit if set. |
Vert | Orientation of boot screen: horizontal if clear, vertical if set. |
The checksum is the cumulative sum of all 8-bit bytes in the ROM‐including the ROM header‐except for the two bytes of the checksum field. This field is not required to be set correctly.
Editor's Note: It is assumed that all bits in the game version byte other than bit 7 belong to the version number, but this has not been verified.
Information about the current hardware is avaiable through the following I/O port:
0xA0 | Byte | SYSTEM_CTRL1 | System control 1 |
7 | 4 | 3 | 2 | 1 | 0 | ||
- | cwait |
cbus |
WSC |
- | |||
4 | 1 | 1 | 1 | 1 |
- | These bits have unknown significance. | |
cwait | R | Cartridge accesses take 3 CPU cycles when clear, or 1 when set. |
cbus | R/W | The cartridge bus is 8-bit when clear, or 16-bit when set. |
WSC | R | Color mode is unavailable when clear, or available when set. |
Inspecting WSC
is the preferred way to detect hardware features.
Editor's Note: The program should not change cbus
. This bit's
writeable status may only be intended for use by the boot ROM.
Editor's Note: Certain bits in this port may be writeable depending on the exact model and color mode configuration, and this may be a side-effect of exposing certain features to the boot ROM. It's apparent that the only intended use of this port by programs is to check for the availability of color mode.
On color models, various features not present in the monochrome model can be activated or deactivated.
Color features are managed through the following port:
0x60 | Byte | SYSTEM_CTRL2 | System control 2 |
7 | 6 | 5 | 4 | 0 | |||
Color |
FourBpp |
Packed |
- | ||||
1 | 1 | 1 | 5 |
- | These bits have unknown significance. | |
Color | R/W | When set, color mode is enabled. |
FourBpp | R/W | When set, 4bpp mode is enabled. |
Packed | R/W | When set, packed mode is enabled. |
This port has no function on the monochrome model, and reading from it on a monochrome model returns undefined data.
If Color
is set and FourBpp
is clear,
characters are treated as 2 bits per pixel.
If Color
and FourBpp
are both set, characters are
treated as 4 bits per pixel. FourBpp
has no effect when
Color
is clear.
If Color
, FourBpp
and Packed
are all
set, characters are treated as 4 bits per pixel packed. Packed
has no effect when either Color
or FourBpp
is
clear.
Setting Color
will enable color mode on color models. The
following system features are available only while Color
is set:
• | Color image features |
• | WRAM expanded to 64 KiB |
• | Internal EEPROM expanded to 2 KiB |
• | DMA features |
• | Hyper Voice |
Some features behave differently depending on whether color mode is enabled or disabled. In all cases, such features will behave the way they do on the monochrome model whenever color mode is disabled. In particular, certain I/O ports have different formats in color mode, and will use the monochrome model's formats whenever color mode is disabled. If color mode is disabled, writes into the expanded WRAM are ignored and reads in expanded WRAM are undefined.
Editor's Note: The WonderWitch API preserves the lowest 5 bits when accessing
SYSTEM_CTRL2
. No significance has been observed in these bits,
so this decision may have been made in the interest of future-proofing it.
When color mode is available according to SYSTEM_CTRL1, an additional I/O port becomes available:
0x62 | Byte | SYSTEM_CTRL3 | System control 3 |
7 | 6 | 1 | 0 | ||||
sc |
- | off |
|||||
1 | 6 | 1 |
- | These bits have unknown significance and are clear when read. | |
sc | R | The system is a SwanCrystal when set, or a WonderSwan Color when clear. |
off | W | When 1 is written to this bit, the system will power off. |
Overview
Specifications
Register Set
Operands
Prefixes
Exceptions
Exceptions and Interrupts
List of Exceptions
Instruction Set
Memory and Register
Arithmetic
Bitwise
CPU Control
Branch
Block
Segment Override
Appendix
Opcode Map
8086 Translation Map
WonderSwan uses an NEC V30 CPU:
Name: | V30MZ |
Address bus: | 20 bits |
Data bus: | 16 bits |
Clock speed: | 3.072 MHz |
Instruction cache: | None |
Instruction set: | CISC |
Manufacturer: | Renesas Electronics Corporation |
Word size: | 16 bits |
Year: | 1998 |
The V Series microprocessors were designed as pin-compatible alternatives to the Intel 8086. The V30MZ in particular is a later model providing limited compatibility with the 8086 and has reduced capabilities when compared to other V Series products, but offers improved power efficiency and execution time.
All registers on the V30MZ are 16-bit. The following registers are present:
AW | General-purpose |
BP | Base pointer |
BW | General-purpose |
CW | General-purpose |
DS0 | Data segment 0 |
DS1 | Data segment 1 |
DW | General-purpose |
IX | Index |
IY | Index |
PC | Program counter |
PS | Program segment |
PSW | Program status word |
SP | Stack pointer |
SS | Stack segment |
AW
, BW
,
CW
, DW
-
General Purpose Registers
Most operations on data, such as arithmetic operations, are performed on these registers. They can also be used as sources and destinations for data transfers.
For 16-bit operations, these registers are used directly as AW
,
BW
, CW
and DW
.
For 8-bit operations, these registers may be used as two 8-bit registers
each. The low-byte registers are used as AL
,
BL
, CL
and
DL
. The high-byte registers are used as
AH
, BH
,
CH
and DH
.
DS0
, DS1
,
PS
, SS
- Segment Registers
Provide the segment portion of a physical address. The value in the segment register is shifted left 4 bits, and the resulting value is added to the 16-bit offset value of another register to compute the final physical address.
Operations that produce physical addresses have a default segment register assigned to them. In most of these cases, the actual segment register used in the physical address calculation can be changed by using a segment override prefix.
The following are the various memory-access scenarios and how they interact with segment registers:
Default | Override | Scenario |
---|---|---|
DS0 | Yes | 16-bit direct memory |
DS0 | Yes |
Memory operand, not BP
base
|
SS | Yes | Memory operand, BP base |
DS0 | Yes | Block instruction, IX value |
DS1 | No | Block instruction, IY value |
DS0 | Yes | CHKIND instruction |
DS0 | Yes | TRANS instruction |
PS | No | Instruction fetch |
SS | No | Stack operation |
SP
- Stack PointerPoints to the most recent data added to the stack.
When constructing a physical address,
SP
provides the offset portion and
SS provides the segment portion.
BP
- Base PointerServes as a data offset for memory operations, and is used as part of the operation of select stack instructions.
IX
, IY
- Index Registers
Used as relative offsets during memory operations: one register is used as the base value for the offset, then an index register is added to that value. For instance, if the offset of a data struct is stored in one register, the individual members of that struct could be accessed using an index register.
PC
- Program Counter
Holds the offset of the instruction about to be executed. PC
is
automatically incremented as instruction bytes are fetched from memory. When
an instruction is fully fetched, PC
will hold the offset of the
first byte of the next instruction.
When constructing a physical address,
PC
provides the offset portion and
PS provides the segment portion.
After PC
reaches 0xFFFF
, it will roll over to
0x0000
without modifying PS
.
PSW
- Program Status Word
Holds status and configuraiton flags. During the operation of instructions,
flags in PSW
are used to control some operations and reflect
information about the results of other operations.
This register has the following format:
15 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ||
1 | 1 | 1 | 1 | V | DIR |
IE |
BRK |
S | Z | 0 | AC |
0 | P | 1 | CY |
4 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
0 | R | These bits have a fixed value and are clear. | |
1 | R | These bits have a fixed value and are set. | |
V | R/W | Overflow | Set when the result of an operation is too large. |
DIR | R/W | Direction | Specifies the direction of a memory or block operation. |
IE | R/W | Interrupt enable | When set, interrupts will be processed. |
BRK | R/W | Break | When set, after each instruction executed, an exception is raised with vector 1. |
S | R/W | Sign | Set when the result of an operation is negative. |
Z | R/W | Zero | Set when the result of an operation is zero. |
AC | R/W | Auxiliary Carry |
Similar to CY , but applies with respect to the lowest 4
bits of the operation.
|
P | R/W | Parity | Set when the number of set bits in the lower 8 bits of an operation is even, or cleared if odd. |
CY | R/W | Carry | Set when an operation produces a carry or borrows. |
During the operation of the branch instructions,
certain flag state combinations are checked in PSW
.
DIR
and CY
can be modified by the
CLR1 and
SET1 instructions.
IE
can be modified by the
DI and
EI instructions.
There is no instruction that can directly modify BRK
. To change
it, the "POP PSW
" instruction must be
used. The exception will be raised after executing the instruction that
follows POP PSW
.
Editor's Note: On other V Series CPUs, bit 15 of PSW
is a flag
called "mode" (MD
), used to control an 8-bit emulation mode.
While set, the CPU would run in native mode, and while clear, it would run in
emulation mode. Emulation mode provides a different set of instructions and
was intended for backwards compatibility with older processors.
CPU instructions are encoded using various different binary formats. Depending on the instruction, data for different kinds of operands may be present, encoded directly into the instruction's machine code.
Operands
Operation Size
Operation Direction
Accumulator
Immediate
Memory
Register
Segment Register
Many instructions can operate as either 8-bit or 16-bit. This affects the width of the registers being accessed as well as how many bytes need to be read from memory for operand values. The data size of an operation is often specified in the first byte of instruction code in one of two ways:
0 | 7 | 1 | 0 | |||||
- | W | |||||||
7 | 1 | |||||||
0 | 7 | 4 | 3 | 2 | 0 | |||
- | W | - | ||||||
4 | 1 | 3 |
- | These bits do not pertain to the operation size. |
W | If present, specifies 8-bit when clear and 16-bit when set. |
When writing instructions, the size of the operation is not explicitly specified: is typically evident from the register name used for a register operand. If a register operand is not present, distinct mnemonics are provided for each operation size.
Some instructions specify multiple operands as well as the direction in which to perform the operation. The direction of such instructions is specified in the first byte of instruction code:
0 | 7 | 2 | 1 | 0 | ||||
- | D | - | ||||||
6 | 1 | 1 |
- | These bits do not pertain to the operation direction. |
D | If present, specifies the operands are in the default order when clear or in reverse order when set. |
The operands of an instruction have a default order. Typically, the left
operand is the operation's destination and the right operand is a source. If
D
is present and set, the operands' order and therefore roles
are reversed, causing what would normally be the destination to act as the
source and vice-versa.
Some instructions implicitly use an "accumulator" register as one of their
operands. If the operation is 8-bit, the register is AL
, and if
the operation is 16-bit, the register is AW
.
When an instruction's operand is stored directly in the machine code, it is called an immediate operand. Normally, the size of an immediate operand matches the size of the operation. Some specific instructions may have a special bit in the first byte of machine code that influences the format of the immediate operand:
0 | 7 | 2 | 1 | 0 | ||||
- | s | - | ||||||
6 | 1 | 1 |
- | These bits do not pertain to the immediate operand. |
s | See below. |
If s
is present and clear, the size of the immediate value is
the same as that of the operation: either 8 bits or 16 bits.
If s
is present and set, the immediate value is always 8 bits.
If the operation is 16-bit, the immediate value is sign-extended to 16 bits.
The data for immediate operands appears as additional instruction bytes. 16-bit immediate values are stored with the low byte first.
If the instruction also contains a memory operand, the bytes of the memory operand appear before the bytes of the immediate operand.
Instructions may specify an operand using fields called Mod
and
Mem
. The operand's value may come from a CPU
register, or may be loaded from memory using
one of a variety of offset expressions. Mod
and
Mem
collectively describe how to access the operand's value.
Instructions with memory operands begin with 2 bytes, the second of which has the following structure:
Notation: aa---mmm
1 | 7 | 6 | 5 | 3 | 2 | 0 | ||
Mod | - | Mem | ||||||
2 | 3 | 3 |
- | These bits do not pertain to the memory operand. |
Mod | Indicates the presence of a displacement offset or CPU register. |
Mem | Specifies the offset expression base or a CPU register's index. |
When Mod
is 3, Mem
specifies the index of the
register containing the operand's value. For more information, see
Register.
When Mod
is not 3, Mem
specifies the base of the
expression to use to calculate a memory offset. The value of the operand is
then read from this offset. The following expression bases are available:
Mem | Expression base |
---|---|
0 | BW + IX |
1 | BW + IY |
2 | BP + IX |
3 | BP + IY |
4 | IX |
5 | IY |
6 | BP [note] |
7 | BW |
[note] |
When Mod is 0 and Mem is 6, the operand's
memory offset is not given by an expression. Instead, the literal 16-bit
offset is present as two additional bytes of program code (low byte
first).
|
The offset portion of the operand's physical
address is calculated by evaluating the expression base and optionally
adding a signed displacement offset to it. The value of Mod
determines how this is done:
Mod | Offset | Note |
---|---|---|
0 | No displacement offset is present. | |
1 | + disp8 | An 8-bit, signed displacement offset is present as one additional byte of instruction code. |
2 | + disp16 | A 16-bit, signed displacement offset is present as two additional bytes of instruction code (low byte first). |
3 |
No value is read from memory. The operand's value comes directly from the
register whose index is specified by
Mem .
|
The default segment register to use when
calculating the physical address depends on whether or not BP
is
present in the offset expression. If BP
is present, the default
segment register is SS
. If BP
is not present, the
defaut segment register is DS0
. The actual segment regsiter used
can be specified with a segment override
prefix.
If the instruction also contains an immediate operand, the bytes of the memory operand appear before the bytes of the immediate operand.
Editor's Note: Research is needed to determine whether offset expressions contain signed components, or if it even matters. It may be the case that the offset portion of the physical address is entirely computed as 16 bits before incorporating the value of the segment register.
Most instructions specify at least one register as a source or destination operand. The register is identified with a 3-bit index, depending on whether the operation is 8-bit or 16-bit:
Index | 8-bit | 16-bit |
---|---|---|
0 | AL | AW |
1 | CL | CW |
2 | DL | DW |
3 | BL | BW |
4 | AH | SP |
5 | CH | BP |
6 | DH | IX |
7 | BH | IY |
If a memory operand has a Mod
field of 3, its Mem
field will be a register index. In this way,
specific instructions can specify two register operands.
Instructions with a register operand usually also have a memory operand, and the register index is encoded into the bits of the second byte not occupied by the memory operand:
Notation: --rrr---
1 | 7 | 6 | 5 | 3 | 2 | 0 | ||
Mod | Reg | Mem | ||||||
2 | 3 | 3 |
Mod | This field pertains to the memory operand. |
Reg | The register's index. |
Mem | This field pertains to the memory operand. |
Specific instructions with register operands may instead specify the register index in the first byte of instruction code:
Notation: -----rrr
0 | 7 | 3 | 2 | 0 | ||||
- | Reg | |||||||
5 | 3 |
- | These bits do not pertain to the register operand. |
Reg | The register's index. |
Some instructions specify a segment register as the source or destination of a data transfer. The segment register is identified with a 2-bit index:
0 | DS1 |
1 | PS |
2 | SS |
3 | DS0 |
In all cases where a segment register operand is encoded into an instruction's bits, the register index occupies the middle two bits of the byte in which it appears:
Notation: ---rr---
7 | 5 | 4 | 3 | 2 | 0 | ||
- | Reg | - | |||||
3 | 2 | 3 |
- | These bits do not pertain to the segment register operand. |
Reg | The segment register's index. |
The POP and PUSH instructions may encode the segment register index into the first byte of instruction code.
The MOV instruction may encode the segment register index into the second byte of instruction code, shared with the bits of a memory operand. In this situation, bit 5 of that byte is not used.
Editor's Note: Research is needed to verify that bit 5 is not used in an
instance of MOV
with a segment register operand.
The behavior of CPU instructions can be modified by prepending prefixes to the instruction. Prefixes are one-byte codes that specify alternative instruction functionality, and appear in the program code immediately prior to the bytes of the prefixed instruction.
There are three general categories of prefixes. All prefixes within each category are mutually exclusive with one another:
• | Segment override |
• | REP (Only applies to block instructions.) |
• | BUSLOCK |
There is no hard limit on how many prefixes may be attached to an instruction. However, since there are three total categories of prefixes, there can be at most three effective prefixes on one instruction. If multiple prefixes from the same category are attached to the same instruction, only the last one (the one immediately preceding the regular instruction data) will take effect.
After fetching a prefix byte and prior to executing the prefixed instruction,
interrupts will not be accepted and
the break flag (BRK
) will not function.
Certain events can cause the CPU to break its current execution, save its status to the stack and begin execution somewhere else according to what happened. The general term for such an occurrence is exception. When the exception is triggered by another hardware component, it is called an interrupt.
On V30MZ, all exceptions are formally referred to as interrupts. Exceptions that result from CPU operations are referred to as software interrupts.
Processing of CPU instructions can raise exceptions on their own, known as software interrupts. This can happen in the following situations:
• | The operation cannot be performed with the given operands. |
• | The BRK or BRKV instruction was executed. |
• |
The BRK flag in PSW
can be used to raise an exception after each instruction executed.
|
Attempting to execute an instruction with an undefined opcode or sub-opcode does not result in an exception. There is no associated operation, so any bytes used to supply their prefixes, opcode, sub-opcode, memory operand or immediate operand are skipped over.
Editor's Note: Research is needed to determine the number of CPU cycles consumed by an illegal opcode.
Hardware components other than the CPU are allowed to request interrupts. This provides a mechanism to synchronize all system operations as well as a way for a hardware component to signal the program when certain conditions are met.
Interrupts can be disabled by clearing the IE
flag in
PSW. The
EI and
DI instructions manipulate this flag
directly, and modifications to PSW
through other instructions
can also be used to configure it.
When an interrupt is requested, it will be processed after the current CPU
instruction finishes and before the next instruction begins. There are
certain situations in which interrupt requests are not processed between
instructions, and in which the break flag (BRK
) will not
function:
• | Immediately following a prefix. |
• | Immediately following a MOV or POP instruction where the destination is a segment register. |
• |
Immediately following an EI,
POP or
RETI instruction that changes
IE from clear to set. The BRK flag still
functions in this case.
|
The HALT instruction will stop all CPU
activity until an interrupt request occurs, at which point it will resume
with exception processing if IE
is set, or the next instruction
if IE
is clear. If no interrupt requests are enabled in any
hardware component, the CPU will be suspended until reset.
When any exception occurs, the program code responsible for handling it is located by reading the address corresponding to its vector. An exception's vector is an unsigned 8-bit index into a global list of handler addresses.
Exception vectors are located in WRAM at the following addresses:
0x00000 - 0x003FF |
Exception vectors |
Up to 256 exception vectors are supported, mostly to be used from software via the BRK instruction.
Each vector is 4 bytes with the following format:
31 | 16 | 15 | 0 | ||||||||||||||||||||||||||||
Segment | Offset | ||||||||||||||||||||||||||||||
16 | 16 |
Segment | The value to load into PS. |
Offset | The value to load into PC. |
When an exception is raised, the following process takes place:
▪ | Push PSW |
▪ | IE = 0 |
▪ | BRK = 0 |
▪ | Push PS |
▪ | Push PC |
Since PC
is incremented for each byte of instruction code
fetched from memory, the value of PC
that gets pushed to the
stack will be the offset of the first byte of the instruction that follows
either the instruction that raised the exception or the instruction that was
executing when the interrupt was requested.
Editor's Note: On V Series CPUs that have an MD
flag in
PSW
, it is set when an exception is raised.
When all of the processing for an exception has completed, the program can return to the main code with the RETI instruction. This instruction performs the following operations:
▪ | Pop PC |
▪ | Pop PS |
▪ | Pop PSW |
If an interrupt is not acknowledged before returning from an instruction, the interrupt request will remain active and the CPU will immediately raise another exception for it.
Editor's Note: Research is needed to determine whether all IRQ lines remain in effect if an interrupt is not acknowledged. The WonderWitch documentation explicitly identifies some interrupts as being edge-driven and others level-driven, but given interrupt requests need to be held during instruction execution, it's not clear exactly how the IRQ state reflects what the hardware is doing.
The following exceptions result from CPU operations (software interrupts) and have fixed vectors:
Vector | Description |
---|---|
0 | CVTBD, DIV or DIVU error |
1 | Single-step via BRK flag |
2 | NMI |
3 | BRK 3 instruction |
4 | BRKV instruction |
5 | CHKIND error |
6 | Unused [note 1] |
7 | Unused [note 2] |
[note 1] | Vector 6 is typically used by other CPUs to handle undefined opcodes. V30MZ silently ignores undefined opcodes and continues execution at the next byte as the start of a new instruction. |
[note 2] |
Vector 7 is reserved for errors that occur during execution of an
instruction called POLL , which places the CPU in a wait
state until woken by a coprocessor. V30MZ has no coprocessor and treats
the POLL opcode as undefined.
|
Any exception raised by the CPU in the list above will be processed before any interrupt requests in the list below.
The following exceptions are interrupts raised by components other than the
CPU. Their vectors are not fixed: their number is added to the base vector
specified by INT_BASE
(see below):
Vector | Name | Type | Description |
---|---|---|---|
+0 | SENDREADY | Level | [note] |
+1 | KEY | Edge | A button was pressed. |
+2 | CASETTE | Level | Requested by cartridge, usually for RTC alarm. |
+3 | RECEIVEREADY | Level | [note] |
+4 | DISPLINE | Edge | A specific row of pixels is being displayed. |
+5 | VBLANK_COUNTUP | Edge | A configurable number of images have been dispalyed. |
+6 | VBLANK | Edge | The image has finished being displayed. |
+7 | HBLANK_COUNTUP | Edge | A configurable number of rows of pixels have been displayed. |
[note] Editor's Note: These interrupts need research.
A "level" interrupt will constantly issue its request until acknowledged. Returning from the handler routine without acknowledging the request will immediately cause the handler to run again.
An "edge" interrupt will only issue its request once as a pulse. Returning from the handler routine without acknolweding the request will not cause the handler to run again, but no further interrupts with the same vector can be requested until the previous one is acknowledged.
In the event two or more interrupts are requested simultaneously, the one with the greatest vector will be processed first.
Hardware interrupts cause pending HALT
instructions to complete, even if interrupts are otherwise masked by the
IE
flag in PSW.
Editor's Note: Research is needed to verify the mechanics of "level" and "edge".
Hardware interrupts do not have fixed vectors. Instead, their effective vector is calculated by taking a global base vector and adding to it the interrupt's vector number as shown in the list above.
The base interrupt vector is configured through the following I/O port:
This port is ostensibly an unsigned 8-bit value directly representing the hardware interrupt base vector number. However, the lowest 3 bits are ignored (limiting the base vector to multiples of 8) and are undefined when read.
Interrupt requests are managed through the following I/O ports, all of which have the same format:
0xB2 | Byte | INT_ENABLE | Interrupt enable |
0xB4 | Byte | INT_CAUSE | Interrupt status |
0xB6 | Byte | INT_CAUSE_CLEAR | Interrupt acknowledge |
Each bit in these ports corresponds to one of the hardware interrupts, with the position of each bit matching the interrupt's relative vector index.
The bits in INT_ENABLE
specify which hardware interrupt
situations are permitted. INT_ENABLE
can be both read and
written.
When an interrupt situation occurs while the corresponding bit is set in
INT_ENABLE
, the corresponding bit in INT_CAUSE
becomes set. While INT_CAUSE
is non-zero, a CPU interrupt will
be requested (the processing of which can be masked by the IE
flag in PSW). Clearing bits in
INT_ENABLE
has no effect on INT_CAUSE
.
INT_CAUSE
is read-only and writes have no effect.
When a 1 is written to a bit in INT_CAUSE_CLEAR
, the
corresponding interrupt is acknowledged and the corresponding bit in
INT_CAUSE
is cleared, causing any active request for that
interrupt to be canceled. When a 0 is written to a bit in
INT_CAUSE_CLEAR
, no action is taken for that interrupt.
INT_CAUSE_CLEAR
is write-only and its contents are undefined
when read.
The non-maskable interrupt (NMI) is a hardware interrupt that cannot be
ignored by the CPU: it will invoke its handler routine regardless of the
state of the IE
flag in PSW,
even if another interrupt is already being handled. The NMI is automatically
acknowledged as soon as it is triggered, before its handler routine is
invoked.
The NMI is configured through the following I/O port:
0xB7 | INT_NMI_CTRL | NMI control |
7 | 5 | 4 | 3 | 0 | |||
- | BAT |
- | |||||
3 | 1 | 4 |
- | R | These bits have no significance and are clear when read. |
BAT | R/W | When set, enable NMI to detect low battery. |
When the system battery gets low on voltage, a dedicated LCD segment
activates. If BAT
is set when this occurs, an NMI will be
triggered. If BAT
becomes set while the battery voltage is
already low, an NMI will be triggered immediately. While the battery voltage
is low, BAT
must be cleared then set again in order to trigger
another NMI.
NEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
CVTBW | CBW | - | - | - | - | - | - | Convert Byte to Word |
AH = 0x00 if AL ≥ 0,
0xFF if AL < 0
|
CVTWL | CWD | - | - | - | - | - | - | Convert Word to Long |
DW = 0x0000 if AW ≥ 0,
0xFFFF if AW < 0
|
IN | IN | - | - | - | - | - | - | Input | acc = (I/O) [src] |
LDEA | LEA | - | - | - | - | - | - | Load Effective Address | dest = offset of src |
MOV |
MOV , LAHF , LDS ,
LES , SAHF
|
- | - | - | - | - | - | Move | dest = src |
OUT | OUT | - | - | - | - | - | - | Output | (I/O) [acc] = src |
POP |
POP , POPA , POPF
|
* | * | * | * | * | * | Pop | Remove from stack |
PUSH |
PUSH , PUSHA PUSHF
|
- | - | - | - | - | - | Push | Add to stack |
SALC | SALC | - | - | - | - | - | - | Set AL on Carry |
AL = 0x00 if CY = 0,
0xFF if CY = 1
|
TRANS | XLAT | - | - | - | - | - | - | Translate | AL = [BW + AL ] |
XCH | XCHG | - | - | - | - | - | - | Exchange | (temp) = dest, dest = src, src = (temp) |
CVTBW
- Convert Byte to WordNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
CVTBW | CBW | - | - | - | - | - | - | Convert Byte to Word |
AH = 0x00 if AL ≥ 0,
0xFF if AL < 0
|
Sign-extends AL
into AW
. If the highest bit of
AL
is clear, stores 0x00
into AH
.
Otherwise, stores 0xFF
into AH
.
Code | Cycles | Operands |
---|---|---|
10011000 | 1 | None |
CVTWL
- Convert Word to LongNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
CVTWL | CWD | - | - | - | - | - | - | Convert Word to Long |
DW = 0x0000 if AW ≥ 0,
0xFFFF if AW < 0
|
Sign-extends AW
into DW
,AW
. If the
highest bit of AW
is clear, stores 0x0000
into
DW
. Otherwise, stores 0xFFFF
into DW
.
Code | Cycles | Operands |
---|---|---|
10011001 | 1 | None |
IN
- InputNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
IN | IN | - | - | - | - | - | - | Input | acc = (I/O) [src] |
Inputs the value from the I/O port pointed to by src and stores it
into AL
. If 16-bit, inputs the value from the I/O port pointed
to by src + 1 and stores it into AH
.
Code | Cycles | Operands |
---|---|---|
1110010W | 6 | Accumulator, Immediate |
1110110W | 6 |
Accumulator,
DW
|
The Accumulator/Immediate variant of this instruction provides the lower 8 bits of an I/O port as one additional byte of program code. The upper 8 bits of the port are zero.
LDEA
- Load Effective AddressNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
LDEA | LEA | - | - | - | - | - | - | Load Effective Address | dest = offset of src |
Calculates the offset of a memory operand and stores the result into a 16-bit register.
Code | Cycles | Operands |
---|---|---|
10001101 aarrrmmm | 1 | Register, Memory |
If the memory operand specifies a register, the value in that register is stored to the destination as though the instruction were MOV.
If the memory operand specifies an offset, the value at that offset is not read from memory. Instead, the offset itself is stored to the destination.
MOV
- MoveNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
MOV |
MOV , LAHF , LDS ,
LES , SAHF
|
- | - | - | - | - | - | Move | dest = src |
Takes the value from src and stores it into dest.
Code | Cycles | Operands |
---|---|---|
100010DW aarrrmmm | 1 | Register, Memory |
100011D0 aa-rrmmm | 1-3 | Memory, Segment Register [note 1] |
10011110 | 4 | PSW , AH [note 2] |
10011111 | 2 | AH , PSW [note 3] |
101000DW | 1 | Accumulator, Direct Memory |
1011Wrrr | 1 | Register, Immediate |
11000100 aarrrmmm | 6 |
DS1 ,
Register,
Memory [note 4]
|
11000101 aarrrmmm | 6 |
DS0 ,
Register,
Memory [note 5]
|
1100011W aa---mmm | 1 | Memory, Immediate |
[note 1] |
If PS is specified as the destination of the Memory/Segment
Register variant of this instruction, the operation will not be
performed.
|
[note 2] |
The Intel notation for the PSW , AH variant of
this instruction has the mnemonic SAHF and has zero
operands.
|
[note 3] |
The Intel notation for the AH , PSW variant of
this instruction has the mnemonic LAHF and has zero
operands.
|
[note 4] |
The Intel notation for the DS1 , … variant of this
instruction has the mnemonic LES and does not include the
segment register operand.
|
[note 5] |
The Intel notation for the DS0 , … variant of this
instruction has the mnemonic LDS and does not include the
segment register operand.
|
After executing the Memory/Segment Register variant of this instruction and
prior to executing the following instruction,
interrupts will not be accepted and
the break flag (BRK
) will not function.
When transferring between AH
and
PSW, only the lower 8 bits of
PSW
are relevant.
The Accumulator/Direct Memory variant of this instruction provides a 16-bit memory offset as two additional bytes of program code (low byte first). The memory at this offset is accessed by the operation.
The three-operand variants of this instruction load 32 bits from the memory pointed to by the memory operand. The lower 16 bits (low byte first) are stored into the 16-bit register operand and the upper 16 bits (low byte first) are stored into the segment register operand.
If a three-operand variant of this instruction specifies a register for the memory operand, the offset accessed in memory will be undefined.
The number of cycles taken by the Memory/Segment Register variant of this instruction depends on the memory operand:
1 | The memory operand is the destination and a register. |
2 | The memory operand is the source and a register. |
3 | The memory operand is an offset. |
OUT
- OutputNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
OUT | OUT | - | - | - | - | - | - | Output | (I/O) [dest] = acc |
Outputs the value of AL
to the I/O port pointed to by
dest. If 16-bit, outputs the value of AH
to the I/O port
pointed to by dest + 1.
Code | Cycles | Operands |
---|---|---|
1110011W | 6 | Immediate, Accumulator |
1110111W | 6 |
DW ,
Accumulator
|
The Immediate/Accumulator variant of this instruction provides the lower 8 bits of an I/O port as one additional byte of program code. The upper 8 bits of the port are zero.
POP
- PopNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
POP |
POP , POPA , POPF
|
* | * | * | * | * | * | Pop | Remove from stack |
Retrieves a 16-bit value from the stack and stores it in the operand. During
a pop operation, the value is loaded from the memory pointed to by
SS
:SP
(low byte first), then SP
is
incremented by 2.
Code | Cycles | Operands |
---|---|---|
000rr111 | 3 | Segment Register [note 1] |
01011rrr | 1 | Register |
01100001 | 8 | R [note 2] |
10001111 aa---mmm | 1-3 | Memory |
10011101 | 3 | PSW [note 3] |
[note 1] |
The instruction code 00001111 does not correspond to
"POP PS ". It is an undefined opcode.
|
[note 2] |
The Intel notation for the R variant of this instruction has
the mnemonic POPA and has zero operands.
|
[note 3] |
The Intel notation for the PSW variant of this instruction
has the mnemonic POPF and has zero operands.
|
After executing the Segment Register variant of this instruction and prior to
executing the following instruction,
interrupts will not be accepted and
the break flag (BRK
) will not function.
The Register and Memory variants of this instruction are 16-bit operations.
The R
variant of this instruction performs the following
algorithm:
▪ | Pop IY |
▪ | Pop IX |
▪ | Pop BP |
▪ | SP = SP + 2 |
▪ | Pop BW |
▪ | Pop DW |
▪ | Pop CW |
▪ | Pop AW |
Status flags in PSW will only be modified
when PSW
is the operand. If the PSW
variant of this
instruction causes the interrupt enable flag (IE
) to transition
from clear to set, then prior to executing the following instruction,
interrupts will not be accepted, but the break flag (BRK
) will
continue to function.
The number of cycles taken by the Memory variant of this instruction depends on the operand:
1 | The operand is a register. |
3 | The operand is an offset. |
Editor's Note: The instruction set documentation indicates anomalous behavior
when using PUSH SP
followed by POP SP
. This needs
to be investigated.
PUSH
- PushNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
PUSH |
PUSH , PUSHA PUSHF
|
- | - | - | - | - | - | Push | Add to stack |
Stores a 16-bit value on the stack. During a push operation, SP
is decremented by 2, then the value is stored into memory at the offset
pointed to by SP
(low byte first).
Code | Cycles | Operands |
---|---|---|
000rr110 | 2 | Segment Register |
01010rrr | 1 | Register |
01100000 | 9 | R [note 1] |
011010s0 | 1 | Immediate |
10011100 | 2 | PSW [note 2] |
1111111- aa110mmm | 1-2 | Memory |
[note 1] |
The Intel notation for the R variant of this instruction has
the mnemonic PUSHA and has zero operands.
|
[note 2] |
The Intel notation for the PSW variant of this instruction
has the mnemonic PUSHF and has zero operands.
|
All push operations are 16-bit. This affects which data is accessed by the Register and Memory variants of this instruction, and the size of the immediate operand.
The R
variant of this instruction performs the following
algorithm:
▪ | (temp) = SP |
▪ | Push AW |
▪ | Push CW |
▪ | Push DW |
▪ | Push BW |
▪ | Push (temp) |
▪ | Push BP |
▪ | Push IX |
▪ | Push IY |
The Memory variant of this instruction is a 16-bit operation.
The number of cycles taken by the Memory variant of this instruction depends on the operand:
1 | The operand is a register. |
2 | The operand is an offset. |
SALC
- Set AL
on CarryNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
SALC | SALC | - | - | - | - | - | - | Set AL on Carry |
AL = 0x00 if CY = 0,
0xFF if CY = 1
|
Sets AL
according to the status of CY
. If
CY
is clear, stores 0x00
into AL
.
Otherwise, stores 0xFF
into AL
.
Code | Cycles | Operands |
---|---|---|
11010110 | 8 | None |
Editor's Note: This instruction is historically undocumented, even by Intel.
It was first documented in the instruction set for the Pentium Pro (P6/i686)
in 1995, but has been confirmed to be present in all of Intel's x86 CPUs all
the way back to the 8086. Its purpose is to assist compilers by succinctly
transferring boolean results into AL
(for use as function return
values) without affecting any of the status flags, and it is provided by
V30MZ for compatibility reasons.
TRANS
- TranslateNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
TRANS | XLAT | - | - | - | - | - | - | Translate | AL = [BW + AL ] |
Calculates a memory offset as the unsigned sum of BW
and
AL
, and loads the byte at that offset into AL
.
Code | Cycles | Operands |
---|---|---|
11010111 | 5 | [BW] |
This instruction's operands are implicit and may be written in other ways:
• | The operand may be omitted. |
• |
The instruction may be written as "TRANSB " with zero
operands.
|
The default segment register for this
instruction is DS0
. The segment register to use can be selected
with a segment override prefix.
XCH
- ExchangeNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
XCH | XCHG | - | - | - | - | - | - | Exchange | (temp) = dest, dest = src, src = (temp) |
Exchanges the values stored in the operands.
Code | Cycles | Operands |
---|---|---|
1000011W aarrrmmm | 3-5 | Register, Memory |
10010rrr | 3 | Accumulator, Register |
The Accumulator/Register variant of this instruction is a 16-bit operation.
This instruction may be written with its operands reversed, as the operation will be unchanged.
When the Accumulator/Register variant of this instruction is used to exchange
AW
with itself, it is regarded as its own instruction:
Code | Mnemonic | Name | Cycles | Operands |
---|---|---|---|---|
10010000 | NOP | No Operation | 3 | None |
The number of cycles taken by the Register/Memory variant of this instruction depends on the memory operand:
3 | The memory operand is a register. |
5 | The memory operand is an offset. |
NEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
ADD | ADD | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | Add | dest = dest + src |
ADDC | ADC | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | Add with Carry | dest = dest + src + CY |
ADJ4A | DAA | ✓ | ✓ | ? | ✓ | ✓ | ✓ | Adjust Nibble Add | See instruction for details. |
ADJ4S | DAS | ✓ | ✓ | ? | ✓ | ✓ | ✓ | Adjust Nibble Subtract | See instruction for details. |
ADJBA | AAA | ★ | ★ | ★ | ✓ | ★ | ✓ | Adjust Byte Add | See instruction for details. |
ADJBS | AAS | ★ | ★ | ★ | ✓ | ★ | ✓ | Adjust Byte Subtract | See instruction for details. |
CMP | CMP | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | Compare | (discard) = dest - src |
CVTBD | AAM | ✓ | ✓ | ? | ? | ✓ | ? | Convert Binary to Decimal |
AH = AL / src,
AL = AL MOD src
|
CVTDB | AAD | ✓ | ✓ | ★ | ★ | ✓ | ★ | Convert Decimal to Binary |
AL = AH * src + AL ,
AH = 0
|
DEC | DEC | ✓ | ✓ | ✓ | - | ✓ | ✓ | Decrement | dest = dest - 1 |
DIV | IDIV | ? | ? | ? | ? | ? | ? | Divide Signed | See instruction for details. |
DIVU | DIV | ? | ? | ? | ? | ? | ? | Divide Unsigned | See instruction for details. |
FPO1 | ESC | - | - | - | - | - | - | Floating Point Operation 1 | No operation. |
INC | INC | ✓ | ✓ | ✓ | - | ✓ | ✓ | Increment | dest = dest + 1 |
MUL | IMUL | ★ | ★ | ✓ | ✓ | ★ | ★ | Multiply Signed | See instruction for details. |
MULU | MUL | ★ | ★ | ✓ | ✓ | ★ | ★ | Multiply Unsigned | See instruction for details. |
NEG | NEG | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | Negate | dest = 0 - dest |
SUB | SUB | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | Subtract | dest = dest - src |
SUBC | SBB | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | Subtract with Carry | dest = dest - src - CY |
ADD
- AddNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
ADD | ADD | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | Add | dest = dest + src |
Adds the two operands. The result is stored in the left operand.
Code | Cycles | Operands |
---|---|---|
000000DW aarrrmmm | 1-3 | Memory, Register |
0000010W | 1 | Accumulator, Immediate |
100000sW aa000mmm | 1-3 | Memory, Immediate |
The zero flag (Z
) is set when the result of the addition is
zero, or is cleared otherwise.
The sign flag (S
) is set when the highest bit of the result is
set, or is cleared otherwise.
The overflow flag (V
) is set when the operands have the same
sign and the result has the opposite sign, or is cleared otherwise.
The carry flag (CY
) is set when the unsigned sum exceeds
0xFF
for byte or 0xFFFF
for word, or is cleared
otherwise.
The parity flag (P
) is set when the number of set bits in the
lower 8 bits of the result is even, or is cleared otherwise.
The auxiliary carry flag (AC
) is set when the unsigned sum of
the lowest 4 bits of the operands exceeds 0xF
, or is cleared
otherwise.
The number of cycles taken by the Memory/Register variant of this instruction depends on the operands:
1 | Both operands are registers. |
2 | The source operand is an offset. |
3 | The destination operand is an offset. |
The number of cycles taken by the Memory/Immediate variant of this instruction depends on the operands:
1 | The destination operand is a register. |
3 | The destination operand is an offset. |
ADDC
- Add with CarryNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
ADDC | ADC | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | Add with Carry | dest = dest + src + CY |
Adds the two operands, plus 1 more if the carry flag (CY
) was
set. The result is stored in the left operand.
Code | Cycles | Operands |
---|---|---|
000100DW aarrrmmm | 1-3 | Memory, Register |
0001010W | 1 | Accumulator, Immediate |
100000sW aa010mmm | 1-3 | Memory, Immediate |
The zero flag (Z
) is set when the result of the addition is
zero, or is cleared otherwise.
The sign flag (S
) is set when the highest bit of the result is
set, or is cleared otherwise.
The overflow flag (V
) is set when the operands have the same
sign and the result has the opposite sign, or is cleared otherwise.
The carry flag (CY
) is set when the unsigned sum exceeds
0xFF
for byte or 0xFFFF
for word, or is cleared
otherwise.
The parity flag (P
) is set when the number of set bits in the
lower 8 bits of the result is even, or is cleared otherwise.
The auxiliary carry flag (AC
) is set when the unsigned sum of
the lowest 4 bits of the operands exceeds 0xF
, or is cleared
otherwise.
The number of cycles taken by the Memory/Register variant of this instruction depends on the operands:
1 | Both operands are registers. |
2 | The source operand is an offset. |
3 | The destination operand is an offset. |
The number of cycles taken by the Memory/Immediate variant of this instruction depends on the operands:
1 | The destination operand is a register. |
3 | The destination operand is an offset. |
ADJ4A
- Adjust Nibble AddNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
ADJ4A | DAA | ✓ | ✓ | ? | ✓ | ✓ | ✓ | Adjust Nibble Add | See below. |
When ADD or
ADDC is used on two-digit binary-coded
decimal numbers, ADJ4A
can be used to adjust the result in
the AL
register in order to produce the correct two-digit
binary-coded decimal result.
Code | Cycles | Operands |
---|---|---|
00100111 | 10 | None |
The adjustment performs the following algorithm:
♦ |
If (AL AND 0x0F ) > 0x09 ,
or AC = 1
|
||||
♦ |
If AL > 0x9F ,
or CY = 1
|
If the operands of the original addition were not two-digit binary-coded decimal, the result of the adjustment will be nonsense.
The zero flag (Z
) is set when the result of the adjustment is
zero, or is cleared otherwise.
The sign flag (S
) is set when the highest bit of the adjustment
is set, or is cleared otherwise.
The overflow flag (V
) has an unspecified state after this
instruction completes.
The carry (CY
) and auxiliary carry (AC
) flags are
updated according to the above algorithm.
The parity flag (P
) is set when the number of set bits in the
result is even, or is cleared otherwise.
ADJ4S
- Adjust Nibble SubtractNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
ADJ4S | DAS | ✓ | ✓ | ? | ✓ | ✓ | ✓ | Adjust Nibble Subtract | See below. |
When SUB or
SUBC is used on two-digit binary-coded
decimal numbers, ADJ4S
can be used to adjust the result in
the AL
register in order to produce the correct two-digit
binary-coded decimal result.
Code | Cycles | Operands |
---|---|---|
00101111 | 10 | None |
The adjustment performs the following algorithm:
♦ |
If (AL AND 0x0F ) > 0x09 ,
or AC = 1
|
||||
♦ |
If AL > 0x9F ,
or CY = 1
|
If the operands of the original subtraction were not two-digit binary-coded decimal, the result of the adjustment will be nonsense.
The zero flag (Z
) is set when the result of the adjustment is
zero, or is cleared otherwise.
The sign flag (S
) is set when the highest bit of the adjustment
is set, or is cleared otherwise.
The overflow flag (V
) has an unspecified state after this
instruction completes.
The carry (CY
) and auxiliary carry (AC
) flags are
updated according to the above algorithm.
The parity flag (P
) is set when the number of set bits in the
result is even, or is cleared otherwise.
ADJBA
- Adjust Byte AddNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
ADJBA | AAA | ★ | ★ | ★ | ✓ | ★ | ✓ | Adjust Byte Add | See below. |
When ADD or
ADDC is used on one-digit
binary-coded
decimal numbers, ADJBA
can be used to adjust the values in
the AL
and AH
registers in order to produce the
correct two-digit binary-coded decimal result.
Code | Cycles | Operands |
---|---|---|
00110111 | 9 | None |
The adjustment performs the following algorithm:
♦ |
If (AL AND 0x0F ) > 0x09 ,
or AC = 1
|
||||||||||||
◊ |
Otherwise
|
If the operands of the original addition were not one-digit binary-coded decimal, the result of the adjustment will be nonsense.
The zero (Z
), sign (S
), carry (CY
) and
auxiliary carry (AC
) flags are updated according to the
above algorithm.
The overflow (V
) flag is always cleared.
The parity (P
) flag is always set.
★ In the V Series specification, the zero (Z
), sign
(S
), overflow (V
) and parity (P
) flags
have unspecified states after this instruction completes.
ADJBS
- Adjust Byte SubtractNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
ADJBS | AAS | ★ | ★ | ★ | ✓ | ★ | ✓ | Adjust Byte Subtract | See below. |
When SUB or
SUBC is used on one-digit binary-coded
decimal numbers, ADJBS
can be used to adjust the result in
the AL
and AH
registers in order to produce the
correct two-digit binary-coded decimal output.
Code | Cycles | Operands |
---|---|---|
00111111 | 9 | None |
The adjustment performs the following algorithm:
♦ |
If (AL AND 0x0F ) > 0x09 ,
or AC = 1
|
||||||||||||
◊ |
Otherwise
|
If the operands of the original subtraction were not 4-bit binary-coded decimal, the result of the adjustment will be nonsense.
The zero (Z
), sign (S
), carry (CY
) and
auxiliary carry (AC
) flags are updated according to the
above algorithm.
The overflow (V
) flag is always cleared.
The parity (P
) flag is always set.
★ In the V Series specification, the zero (Z
), sign
(S
), overflow (V
) and parity (P
) flags
have unspecified states after this instruction completes.
CMP
- CompareNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
CMP | CMP | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | Compare | (discard) = dest - src |
Subtracts the operands, updating the status flags in the process, and discards the result.
Code | Cycles | Operands |
---|---|---|
001110DW aarrrmmm | 1-2 | Memory, Register |
0011110W | 1 | Accumulator, Immediate |
100000sW aa111mmm | 1-2 | Memory, Immediate |
The zero flag (Z
) is set when the result of the subtraction is
zero, or is cleared otherwise.
The sign flag (S
) is set when the highest bit of the result is
set, or is cleared otherwise.
The overflow flag (V
) is set when the operands have opposite
signs and the left operand and result have opposite signs, or is cleared
otherwise.
The carry flag (CY
) is set when the unsigned difference passes
zero, or is cleared otherwise.
The parity flag (P
) is set when the number of set bits in the
lower 8 bits of the result is even, or is cleared otherwise.
The auxiliary carry flag (AC
) is set when the unsigned
difference of the lowest 4 bits of the operands passes zero, or is cleared
otherwise.
The number of cycles taken by the Memory/Register variant of this instruction depends on the operands:
1 | Both operands are registers. |
2 | One of the operands is an offset. |
The number of cycles taken by the Memory/Immediate variant of this instruction depends on the operands:
1 | The destination operand is a register. |
2 | The destination operand is an offset. |
CVTBD
- Convert Binary to DecimalNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
CVTBD | AAM | ✓ | ✓ | ? | ? | ✓ | ? | Convert Binary to Decimal |
AH = AL / src, AL =
AL MOD src
|
An 8-bit, unsigned division is performed as AL
/ src, the
quotient is stored into AH
, and the remainder is stored into
AL
.
Code | Cycles | Operands |
---|---|---|
11010100 | 17 | Immediate |
If the divisor is zero, an exception
is raised with vector 0. The value of AW
is undefined in this
situation.
The zero flag (Z
) is set when the resulting value of
AL
is zero, or is cleared otherwise.
The sign flag (S
) is set when the highest bit of the resulting
value of AL
is set, or is cleared otherwise.
The parity flag (P
) is set when the number of set bits in the
resulting value of AL
is even, or is cleared otherwise.
The overflow (V
), carry (CY
) and auxiliary carry
(AC
) flags have unspecified states after this instruction
completes.
Editor's Note: The intended use of this instruction is to use an operand of
10
to adjust the result of two multiplied binary-coded
decimal values after using
MULU.
Editor's Note: Formally, the V Series specification does not include an
operand for this instruction, but provides a second byte 0x0A
as
a sort of 16-bit opcode. The V30MZ treats this byte as an operand in
accordance with the 8086 family specification.
CVTDB
- Convert Decimal to BinaryNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
CVTDB | AAD | ✓ | ✓ | ★ | ★ | ✓ | ★ | Convert Decimal to Binary |
AL = AH * src + AL ,
AH = 0
|
An 8-bit, unsigned multiplication is performed as AH
*
src, the value in AL
is added, the lower 8 bits of the
result are stored into AL
, and zero is stored into
AH
.
Code | Cycles | Operands |
---|---|---|
11010101 00001010 | 6 | Immediate |
V30MZ processes this instruction by performing
MULU followed by
ADD. All flags—including overflow
(V
), carry (CY
) and auxiliary carry
(AC
)—are updated according to the usual operations of
ADD
.
★ In the V Series specification, the overflow (V
), carry
(CY
) and auxiliary carry (AC
) flags have
unspecified states after this instruction completes.
Editor's Note: The intended use of this instruction is to use an operand of
10
to prepare a binary-coded
decimal value to be subsequently divided using
DIVU, such that it will produce the
correct binary-coded decimal result.
Editor's Note: Formally, the V Series specification does not include an
operand for this instruction, but provides a second byte 0x0A
as
a sort of 16-bit opcode. The V30MZ treats this byte as an operand in
accordance with the 8086 family specification.
DEC
- DecrementNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
DEC | DEC | ✓ | ✓ | ✓ | - | ✓ | ✓ | Decrement | dest = dest - 1 |
Subtracts 1 from the operand and stores the result back into the operand.
Code | Cycles | Operands |
---|---|---|
01001rrr | 1 | Register |
1111111W aa001mmm | 1-3 | Memory |
The Register variant of this instruction is a 16-bit operation.
The zero flag (Z
) is set when the result of the subtraction is
zero, or is cleared otherwise.
The sign flag (S
) is set when the highest bit of the result is
set, or is cleared otherwise.
The overflow flag (V
) is set when the original value was -128
for byte or -32,768 for word, or is cleared otherwise.
The parity flag (P
) is set when the number of set bits in the
lower 8 bits of the result is even, or is cleared otherwise.
The auxiliary carry flag (AC
) is set if the lowest 4 bits of
the original value were all clear, or is cleared otherwise.
The number of cycles taken by the Memory variant of this instruction depends on the operand:
1 | The operand is a register. |
3 | The operand is an offset. |
DIV
- Divide SignedNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
DIV | IDIV | ? | ? | ? | ? | ? | ? | Divide Signed | See below. |
As an 8-bit operation, a signed division is performed as AW
/
mem, the remainder is stored into AH
and the quotient is
stored into AL
.
As a 16-bit operation, a 32-bit value is produced with DW
as the
upper bits and AW
as the lower bits, a signed division is
performed as this value / mem, the remainder is stored into
DW
and the quotient is stored into AW
.
The quotient is truncated to an integer (towards zero), and the remainder has the same sign as the dividend.
Code | Cycles | Operands |
---|---|---|
1111011W aa111mmm | 17-25 | Memory |
If the divisor is zero or the magnitude of the quotient (after truncation)
exceeds ±0x7F
for 8-bit or ±0x7FFF
for 16-bit, an exception is raised
with vector 0. The values of AW
and DW
(if 16-bit)
are undefined in this situation.
The zero (Z
), sign (S
), overflow, (V
),
carry (CY
), parity (P
) and auxiliary carry
(AC
) flags have unspecified states after this instruction
completes.
The number of cycles taken by this instruction depends on the operation size and operand:
17 | 8-bit | Register |
18 | 8-bit | Offset |
24 | 16-bit | Register |
25 | 16-bit | Offset |
Editor's Note: Most x86 CPUs after the Intel 8089 include the maximum negative value (-128 and -32,768) in the range of valid quotients. The V Series specification matches the range defined in the original 8086 family specification, which excludes the maximum negative value.
Editor's Note: Although the values in DW
(if 16-bit) and
AW
are formally undefined in the event of an exception, hardware
testing suggests that these registers are simply not modified.
DIVU
- Divide UnsignedNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
DIVU | DIV | ? | ? | ? | ? | ? | ? | Divide Unsigned | See below. |
As an 8-bit operation, an unsigned division is performed as AW
/
mem, the remainder is stored into AH
and the quotient is
stored into AL
.
As a 16-bit operation, a 32-bit value is produced with DW
as the
upper bits and AW
as the lower bits, an unsigned division is
performed as this value / mem, the remainder is stored into
DW
and the quotient is stored into AW
.
The quotient is truncated to an integer (towards zero).
Code | Cycles | Operands |
---|---|---|
1111011W aa110mmm | 15-24 | Memory |
If the divisor is zero or the quotient (after truncation) exceeds
0xFF
for 8-bit or 0xFFFF
for 16-bit, an
exception is raised with vector 0.
The values of AW
and DW
(if 16-bit) are undefined
in this situation.
The zero (Z
), sign (S
), overflow, (V
),
carry (CY
), parity (P
) and auxiliary carry
(AC
) flags have unspecified states after this instruction
completes.
The number of cycles taken by this instruction depends on the operation size and operand:
Cycles | Size | Operand |
---|---|---|
15 | 8-bit | Register |
16 | 8-bit | Offset |
23 | 16-bit | Register |
24 | 16-bit | Offset |
Editor's Note: Although the values in DW
(if 16-bit) and
AW
are formally undefined in the event of an exception, hardware
testing suggests that these registers are simply not modified.
FPO1
- Floating Point Operation 1NEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
FPO1 | ESC | - | - | - | - | - | - | Floating Point Operation 1 | No operation. |
Performs no operation.
Code | Cycles | Format |
---|---|---|
11011--- aa---mmm | 1 | Memory |
Although this instruction performs no operation, additional bytes of instruction code may still be present depending on the memory operand. If the memory operand specifies an offset, no memory is actually accessed.
Editor's Note: This instruction was carried over from the base V Series instruction set. Its original function was to control a floating-point coprocessor, but the coprocessor feature is not supported on V30MZ.
INC
- IncrementNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
INC | INC | ✓ | ✓ | ✓ | - | ✓ | ✓ | Increment | dest = dest + 1 |
Adds 1 to the operand and stores the result back into the operand.
Code | Cycles | Operands |
---|---|---|
01000rrr | 1 | Register |
1111111W aa000mmm | 1-3 | Memory |
The Register variant of this instruction is a 16-bit operation.
The zero flag (Z
) is set when the result of the addition is
zero, or is cleared otherwise.
The sign flag (S
) is set when the highest bit of the result is
set, or is cleared otherwise.
The overflow flag (V
) is set when the original value was 127
for byte or 32,767 for word, or is cleared otherwise.
The parity flag (P
) is set when the number of set bits in the
lower 8 bits of the result is even, or is cleared otherwise.
The auxiliary carry flag (AC
) will be set if the lowest 4 bits
of the original value were all set, or is cleared otherwise.
The number of cycles taken by the Memory variant of this instruction depends on the operand:
1 | The operand is a register. |
3 | The operand is an offset. |
MUL
- Multiply SignedNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
MUL | IMUL | ★ | ★ | ✓ | ✓ | ★ | ★ | Multiply Signed | See below. |
Performs a signed multiplication of the operands. The exact operation depends on which variant of the instruction is being executed.
Code | Cycles | Operands |
---|---|---|
011010S1 aarrrmmm | 3-4 | Register, Memory, Immediate |
1111011W aa101mmm | 3-4 | Memory |
The three-operand variant of this instruction performs a signed 16-bit multiplication. The memory and immediate operands are multiplied together, and the lower 16 bits of the product are stored into the register operand.
If the three-operand variant of this instruction specifies a memory operand that matches the register operand, the register can optionally be written only once, forming a two-operand instruction with it and the immediate operand.
The Memory variant of this instruction performs a signed 8- or 16-bit
multiplication with the accumulator and the operand. As an 8-bit operation,
the upper 8 bits of the product are stored into AH
and the lower
8 bits of the result are stored into AL
. As a 16-bit operation,
the upper 16 bits of the result are stored into DW
and the lower
16 bits of the result are stored into AW
.
The overflow (V
) and carry (CY
) flags are set if
the full product is not a sign-extension of the lowest 8 or 16 bits of the
product (depending on the size of the operation), or are cleared otherwise.
The zero (Z
) flag is always set.
The sign (S
), parity (P
) and auxiliary carry
(AC
) flags are always cleared.
The number of cycles taken by either variant of this instruction depends on the memory operand:
3 | The memory operand is a register. |
4 | The memory operand is an offset. |
★ In the V Series specification, the zero (Z
), sign
(S
), parity (P
) and auxiliary carry
(AC
) flags have unspecified states after this instruction
completes.
MULU
- Multiply UnsignedNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
MULU | MUL | ★ | ★ | ✓ | ✓ | ★ | ★ | Multiply Unsigned | See below. |
Performs an unsigned multiplication of the accumulator and the operand. As an
8-bit operation, the upper 8 bits of the product are stored into
AH
and the lower 8 bits of the product are stored into
AL
. As a 16-bit operation, the upper 16 bits of the result are
stored into DW
and the lower 16 bits of the result are stored
into AW
.
Code | Cycles | Operands |
---|---|---|
1111011W aa100mmm | 3-4 | Memory |
The overflow (V
) and carry (CY
) flags will be set
if the upper half of the product is not zero, or are cleared otherwise.
The zero (Z
) flag is always set.
The sign (S
), parity (P
) and auxiliary carry
(AC
) flags are always cleared.
The number of cycles taken by this instruction depends on the operand:
3 | The operand is a register. |
4 | The operand is an offset. |
★ In the V Series specification, the zero (Z
), sign
(S
), parity (P
) and auxiliary carry
(AC
) flags have unspecified states after this instruction
completes.
NEG
- NegateNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
NEG | NEG | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | Negate | dest = 0 - dest |
Calculates the additive inverse of dest by subtracting dest from zero, and stores the result back into dest.
Code | Cycles | Operands |
---|---|---|
1111011W aa011mmm | 1-3 | Memory |
The zero flag (Z
) is set when the result of the negation is
zero, or is cleared otherwise.
The sign flag (S
) is set when the highest bit of the result is
set, or is cleared otherwise.
The overflow flag (V
) is set if the original value was -128 for
byte or -32,768 for word, or is cleared otherwise.
The carry flag (CY
) is set if the original value was not zero,
or is cleared otherwise.
The parity flag (P
) is set when the number of set bits in the
lower 8 bits of the result is even, or is cleared otherwise.
The auxiliary carry flag (AC
) is set if any of the lowest 4 bits
of the original value were set, or is cleared otherwise.
The number of cycles taken by this instruction depends on the operand:
1 | The operand is a register. |
3 | The operand is an offset. |
SUB
- SubtractNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
SUB | SUB | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | Subtract | dest = dest - src |
Subtracts the two operands. The result is stored in the left operand.
Code | Cycles | Operands |
---|---|---|
001010DW aarrrmmm | 1-3 | Memory, Register |
0010110W | 1 | Accumulator, Immediate |
100000sW aa101mmm | 1-3 | Memory, Immediate |
The zero flag (Z
) is set when the result of the subtraction is
zero, or is cleared otherwise.
The sign flag (S
) is set when the highest bit of the result is
set, or is cleared otherwise.
The overflow flag (V
) is set when the operands have opposite
signs and the left operand and result have opposite signs, or is cleared
otherwise.
The carry flag (CY
) is set when the unsigned difference passes
zero, or is cleared otherwise.
The parity flag (P
) is set when the number of set bits in the
lower 8 bits of the result is even, or is cleared otherwise.
The auxiliary carry flag (AC
) is set when the unsigned
difference of the lowest 4 bits of the operands passes zero, or is cleared
otherwise.
The number of cycles taken by the Memory/Register variant of this instruction depends on the operands:
1 | Both operands are registers. |
2 | The source operand is an offset. |
3 | The destination operand is an offset. |
The number of cycles taken by the Memory/Immediate variant of this instruction depends on the operands:
1 | The destination operand is a register. |
3 | The destination operand is an offset. |
SUBC
- Subtract with CarryNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
SUBC | SBC | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | Subtract | dest = dest - src - CY |
Subtracts the two operands, minus 1 more if the carry flag (CY
)
was set. The result is stored in the left operand.
Code | Cycles | Operands |
---|---|---|
000110DW aarrrmmm | 1-3 | Memory, Register |
0001110W | 1 | Accumulator, Immediate |
100000sW aa011mmm | 1-3 | Memory, Immediate |
The zero flag (Z
) is set when the result of the subtraction is
zero, or is cleared otherwise.
The sign flag (S
) is set when the highest bit of the result is
set, or is cleared otherwise.
The overflow flag (V
) is set when the operands have opposite
signs and the left operand and result have opposite signs, or is cleared
otherwise.
The carry flag (CY
) is set when the unsigned difference passes
zero, or is cleared otherwise.
The parity flag (P
) is set when the number of set bits in the
lower 8 bits of the result is even, or is cleared otherwise.
The auxiliary carry flag (AC
) is set when the unsigned
difference of the lowest 4 bits of the operands passes zero, or is cleared
otherwise.
The number of cycles taken by the Memory/Register variant of this instruction depends on the operands:
1 | Both operands are registers. |
2 | The source operand is an offset. |
3 | The destination operand is an offset. |
The number of cycles taken by the Memory/Immediate variant of this instruction depends on the operands:
1 | The destination operand is a register. |
3 | The destination operand is an offset. |
NEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
AND | AND | ✓ | ✓ | 0 | 0 | ✓ | ? | And | dest = dest AND src |
NOT | NOT | - | - | - | - | - | - | Not | dest = NOT dest |
OR | OR | ✓ | ✓ | 0 | 0 | ✓ | ? | Or | dest = dest OR src |
ROL | ROL | - | - | ★ | ✓ | - | - | Rotate Left | dest = dest rotate left by src |
ROLC | RCL | - | - | ★ | ✓ | - | - | Rotate Left with Carry |
(CY ,dest) = (CY ,dest) rotate
left by src
|
ROR | ROR | - | - | ★ | ✓ | - | - | Rotate Right | dest = dest rotate right by src |
RORC | RCR | - | - | ★ | ✓ | - | - | Rotate Right with Carry |
(CY ,dest) = (CY ,dest) rotate
right by src
|
SHL | SHL | ✓ | ✓ | * | ✓ | ✓ | ? | Shift Left | dest = dest << src |
SHR | SHR | ✓ | ✓ | * | ✓ | ✓ | ? | Shift Right | dest = dest >> src (zero-filling) |
SHRA | SAR | ✓ | ✓ | * | ✓ | ✓ | ? | Shift Right Arithmetic | dest = dest >> src (sign-propagating) |
TEST | TEST | ✓ | ✓ | 0 | 0 | ✓ | ? | Test | (discard) = dest AND src |
XOR | XOR | ✓ | ✓ | 0 | 0 | ✓ | ? | Exclusive Or | dest = dest XOR src |
AND
- AndNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
AND | AND | ✓ | ✓ | 0 | 0 | ✓ | ? | And | dest = dest AND src |
Computes the bitwise AND of the operands. The result is stored in the left operand.
Code | Cycles | Operands |
---|---|---|
001000DW aarrrmmm | 1-3 | Memory, Register |
0010010W | 1 | Accumulator, Immediate |
100000sW aa100mmm | 1-3 | Memory, Immediate |
The zero flag (Z
) is set when the result of the operation is
zero, or is cleared otherwise.
The sign flag (S
) is set when the highest bit of the result is
set, or is cleared otherwise.
The overflow (V
) and carry (CY
) flags are cleared.
The parity flag (P
) is set when the number of set bits in the
lower 8 bits of the result is even, or is cleared otherwise.
The auxiliary carry flag (AC
) has an unspecified state after
this instruction completes.
The number of cycles taken by the Memory/Register variant of this instruction depends on the operands:
1 | Both operands are registers. |
2 | The source operand is an offset. |
3 | The destination operand is an offset. |
The number of cycles taken by the Memory/Immediate variant of this instruction depends on the operands:
1 | The destination operand is a register. |
3 | The destination operand is an offset. |
NOT
- NotNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
NOT | NOT | - | - | - | - | - | - | Not | dest = NOT dest |
Inverts the bits of the operand.
Code | Cycles | Operands |
---|---|---|
1111011W aa010mmm | 1-3 | Memory |
The number of cycles taken by this instruction depends on the operand:
1 | The operand is a register. |
3 | The operand is an offset. |
OR
- OrNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
OR | OR | ✓ | ✓ | 0 | 0 | ✓ | ? | Or | dest = dest OR src |
Computes the bitwise OR of the operands. The result is stored in the left operand.
Code | Cycles | Operands |
---|---|---|
000010DW aarrrmmm | 1-3 | Memory, Register |
0000110W | 1 | Accumulator, Immediate |
100000sW aa001mmm | 1-3 | Memory, Immediate |
The zero flag (Z
) is set when the result of the operation is
zero, or is cleared otherwise.
The sign flag (S
) is set when the highest bit of the result is
set, or is cleared otherwise.
The overflow (V
) and carry (CY
) flags are cleared.
The parity flag (P
) is set when the number of set bits in the
lower 8 bits of the result is even, or is cleared otherwise.
The auxiliary carry flag (AC
) has an unspecified state after
this instruction completes.
The number of cycles taken by the Memory/Register variant of this instruction depends on the operands:
1 | Both operands are registers. |
2 | The source operand is an offset. |
3 | The destination operand is an offset. |
The number of cycles taken by the Memory/Immediate variant of this instruction depends on the operands:
1 | The destination operand is a register. |
3 | The destination operand is an offset. |
ROL
- Rotate LeftNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
ROL | ROL | - | - | ★ | ✓ | - | - | Rotate Left | dest = dest rotate left by src |
Performs a left bitwise rotation on the value of the destination by the number of bits given by the source, and stores the result into the destination.
For each bit of rotation, a left shift is performed on dest, and the previous highest bit becomes the new lowest bit.
Code | Cycles | Operands |
---|---|---|
1100000W aa000mmm | 3-5 | Memory, Immediate |
1101000W aa000mmm | 1-3 | Memory, 1 |
1101001W aa000mmm | 3-5 | Memory, CL |
Only the lowest 5 bits of src are used in the operation.
If dest is an offset, the read and write memory accesses are performed even when src is zero.
The size of the immediate operand in the Memory/Immediate variant of this instruction is always one byte.
If src is zero, the carry flag (CY
) is not modified.
Otherwise, it becomes a copy of the lowest bit of the result of the
operation.
The overflow flag (V
) is set if the highest bit of dest
changes during the final bit of rotation, or is cleared otherwise.
The numbers of cycles taken by the Memory/Immediate and
Memory/CL
variants of this instruction depend on the memory
operand:
3 | The memory operand is a register. |
5 | The memory operand is an offset. |
The number of cycles taken by the Memory/1 variant of this instruction depends on the memory operand:
1 | The memory operand is a register. |
3 | The memory operand is an offset. |
★ In the V Series specification, the overflow (V
) flag has
unspecified state after the Memory/Immediate and Memory/CL
variants of this instruction complete.
ROLC
- Rotate Left with CarryNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
ROLC | RCL | - | - | ★ | ✓ | - | - | Rotate Left with Carry |
(CY ,dest) = (CY ,dest) rotate
left by src
|
Performs a left bitwise rotation on a value formed by treating
CY
as an additional bit one place higher than the highest bit of
the destination. The number of bits to rotate is given by the source, and the
result is stored into CY
and the destination.
For each bit of rotation, a left shift is performed on dest,
CY
is used as the new lowest bit of dest, and the
previous highest bit of dest becomes the new CY
.
Code | Cycles | Operands |
---|---|---|
1100000W aa010mmm | 3-5 | Memory, Immediate |
1101000W aa010mmm | 1-3 | Memory, 1 |
1101001W aa010mmm | 3-5 | Memory, CL |
Only the lowest 5 bits of src are used in the operation.
If dest is an offset, the read and write memory accesses are performed even when src is zero.
The size of the immediate operand in the Memory/Immediate variant of this instruction is always one byte.
If src is zero, the carry flag (CY
) is not modified.
Otherwise, it is modified as described above.
The overflow flag (V
) is set if the highest bit of dest
changes during the final bit of rotation, or is cleared otherwise.
The numbers of cycles taken by the Memory/Immediate and
Memory/CL
variants of this instruction depend on the memory
operand:
3 | The memory operand is a register. |
5 | The memory operand is an offset. |
The number of cycles taken by the Memory/1 variant of this instruction depends on the memory operand:
1 | The memory operand is a register. |
3 | The memory operand is an offset. |
★ In the V Series specification, the overflow (V
) flag has
unspecified state after the Memory/Immediate and Memory/CL
variants of this instruction complete.
ROR
- Rotate RightNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
ROR | ROR | - | - | ★ | ✓ | - | - | Rotate Right | dest = dest rotate right by src |
Performs a right bitwise rotation on the value of the destination by the number of bits given by the source, and stores the result into the destination.
For each bit of rotation, a right shift is performed on dest, and the previous lowest bit becomes the new highest bit.
Code | Cycles | Operands |
---|---|---|
1100000W aa001mmm | 3-5 | Memory, Immediate |
1101000W aa001mmm | 1-3 | Memory, 1 |
1101001W aa001mmm | 3-5 | Memory, CL |
Only the lowest 5 bits of src are used in the operation.
If dest is an offset, the read and write memory accesses are performed even when src is zero.
The size of the immediate operand in the Memory/Immediate variant of this instruction is always one byte.
If src is zero, the carry flag (CY
) is not modified.
Otherwise, it becomes a copy of the highest bit of the result of the
operation.
The overflow flag (V
) is set if the highest bit of dest
changes during the final bit of rotation, or is cleared otherwise.
The numbers of cycles taken by the Memory/Immediate and
Memory/CL
variants of this instruction depend on the memory
operand:
3 | The memory operand is a register. |
5 | The memory operand is an offset. |
The number of cycles taken by the Memory/1 variant of this instruction depends on the memory operand:
1 | The memory operand is a register. |
3 | The memory operand is an offset. |
★ In the V Series specification, the overflow (V
) flag has
unspecified state after the Memory/Immediate and Memory/CL
variants of this instruction complete.
RORC
- Rotate Right with CarryNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
ROLC | RCL | - | - | ★ | ✓ | - | - | Rotate Left with Carry |
(CY ,dest) = (CY ,dest) rotate
right by src
|
Performs a right bitwise rotation on a value formed by treating
CY
as an additional bit one place higher than the highest bit of
the destination. The number of bits to rotate is given by the source, and the
result is stored into CY
and the destination.
For each bit of rotation, a right shift is performed on dest,
CY
is used as the new highest bit of dest, and the
previous lowest bit of dest becomes the new CY
.
Code | Cycles | Operands |
---|---|---|
1100000W aa011mmm | 3-5 | Memory, Immediate |
1101000W aa011mmm | 1-3 | Memory, 1 |
1101001W aa011mmm | 3-5 | Memory, CL |
Only the lowest 5 bits of src are used in the operation.
If dest is an offset, the read and write memory accesses are performed even when src is zero.
The size of the immediate operand in the Memory/Immediate variant of this instruction is always one byte.
If src is zero, the carry flag (CY
) is not modified.
Otherwise, it is modified as described above.
The overflow flag (V
) is set if the highest bit of dest
changes during the final bit of rotation, or is cleared otherwise.
The numbers of cycles taken by the Memory/Immediate and
Memory/CL
variants of this instruction depend on the memory
operand:
3 | The memory operand is a register. |
5 | The memory operand is an offset. |
The number of cycles taken by the Memory/1 variant of this instruction depends on the memory operand:
1 | The memory operand is a register. |
3 | The memory operand is an offset. |
★ In the V Series specification, the overflow (V
) flag has
unspecified state after the Memory/Immediate and Memory/CL
variants of this instruction complete.
SHL
- Shift LeftNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
SHL | SHL | ✓ | ✓ | * | ✓ | ✓ | ? | Shift Left | dest = dest << src |
Performs a left bitwise shift on the value of the destination by the number of bits given by the source, and stores the result into the destination. Bits shifted in on the right are zeroes.
Code | Cycles | Operands |
---|---|---|
1100000W aa100mmm | 3-5 | Memory, Immediate |
1101000W aa100mmm | 1-3 | Memory, 1 |
1101001W aa100mmm | 3-5 | Memory, CL |
Only the lowest 5 bits of src are used in the operation.
If dest is an offset, the read and write memory accesses are performed even when src is zero.
The size of the immediate operand in the Memory/Immediate variant of this instruction is always one byte.
The zero flag (Z
) is set when the result of the shift is zero,
or is cleared otherwise.
The sign flag (S
) is set when the highest bit of the result is
set, or is cleared otherwise.
If src is zero, the carry flag (CY
) is not modified.
Otherwise, it becomes a copy of the last bit that was shifted out of the left
side of the register.
For the Memory/1 variant of this instruction, the overflow flag
(V
) is set if the highest bit of dest changes, or is
cleared otherwise. For other variants of this instruction, the overflow flag
has an unspecified state after the instruction completes.
The parity flag (P
) is set when the number of set bits in the
lower 8 bits of the result is even, or is cleared otherwise.
The auxiliary carry flag (AC
) has an unspecified state after
this instruction completes.
The numbers of cycles taken by the Memory/Immediate and
Memory/CL
variants of this instruction depend on the memory
operand:
3 | The memory operand is a register. |
5 | The memory operand is an offset. |
The number of cycles taken by the Memory/1 variant of this instruction depends on the memory operand:
1 | The memory operand is a register. |
3 | The memory operand is an offset. |
SHR
- Shift RightNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
SHR | SHR | ✓ | ✓ | * | ✓ | ✓ | ? | Shift Right | dest = dest >> src (zero-filling) |
Performs a right bitwise shift on the value of the destination by the number of bits given by the source, and stores the result into the destination. Bits shifted in on the left are zeroes.
Code | Cycles | Operands |
---|---|---|
1100000W aa101mmm | 3-5 | Memory, Immediate |
1101000W aa101mmm | 1-3 | Memory, 1 |
1101001W aa101mmm | 3-5 | Memory, CL |
Only the lowest 5 bits of src are used in the operation.
If dest is an offset, the read and write memory accesses are performed even when src is zero.
The size of the immediate operand in the Memory/Immediate variant of this instruction is always one byte.
The zero flag (Z
) is set when the result of the shift is zero,
or is cleared otherwise.
The sign flag (S
) is set when the highest bit of the result is
set, or is cleared otherwise.
If src is zero, the carry flag (CY
) is not modified.
Otherwise, it becomes a copy of the last bit that was shifted out of the
right side of the register.
For the Memory/1 variant of this instruction, the overflow flag
(V
) is set if the highest bit of dest changes, or is
cleared otherwise. For other variants of this instruction, the overflow flag
has an unspecified state after the instruction completes.
The parity flag (P
) is set when the number of set bits in the
lower 8 bits of the result is even, or is cleared otherwise.
The auxiliary carry flag (AC
) has an unspecified state after
this instruction completes.
The numbers of cycles taken by the Memory/Immediate and
Memory/CL
variants of this instruction depend on the memory
operand:
3 | The memory operand is a register. |
5 | The memory operand is an offset. |
The number of cycles taken by the Memory/1 variant of this instruction depends on the memory operand:
1 | The memory operand is a register. |
3 | The memory operand is an offset. |
SHRA
- Shift Right ArithmeticNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
SHRA | SAR | ✓ | ✓ | * | ✓ | ✓ | ? | Shift Right Arithmetic | dest = dest >> src (sign-propagating) |
Performs a right bitwise shift on the value of the destination by the number of bits given by the source, and stores the result into the destination. Bits shifted in on the left are copies of the highest bit of the original value.
Code | Cycles | Operands |
---|---|---|
1100000W aa111mmm | 3-5 | Memory, Immediate |
1101000W aa111mmm | 1-3 | Memory, 1 |
1101001W aa111mmm | 3-5 | Memory, CL |
Only the lowest 5 bits of src are used in the operation.
If dest is an offset, the read and write memory accesses are performed even when src is zero.
The size of the immediate operand in the Memory/Immediate variant of this instruction is always one byte.
The zero flag (Z
) is set when the result of the shift is zero,
or is cleared otherwise.
The sign flag (S
) is set when the highest bit of the result is
set, or is cleared otherwise.
If src is zero, the carry flag (CY
) is not modified.
Otherwise, becomes a copy of the last bit that was shifted out of the right
side of the register.
For the Memory/1 variant of this instruction, the overflow flag
(V
) is set if the highest bit of dest changes, or is
cleared otherwise. For other variants of this instruction, the overflow flag
has an unspecified state after the instruction completes.
The parity flag (P
) is set when the number of set bits in the
lower 8 bits of the result is even, or is cleared otherwise.
The auxiliary carry flag (AC
) has an unspecified state after
this instruction completes.
The numbers of cycles taken by the Memory/Immediate and
Memory/CL
variants of this instruction depend on the memory
operand:
3 | The memory operand is a register. |
5 | The memory operand is an offset. |
The number of cycles taken by the Memory/1 variant of this instruction depends on the memory operand:
1 | The memory operand is a register. |
3 | The memory operand is an offset. |
TEST
- TestNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
TEST | TEST | ✓ | ✓ | 0 | 0 | ✓ | ? | Test | (discard) = dest AND src |
Computes the bitwise AND of the operands, updates the status flags accordingly, and discards the result.
Code | Cycles | Operands |
---|---|---|
1000010W aarrrmmm | 1-2 | Register, Memory |
1010100W | 1 | Accumulator, Immediate |
1111011W aa000mmm | 1-2 | Memory, Immediate |
The zero flag (Z
) is set when the result of the operation is
zero, or is cleared otherwise.
The sign flag (S
) is set when the highest bit of the result is
set, or is cleared otherwise.
The overflow (V
) and carry (CY
) flags are cleared.
The parity flag (P
) is set when the number of set bits in the
lower 8 bits of the result is even, or is cleared otherwise.
The auxiliary carry flag (AC
) has an unspecified state after
this instruction completes.
The numbers of cycles taken by the Register/Memory and Memory/Immediate variants of this instruction depend on the memory operand:
1 | The memory operand is a register. |
2 | The memory operand is an offset. |
XOR
- Exclusive OrNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
XOR | XOR | ✓ | ✓ | 0 | 0 | ✓ | ? | Exclusive Or | dest = dest XOR src |
Computes the bitwise exclusive OR of the operands. The result is stored in the left operand.
Code | Cycles | Operands |
---|---|---|
001100DW aarrrmmm | 1-3 | Memory, Register |
0011010W | 1 | Accumulator, Immediate |
100000sW aa110mmm | 1-3 | Memory, Immediate |
The zero flag (Z
) is set when the result of the operation is
zero, or is cleared otherwise.
The sign flag (S
) is set when the highest bit of the result is
set, or is cleared otherwise.
The overflow (V
) and carry (CY
) flags are cleared.
The parity flag (P
) is set when the number of set bits in the
lower 8 bits of the result is even, or is cleared otherwise.
The auxiliary carry flag (AC
) has an unspecified state after
this instruction completes.
The number of cycles taken by the Memory/Register variant of this instruction depends on the operands:
1 | Both operands are registers. |
2 | The source operand is an offset. |
3 | The destination operand is an offset. |
The number of cycles taken by the Memory/Immediate variant of this instruction depends on the operands:
1 | The destination operand is a register. |
3 | The destination operand is an offset. |
NEC | Intel | Name | Operation |
---|---|---|---|
BUSLOCK | LOCK | Bus Lock | Execute instruction with full control of the bus |
NEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
BR | JMP | - | - | - | - | - | - | Branch | Unconditional jump |
BRK | INT , INT3 |
- | - | - | - | - | - | Break | Raise exception vector |
BRKV | INTO | - | - | - | - | - | - | Break if Overflow | If V = 1, raise exception 4 |
CALL | CALL | - | - | - | - | - | - | Call | Call subroutine |
CHKIND | BOUND | - | - | - | - | - | - | Check Index | Array bounds check |
CLR1 | CLC , CLD |
- | - | - | * | - | - | Clear Bit | dest = 0 |
DI | CLI | - | - | - | - | - | - | Disable Interrupt | IE = 0 |
DISPOSE | LEAVE | - | - | - | - | - | - | Dispose a Stack Frame | SP = BP , pop BP |
EI | STI | - | - | - | - | - | - | Enable Interrupt | IE = 1 |
HALT | HLT | - | - | - | - | - | - | Halt | Wait for interrupt |
NOT1 | CMC | - | - | - | ✓ | - | - | Not Bit | CY = NOT CY |
POLL | WAIT | - | - | - | - | - | - | Poll and Wait | No operation. |
PREPARE | ENTER | - | - | - | - | - | - | Prepare New Stack Frame | See instruction for details. |
RET | RET | - | - | - | - | - | - | Return from Procedure | Return from subroutine |
RETI | IRET | * | * | * | * | * | * | Return from Interrupt | Return from exception handling |
SET1 | STC , STD |
- | - | - | * | - | - | Set Bit | dest = 1 |
BUSLOCK
- Bus Lock PrefixNEC | Intel | Name | Operation |
---|---|---|---|
BUSLOCK | LOCK | Bus Lock Prefix | Execute instruction with full control of the bus |
This is a prefix that applies to all instructions.
When the instruction prefixed by BUSLOCK
executes, the CPU has
full control of the memory bus until the instruction completes. Any other
component that attempts to access the bus during this time will be stalled,
and any interrupts will be held,
until the lock is released.
Code | Cycles |
---|---|
11110000 | 1 |
If the prefixed instruction is a block instruction that is also prefixed by REP, the bus will remain locked until all repetitions are fully processed.
BR
- BranchNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
BR | JMP | - | - | - | - | - | - | Branch | Unconditional jump |
Unconditionally redirects the program to another address:
♦ |
If 32-bit:
|
||
▪ | PC = Destination PC |
Code | Cycles | Operands |
---|---|---|
11101001 | 4 | 16-bit Displacement |
11101010 | 7 | 32-bit Immediate |
11101011 | 4 | 8-bit Displacement |
1111111- aa100mmm | 4-5 | 16-bit Memory |
1111111- aa101mmm | 10 | 32-bit Memory |
Displacement values are signed values that appear as additional bytes of
program code and are added to PC
to produce the destination
offset. A 16-bit displacement value is stored with the low byte first. The
value of PC
to which the displacement is added is the offset of
the first byte of the instruction following the BR
instruction.
The 32-bit variants of this instruction load 4 consecutive bytes as the
destination. The first two bytes are the new value for PC
(low
byte first), and the second two bytes are the new value for PS
(low byte first).
For the 32-bit Immediate variant of this instruction, the 4 destination bytes are present as additional bytes of program code.
If the 32-bit Memory variant of this instruction specifies a register for the memory operand, the segment and offset of the branch are undefined.
The number of cycles taken by the 16-bit Memory variant of this instruction depends on the operand:
4 | The operand is a register. |
5 | The operand is an offset. |
There is no distinction in assembly notation to differentiate between the in-segment and out-of-segment variants of this instruction. It is intended that the assembler selects the appropriate variant depending on how the procedure's scope is defined (such as "near" for in-segment or "far" for out-of-segment). Common assemblers have introduced distinct mnemonics to denote which instruction is being used:
NASM | AT&T | |
---|---|---|
JMP NEAR | jmp | In segment |
JMP FAR | ljmp | Out of segment |
BRK
- BreakNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
BRK | INT , INT3 |
- | - | - | - | - | - | Break | Raise exception vector |
Raises an exception with the vector given by the operand.
Code | Cycles | Operands |
---|---|---|
11001100 | 9 | 3 [note] |
11001101 | 9-10 | Immediate |
[note] |
The Intel notation for the 3 variant of this instruction
has the mnemonic INT3 and has zero operands.
|
The immediate value is 8-bit and unsigned.
The number of cycles taken by the Immediate variant of this instruction depends on the operand:
9 | The vector is 3. |
10 | The vector is not 3. |
Editor's Note: On other 8086-style CPUs, the single-byte BRK 3
instruction is given special significance: it can apply in situations where
the operand variant can't, and can process the handler with an elevated
privilege mode. It is intended for software debugging.
BRKV
- Break if OverflowNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
BRKV | INTO | - | - | - | - | - | - | Break if Overflow | If V = 1, raise exception 4 |
If the overflow flag (V
) is set, raises an
exception with vector 4.
Code | Cycles | Operands |
---|---|---|
11001110 | 6-13 | None |
The number of cycles taken by BRKV
depends on V
:
6 | V is clear. |
13 | V is set. |
CALL
- CallNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
CALL | CALL | - | - | - | - | - | - | Call | Call subroutine |
Calls a subroutine, saving the return address on the stack according to the following algorithm:
♦ |
If 32-bit:
|
||||
▪ | Push PC |
||||
▪ | PC = Destination PC |
The value of PC
to which the subroutine will return is the
offset of the first byte of the instruction following the CALL
instruction.
Code | Cycles | Operands |
---|---|---|
10011010 | 10 | 32-bit Immediate |
11101000 | 5 | 16-bit Displacement |
1111111- aa010mmm | 5-6 | 16-bit Memory |
1111111- aa011mmm | 12 | 32-bit Memory |
The 32-bit variants of this instruction load 4 consecutive bytes as the
destination. The first two bytes are the new value for PC
(low
byte first), and the second two bytes are the new value for
PS
(low byte first).
For the 32-bit Immediate variant of this instruction, the 4 destination bytes are present as additional bytes of program code.
For the 16-bit Displacement variant of this instruction, the displacement
value is a signed value that appears as additional bytes of program code
and are added to PC
to produce the destination offset. It is
stored with the low byte first. The value of PC
to which the
displacement is added is the offset of the first byte of the instruction
following the CALL
instruction.
If the 32-bit Memory variant of this instruction specifies a register for the memory operand, the segment and offset of the call are undefined.
The number of cycles taken by the 16-bit Memory variant of this instruction depends on the operand:
5 | The operand is a register. |
6 | The operand is an offset. |
There is no distinction in assembly notation to differentiate between the in-segment and out-of-segment variants of this instruction. It is intended that the assembler selects the appropriate variant depending on how the procedure's scope is defined (such as "near" for in-segment or "far" for out-of-segment). Common assemblers have introduced distinct mnemonics to denote which instruction is being used:
NASM | AT&T | |
---|---|---|
CALL NEAR | call | In segment |
CALL FAR | lcall | Out of segment |
CHKIND
- Check IndexNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
CHKIND | BOUND | - | - | - | - | - | - | Check Index | Array bounds check |
Performs an array bounds check by loading two consecutive 16-bit values from the memory operand (low byte first). The first value is the lower bound of the array and the second value is the upper bound of the array. If the value in the register operand is not greater than or equal to the lower bound and less than or equal to the upper bound, an exception is raised with vector 5.
Code | Cycles | Operands |
---|---|---|
01100010 aarrrmmm | 13-20 | Register, Memory |
This operation performs signed comparisons.
If a register is specified for the memory operand, the offset accessed in memory will be undefined.
The default segment register for this
instruction is DS0
. The segment register to use can be selected
with a segment override prefix.
The number of cycles taken by this instruction depends on whether or not an exception is raised:
13 | An exception is not raised. |
20 | An exception is raised. |
CLR1
- Clear BitNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
CLR1 | CLC , CLD |
- | - | - | * | - | - | Clear Bit | dest = 0 |
Clears the bit specified by the operand.
Code | Cycles | Operands |
---|---|---|
11111000 | 4 | CY [note 1] |
11111100 | 4 | DIR [note 2] |
[note 1] |
The Intel notation for the CY variant of this instruction
has the mnemonic CLC and has zero operands.
|
[note 2] |
The Intel notation for the DIR variant of this instruction
has the mnemonic CLD and has zero operands.
|
This instruction will only modify the flag in PSW specified by its operand.
DI
- Disable InterruptNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
DI | CLI | - | - | - | - | - | - | Disable Interrupt | IE = 0 |
The interrupt enable flag (IE
) is cleared.
Code | Cycles | Operands |
---|---|---|
11111010 | 4 | None |
DISPOSE
- Dispose a Stack FrameNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
DISPOSE | LEAVE | - | - | - | - | - | - | Dispose a Stack Frame | SP = BP , pop BP |
Stores the value in BP
into SP
, then pops
BP
from the new stack location.
This instruction is the counterpart to PREPARE.
Code | Cycles | Operands |
---|---|---|
11001001 | 2 | None |
EI
- Enable InterruptNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
EI | STI | - | - | - | - | - | - | Enable Interrupt | IE = 1 |
The interrupt enable flag (IE
) is set.
Code | Cycles | Operands |
---|---|---|
11111011 | 4 | None |
If IE
was clear prior to executing this instruction, then prior
to executing the following instruction,
interrupts will not be accepted.
HALT
- HaltNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
HALT | HLT | - | - | - | - | - | - | Halt | Wait for interrupt |
Suspends the CPU until an interrupt
is requested. After an interrupt is requested (which may result in a handler
routine ending with RETI), execution
will continue at the instruction following the HALT
instruction.
Code | Cycles | Operands |
---|---|---|
11110100 | 9 | None |
HALT
will always complete when an interrupt is requested. If the
IE
flag in PSW is clear,
exception processing will be prevented, but the program will nonetheless
still resume.
NOT1
- Not BitNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
NOT1 | CMC | - | - | - | ✓ | - | - | Not Bit | CY = NOT CY |
Inverts the carry flag (CY
).
Code | Cycles | Operands |
---|---|---|
11110101 | 4 | CY |
POLL
- Poll and WaitNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
POLL | WAIT | - | - | - | - | - | - | Poll and Wait | No operation. |
Suspends the CPU pending any coprocessor operations. V30MZ has no coprocessor, so this instruction has no useful function other than to spend CPU cycles.
Code | Cycles | Operands |
---|---|---|
10011011 | 10 | None |
Editor's Note: The V Series specification cautions against using this instruction with BUSLOCK. No problematic operations have been observed on V30MZ.
PREPARE
- Prepare New Stack FrameNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
PREPARE | ENTER | - | - | - | - | - | - | Prepare New Stack Frame | See below. |
This instruction contains an 8-bit immediate operand of which only the lowest 5 bits are significant. This section refers to the operand as "the 5-bit immediate value" and "imm5".
Prepares a lexical stack frame by performing the following algorithm:
▪ | Push BP |
||||||||
▪ | temp = SP |
||||||||
♦ |
If imm5 > 0:
|
||||||||
▪ | BP = temp |
||||||||
▪ | SP = SP - imm16 |
This instruction is the counterpart to DISPOSE.
Code | Cycles | Operands |
---|---|---|
11001000 | 8+ | 16-bit Immediate, 8-bit Immediate |
The opcode byte is followed by the 16-bit immediate operand's bytes, which are in turn followed by the 8-bit immediate operand's byte.
This instruction's operands are unsigned.
The number of cycles taken by this instruction depends on the 5-bit immediate value:
8 | The 5-bit immediate value is 0. |
14 | The 5-bit immediate value is 1. |
15 + 4 * imm5 | The 5-bit immediate value is greater than 1. |
RET
- Return from ProcedureNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
RET | RET | - | - | - | - | - | - | Return from Procedure | Return from subroutine |
Returns from a subroutine, restoring PC
(and PS
where applicable) to the location when the subroutine was first called, plus
some number of additional stack bytes, according to the following algorithm:
▪ | Pop PC |
||
♦ |
If out of segment:
|
||
▪ | SP = SP + dest |
Code | Cycles | Scope | Operands |
---|---|---|---|
11000010 | 6 | In segment | Immediate |
11000011 | 6 | In segment | None |
11001010 | 9 | Out of segment | Immediate |
11001011 | 8 | Out of segment | None |
The immediate value is 16-bit and is added to SP
after restoring
PC
/PS
. This allows function input arguments to be
automatically released from the stack.
There is no distinction in assembly notation to differentiate between the in-segment and out-of-segment variants of this instruction. It is intended that the assembler selects the appropriate variant depending on how the procedure's scope is defined (such as "near" for in-segment or "far" for out-of-segment). Common assemblers have introduced distinct mnemonics to denote which instruction is being used:
NASM | AT&T | |
---|---|---|
RETN | ret | In segment |
RETF | lret | Out of segment |
RETI
- Return from InterruptNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
RETI | IRET | * | * | * | * | * | * | Return from Interrupt | Return from exception handling |
Returns from an exception or interrupt handler. The program will resume from wherever it left off: either the instruction following the instruction that raised the exception, or the instruction that would have been executed had an interrupt not occurred.
Performs the following algorithm:
▪ | Pop PC |
▪ | Pop PS |
▪ | Pop PSW |
Code | Cycles | Operands |
---|---|---|
11001111 | 10 | None |
The status flags in PSW are restored from
the stack. If this instruction causes the interrupt enable flag
(IE
) to transition from clear to set, then prior to executing
the following instruction, interrupts will not be accepted.
SET1
- Set BitNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
SET1 | STC , STD |
- | - | - | * | - | - | Set Bit | dest = 1 |
Sets the bit specified by the operand.
Code | Cycles | Operands |
---|---|---|
11111001 | 4 | CY [note 1] |
11111101 | 4 | DIR [note 2] |
[note 1] |
The Intel notation for the CY variant of this instruction
has the mnemonic STC and has zero operands.
|
[note 2] |
The Intel notation for the DIR variant of this instruction
has the mnemonic STD and has zero operands.
|
This instruction will only modify the flag in PSW specified by its operand.
These branch instructions conditionally redirect the program to another location. PC is modified if the condition is met, or the program will continue to the next instruction if the condition is not met. The condition typically tests various combinations of status flags in PSW.
Branch instructions are 2 bytes in size: the first byte is the opcode, and
the second byte is a signed displacement offset that is added to
PC
if the condition is true. The value of PC
to
which the displacement is added is the offset of the first byte of the
instruction following the branch instruction.
The number of cycles taken by branch instructions depends on whether or not the condition is true. If the branch is not taken, the number of cycles is given in the lists below. If the branch is taken, add 3 to that number of cycles.
Opcode | NEC | Intel | Branch if ... | Condition | Cycles | Note |
---|---|---|---|---|---|---|
01110010 | BC , BL |
JC , JB , JNAE |
Carry, Lower | if CY = 1 |
1+ | Unsigned |
11100011 | BCWZ | JCXZ | CW Equals Zero |
if CW = 0 |
1+ | |
01110100 |
BE , BZ
|
JE , JZ |
Equal, Zero | if Z = 1 |
1+ | |
01111101 | BGE | JGE , JNL |
Greater Than or Equal | if (S XOR V ) = 0 |
1+ | Signed |
01111111 | BGT | JG , JNLE |
Greater Than |
if ((S XOR V ) OR Z ) = 0
|
1+ | Signed |
01110111 | BH | JA , JNBE |
Higher | if (CY OR Z ) = 0 |
1+ | Unsigned |
01111110 | BLE | JLE , JNG |
Less Than or Equal |
if ((S XOR V ) OR Z ) = 1
|
1+ | Signed |
01111100 | BLT | JL , JNGE |
Less Than | if (S XOR V ) = 1 |
1+ | Signed |
01111000 | BN | JS | Negative | if S = 1 |
1+ | |
01110011 |
BNC , BNL
|
JNC , JAE , JNB
|
Not Carry, Not Lower | if CY = 0 |
1+ | Unsigned |
01110101 |
BNE , BNZ
|
JNE , JNZ |
Not Equal, Not Zero | if Z = 0 |
1+ | |
01110110 | BNH | JBE , JNA |
Not Higher | if (CY OR Z ) = 1 |
1+ | Unsigned |
01110001 | BNV | JNO | Not Overflow | if V = 0 |
1+ | |
01111001 | BP | JNS | Positive | if S = 0 |
1+ | |
01111010 | BPE | JPE | Parity Even | if P = 1 |
1+ | |
01111011 | BPO | JNP , JPO |
Parity Odd | if P = 0 |
1+ | |
01110000 | BV | JO | Overflow | if V = 1 |
1+ |
These instructions decrement CW
by 1 before testing the
condition. In this list, the decrement operation is omitted.
Opcode | NEC | Intel | Decrement and Branch if ... | Condition | Cycles |
---|---|---|---|---|---|
11100010 | DBNZ | LOOP | Not Zero | if CW ≠ 0 |
2+ |
11100001 | DBNZE | LOOPE , LOOPZ |
Not Zero and Equal |
if (CW ≠ 0) AND (Z = 1)
|
3+ |
11100000 | DBNZNE | LOOPNE , LOOPNZ |
Not Zero and Not Equal |
if (CW ≠ 0) AND (Z = 0)
|
3+ |
Block instructions are designed to be executed repeatedly by being used in
conjunction with the REP prefix. They
share a common behavior in that they will increment or decrement the
IX
and IY
registers as applicable, allowing
multiple units of memory to be processed with one instruction.
IX
and IY
are only updated if they are used in an
operation. The amount by which they are modified is 1 for 8-bit operations
and 2 for 16-bit operations. The sign of the modification depends on the
direction flag (DIR
): positive if DIR
is clear, or
negative if DIR
is set. In the list below, this operation is
omitted.
Mechanically, block instructions do not have any operands: they access specific registers as part of their normal operation. However, block instructions in assembly are still presented with operands describing the data being accessed. These operands are written in the following way:
• | The destination operand is always on the left. |
• |
IX and IY operands specify either
"BYTE PTR " for 8-bit or "WORD PTR " for 16-bit,
optionally specify a segment
register with a colon, then finally the register name is written
in [] square brackets.
|
• | If an accumulator is involved, it is not written as an operand. |
• |
If DW is involved, it is written as only the register name,
without any brackets.
|
Some block instructions have multiple mneomincs. The extra mnemonics specify the size of the operation and are written with zero operands. If one of these alternate mnemonics is used, there is no notation for specifying a segment override.
For examples of how any given block instruction may be written, see the documentation for each individual instruction.
NEC | Intel | Name | Operation |
---|---|---|---|
REP | REP | Repeat |
Repeat instruction according to CW and Z .
|
NEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
CMPBK | CMPS | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | Compare Block | (discard) = [IX ] - [IY ] |
CMPM | SCAS | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | Compare Multiple | (discard) = acc - [IY ] |
INM | INS | - | - | - | - | - | - | Input Multiple | (memory) [IY ] = (I/O) [DW ] |
LDM | LODS | - | - | - | - | - | - | Load Multiple | acc = [IX ] |
MOVBK | MOVS | - | - | - | - | - | - | Move Block | [IY ] = [IX ] |
OUTM | OUTS | - | - | - | - | - | - | Output Multiple | (I/O) [DW ] = (memory) [IX ] |
STM | STOS | - | - | - | - | - | - | Store Multiple | [IY ] = acc |
REP
- RepeatNEC | Intel | Name | Operation |
---|---|---|---|
REP | REP | Repeat |
Repeat instruction according to CW and Z .
|
This is a prefix that applies to block instructions. Performs the following algorithm:
♦ | While CW ≠ 0:
|
||||||||||
▪ | Proceed to the next instruction |
Code | Cycles |
---|---|
1111001Z | 5+ |
If the prefixed instruction is not a block instruction, REP
has
no effect. If the prefixed instruction is not
CMPBK or
CMPM, it will always be repeated
until CW
becomes zero.
For CMPBK
and CMPM
, Z
specifies the
state of the zero flag (Z
) in
PSW in order for the repetition to occur.
The condition is true when the bit in the opcode and the bit in
PSW
match.
The zero flag is not modified by the decrement operation performed by this prefix: it can only change if the prefixed instruction modifies it.
This prefix and its field are used with the following mnemonics:
NEC | Intel | Name | Condition |
---|---|---|---|
REP | REP | Repeat | if Z = 1 |
REPE | REPE | Repeat while Equal | if Z = 1 |
REPNE | REPNE | Repeat while Not Equal | if Z = 0 |
REPNZ | REPNZ | Repeat while Not Zero | if Z = 0 |
REPZ | REPZ | Repeat while Zero | if Z = 1 |
The number of cycles taken by an instruction with this prefix differs from the number of cycles taken by a stanalone execution of that instruction. There are always 5 cycles consumed by the prefix itself, as well as an additional number of cycles for each repetition depending on the instruction being repeated:
NEC | Intel | Name | Cycles | Note |
---|---|---|---|---|
CMPBK | CMPS | Compare Block | 5 + 9× | Z = 0 |
CMPBK | CMPS | Compare Block | 5 + 10× | Z = 1 |
CMPM | SCAS | Compare Multiple | 5 + 9× | |
INM | INS | Input Multiple | 5 + 6× | |
LDM | LODS | Load Multiple | 5 + 6× | |
MOVBK | MOVS | Move Block | 5 + 7× | |
OUTM | OUTS | Output Multiple | 5 + 6× | |
STM | STOS | Store Multiple | 5 + 6× |
CMPBK
- Compare BlockNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
CMPBK | CMPS | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | Compare Block | (discard) = [IX ] - [IY ] |
Takes the value in memory pointed to by IX
and subtracts the
value in memory pointed to by IY
, updates the status flags
accordingly, discards the result, and updates IX
and
IY
according to the size of the operation and the direction flag
(DIR
).
This instruction was designed to be used in conjunction with REP, but is valid as a standalone operation.
Code | Cycles | Operands |
---|---|---|
1010011W | 6 | [IX] , [IY] |
This instruction's operands are implicit and may be written in other ways:
• |
"DS1: " may be included in the "[IY] " operand.
|
• |
The mnemonic may be used to denote the size of the operation:
"CMPBKB " for byte and "CMPBKW " for word.
|
• | If the mnemonic denotes the size of the operation, the operands may be omitted. |
IX
and IY
are modified after accessing a value. If
the DIR
flag is clear, the registers are incremented, and if the
DIR
flag is set, the registers are decremented. The amount by
which the registers are modified depends on the size of the operation: 1 when
8-bit and 2 when 16-bit.
The zero flag (Z
) is set when the result of the subtraction is
zero, or is cleared otherwise.
The sign flag (S
) is set when the highest bit of the result is
set, or is cleared otherwise.
The overflow flag (V
) is set when the operands of the
subtraction have opposite signs and the left operand and result have opposite
signs, or is cleared otherwise.
The carry flag (CY
) is set when the unsigned difference passes
zero, or is cleared otherwise.
The parity flag (P
) is set when the number of set bits in the
lower 8 bits of the result is even, or is cleared otherwise.
The auxiliary carry flag (AC
) is set when the unsigned
difference of the lowest 4 bits of the operands passes zero, or is cleared
otherwise.
CMPM
- Compare MultipleNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
CMPM | SCAS | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | Compare Multiple | (discard) = acc - [IY ] |
Takes the value in AL
(if 8-bit) or AW
(if 16-bit)
and subtracts the value in memory pointed to by IY
, updates the
status flags accordingly, discards the result, and updates IY
according to the size of the operation and the direction flag
(DIR
).
This instruction was designed to be used in conjunction with REP, but is valid as a standalone operation.
Code | Cycles | Operands |
---|---|---|
1010111W | 4 | [IY] |
This instruction's operands are implicit and may be written in other ways:
• | An accumulator operand may be present as the first operand. |
• |
"DS1: " may be included in the "[IY] " operand.
|
• |
The mnemonic may be used to denote the size of the operation:
"CMPMB " for byte and "CMPMW " for word.
|
• | If the mnemonic denotes the size of the operation, the operands may be omitted. |
IY
is modified after accessing a value. If the DIR
flag is clear, IY
is incremented, and if the DIR
flag is set, IY
is decremented. The amount by which
IY
is modified depends on the size of the operation: 1 when
8-bit and 2 when 16-bit.
The zero flag (Z
) is set when the result of the subtraction is
zero, or is cleared otherwise.
The sign flag (S
) is set when the highest bit of the result is
set, or is cleared otherwise.
The overflow flag (V
) is set when the subtraction results in
signed wrap-around, or is cleared otherwise. For example, overflow will be
set when subtracting a positive number from a negative number produces a
positive result.
The carry flag (CY
) is set when the subtraction results in
unsigned wrap-around, or is cleared otherwise. For example, carry will be set
when subtracting a number from a lesser number.
The parity flag (P
) is set when the number of set bits in the
lower 8 bits of the result is even, or is cleared otherwise.
The auxiliary carry flag (AC
) is set or cleared through the same
conditions as CY
, but applies to the lowest 4 bits of the
operation.
INM
- Input MultipleNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
INM | INS | - | - | - | - | - | - | Input Multiple | (memory) [IY ] = (I/O) [DW ] |
Inputs the value from the I/O port pointed to by DW
, stores the
it in the memory pointed to by IY
, and updates IY
according to the size of the operation and the direction flag
(DIR
).
This instruction was designed to be used in conjunction with REP, but is valid as a standalone operation.
Code | Cycles | Operands |
---|---|---|
0110110W | 6 | [IY] , DW |
This instruction's operands are implicit and may be written in other ways:
• |
"DS1: " may be included in the "[IY] " operand.
|
• |
The mnemonic may be used to denote the size of the operation:
"INMB " for byte and "INMW " for word.
|
IY
is modified after accessing a value. If the DIR
flag is clear, IY
is incremented, and if the DIR
flag is set, IY
is decremented. The amount by which
IY
is modified depends on the size of the operation: 1 when
8-bit and 2 when 16-bit.
LDM
- Load MultipleNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
LDM | LODS | - | - | - | - | - | - | Load Multiple | acc = [IX ] |
Loads the value in the memory pointed to by IX
, stores the value
into AL
(if 8-bit) or AW
(if 16-bit), and updates
IX
according to the size of the operation and the direction flag
(DIR
).
This instruction was designed to be used in conjunction with REP, but is valid as a standalone operation.
Code | Cycles | Operands |
---|---|---|
1010110W | 3 | [IX] |
This instruction's operands are implicit and may be written in other ways:
• | An accumulator operand may be present as the first operand. |
• |
The mnemonic may be used to denote the size of the operation:
"LDMB " for byte and "LDMW " for word.
|
• | If the mnemonic denotes the size of the operation, the operands may be omitted. |
IX
is modified after accessing a value. If the DIR
flag is clear, IX
is incremented, and if the DIR
flag is set, IX
is decremented. The amount by which
IX
is modified depends on the size of the operation: 1 when
8-bit and 2 when 16-bit.
MOVBK
- Move BlockNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
MOVBK | MOVS | - | - | - | - | - | - | Move Block | [IY ] = [IX ] |
Loads the value in the memory pointed to by IX
, stores it into
the memory pointed to by IY
, and updates IX
and
IY
according to the size of the operation and the direction flag
(DIR
).
This instruction was designed to be used in conjunction with REP, but is valid as a standalone operation.
Code | Cycles | Operands |
---|---|---|
1010010W | 5 | [IY] , [IX] |
This instruction's operands are implicit and may be written in other ways:
• |
"DS1: " may be included in the "[IY] " operand.
|
• |
The mnemonic may be used to denote the size of the operation:
"MOVBKB " for byte and "MOVBKW " for word.
|
• | If the mnemonic denotes the size of the operation, the operands may be omitted. |
IX
and IY
are modified after accessing a value. If
the DIR
flag is clear, the registers are incremented, and if the
DIR
flag is set, the register are decremented. The amount by
which the registers are modified depends on the size of the operation: 1 when
8-bit and 2 when 16-bit.
OUTM
- Output MultipleNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
OUTM | OUTS | - | - | - | - | - | - | Output Multiple | (I/O) [DW ] = (memory) [IX ] |
Loads the value in the memory pointed to by IX
, outputs it to
the I/O port pointed to by DW
, and updates IX
according to the size of the operation and the direction flag
(DIR
).
This instruction was designed to be used in conjunction with REP, but is valid as a standalone operation.
Code | Cycles | Operands |
---|---|---|
0110111W | 7 | DW , [IX] |
This instruction's operands are implicit and may be written in other ways:
• |
The mnemonic may be used to denote the size of the operation:
"OUTMB " for byte and "OUTMW " for word.
|
IX
is modified after accessing a value. If the DIR
flag is clear, IX
is incremented, and if the DIR
flag is set, IX
is decremented. The amount by which
IX
is modified depends on the size of the operation: 1 when
8-bit and 2 when 16-bit.
STM
- Store MultipleNEC | Intel | Z | S | V | CY | P | AC | Name | Operation |
---|---|---|---|---|---|---|---|---|---|
STM | STOS | - | - | - | - | - | - | Load Multiple | [IY ] = acc |
Stores the value in AL
(if 8-bit) or AW
(if 16-bit)
into the memory pointed to by IY
, and updates
IY
according to the size of the operation and the direction flag
(DIR
).
This instruction was designed to be used in conjunction with REP, but is valid as a standalone operation.
Code | Cycles | Operands |
---|---|---|
1010101W | 3 | [IY] |
This instruction's operands are implicit and may be written in other ways:
• | An accumulator operand may be present as a second operand. |
• |
"DS1: " may be included in the "[IY] " operand.
|
• |
The mnemonic may be used to denote the size of the operation:
"STMB " for byte and "STMW " for word.
|
• | If the mnemonic denotes the size of the operation, the operands may be omitted. |
IY
is modified after accessing a value. If the DIR
flag is clear, IY
is incremented, and if the DIR
flag is set, IY
is decremented. The amount by which
IY
is modified depends on the size of the operation: 1 when
8-bit and 2 when 16-bit.
Whenever memory is accessed, a segment register is used in the calculation of the physical address. The default segment register to use is implicit depending on context, and in many cases can be explicitly selected using a one-byte segment override prefix that immediately precedes the program code of the instruction accessing memory.
The following are the various memory-access scenarios and how they interact with segment registers:
Default | Override | Scenario |
---|---|---|
DS0 | Yes | 16-bit direct memory |
DS0 | Yes |
Memory operand, not BP
base
|
SS | Yes | Memory operand, BP base |
DS0 | Yes | Block instruction, IX value |
DS1 | No | Block instruction, IY value |
DS0 | Yes | CHKIND instruction |
DS0 | Yes | TRANS instruction |
PS | No | Instruction fetch |
SS | No | Stack operation |
Code | NEC | Intel | Cycles |
---|---|---|---|
00111110 | DS0: | DS: | 1 |
00100110 | DS1: | ES: | 1 |
00101110 | PS: | CS: | 1 |
00110110 | SS: | SS: | 1 |
When a segment override prefix is used, the corresponding memory operation will use the segment register specified by the prefix instead of the operation's default segment register.
Opcode | Mnemonic | Operands | |
---|---|---|---|
00000000 | ADD | Memory (byte), Register (byte) | |
00000001 | ADD | Memory (word), Register (word) | |
00000010 | ADD | Register (byte), Memory (byte) | |
00000011 | ADD | Register (word), Memory (word) | |
00000100 | ADD | AL , Immediate (byte) |
|
00000101 | ADD | AW , Immediate (word) |
|
00000110 | PUSH | DS1 | |
00000111 | POP | DS1 | |
00001000 | OR | Memory (byte), Register (byte) | |
00001001 | OR | Memory (word), Register (word) | |
00001010 | OR | Register (byte), Memory (byte) | |
00001011 | OR | Register (word), Memory (word) | |
00001100 | OR | AL , Immediate (byte) |
|
00001101 | OR | AW , Immediate (word) |
|
00001110 | PUSH | PS | |
00001111 | Invalid [note 1] | ||
00010000 | ADDC | Memory (byte), Register (byte) | |
00010001 | ADDC | Memory (word), Register (word) | |
00010010 | ADDC | Register (byte), Memory (byte) | |
00010011 | ADDC | Register (word), Memory (word) | |
00010100 | ADDC | AL , Immediate (byte) |
|
00010101 | ADDC | AW , Immediate (word) |
|
00010110 | PUSH | SS | |
00010111 | POP | SS | |
00011000 | SUBC | Memory (byte), Register (byte) | |
00011001 | SUBC | Memory (word), Register (word) | |
00011010 | SUBC | Register (byte), Memory (byte) | |
00011011 | SUBC | Register (word), Memory (word) | |
00011100 | SUBC | AL , Immediate (byte) |
|
00011101 | SUBC | AW , Immediate (word) |
|
00011110 | PUSH | DS0 | |
00011111 | POP | DS0 | |
00100000 | AND | Memory (byte), Register (byte) | |
00100001 | AND | Memory (word), Register (word) | |
00100010 | AND | Register (byte), Memory (byte) | |
00100011 | AND | Register (word), Memory (word) | |
00100100 | AND | AL , Immediate (byte) |
|
00100101 | AND | AW , Immediate (word) |
|
00100110 | DS1: | ||
00100111 | ADJ4A | ||
00101000 | SUB | Memory (byte), Register (byte) | |
00101001 | SUB | Memory (word), Register (word) | |
00101010 | SUB | Register (byte), Memory (byte) | |
00101011 | SUB | Register (word), Memory (word) | |
00101100 | SUB | AL , Immediate (byte) |
|
00101101 | SUB | AW , Immediate (word) |
|
00101110 | PS: | ||
00101111 | ADJ4S | ||
00110000 | XOR | Memory (byte), Register (byte) | |
00110001 | XOR | Memory (word), Register (word) | |
00110010 | XOR | Register (byte), Memory (byte) | |
00110011 | XOR | Register (word), Memory (word) | |
00110100 | XOR | AL , Immediate (byte) |
|
00110101 | XOR | AW , Immediate (word) |
|
00110110 | SS: | ||
00110111 | ADJBA | ||
00111000 | CMP | Memory (byte), Register (byte) | |
00111001 | CMP | Memory (word), Register (word) | |
00111010 | CMP | Register (byte), Memory (byte) | |
00111011 | CMP | Register (word), Memory (word) | |
00111100 | CMP | AL , Immediate (byte) |
|
00111101 | CMP | AW , Immediate (word) |
|
00111110 | DS0: | ||
00111111 | ADJBS | ||
01000000 | INC | AW | |
01000001 | INC | CW | |
01000010 | INC | DW | |
01000011 | INC | BW | |
01000100 | INC | SP | |
01000101 | INC | BP | |
01000110 | INC | IX | |
01000111 | INC | IY | |
01001000 | DEC | AW | |
01001001 | DEC | CW | |
01001010 | DEC | DW | |
01001011 | DEC | BW | |
01001100 | DEC | SP | |
01001101 | DEC | BP | |
01001110 | DEC | IX | |
01001111 | DEC | IY | |
01010000 | PUSH | AW | |
01010001 | PUSH | CW | |
01010010 | PUSH | DW | |
01010011 | PUSH | BW | |
01010100 | PUSH | SP | |
01010101 | PUSH | BP | |
01010110 | PUSH | IX | |
01010111 | PUSH | IY | |
01011000 | POP | AW | |
01011001 | POP | CW | |
01011010 | POP | DW | |
01011011 | POP | BW | |
01011100 | POP | SP | |
01011101 | POP | BP | |
01011110 | POP | IX | |
01011111 | POP | IY | |
01100000 | PUSH | R | |
01100001 | POP | R | |
01100010 | CHKIND | Register (word), Memory (double word) | |
01100011 | Invalid | ||
01100100 | Invalid [note 2] | ||
01100101 | Invalid [note 2] | ||
01100110 | Invalid [note 3] | ||
01100111 | Invalid [note 3] | ||
01101000 | PUSH | Immediate (word) | |
01101001 | MUL | Register (word), Memory (word), Immediate (word) | |
01101010 | PUSH | Immediate (byte, sign-extended) | |
01101011 | MUL | Register (word), Memory (word), Immediate (byte, sign-extended) | |
01101100 | INMB | [IY] , DW |
|
01101101 | INMW | [IY] , DW |
|
01101110 | OUTMB | DW , [IX] |
|
01101111 | OUTMW | DW , [IX] |
|
01110000 | BV | Displacement (byte, sign-extended) | |
01110001 | BNV | Displacement (byte, sign-extended) | |
01110010 | BC, BL | Displacement (byte, sign-extended) | |
01110011 | BNC, BNL | Displacement (byte, sign-extended) | |
01110100 | BE, BZ | Displacement (byte, sign-extended) | |
01110101 | BNE, BNZ | Displacement (byte, sign-extended) | |
01110110 | BNH | Displacement (byte, sign-extended) | |
01110111 | BH | Displacement (byte, sign-extended) | |
01111000 | BN | Displacement (byte, sign-extended) | |
01111001 | BP | Displacement (byte, sign-extended) | |
01111010 | BPE | Displacement (byte, sign-extended) | |
01111011 | BPO | Displacement (byte, sign-extended) | |
01111100 | BLT | Displacement (byte, sign-extended) | |
01111101 | BGE | Displacement (byte, sign-extended) | |
01111110 | BLE | Displacement (byte, sign-extended) | |
01111111 | BGT | Displacement (byte, sign-extended) | |
10000000 | Immediate group: see below | Memory (byte), Immediate (byte) | |
10000001 | Immediate group: see below | Memory (word), Immediate (word) | |
10000010 | Immediate group: see below | Memory (byte), Immediate (byte) | |
10000011 | Immediate group: see below | Memory (word), Immediate (byte, sign-extended) | |
10000100 | TEST | Memory (byte), Register (byte) | |
10000101 | TEST | Memory (word), Register (word) | |
10000110 | XCH | Memory (byte), Register (byte) | |
10000111 | XCH | Memory (word), Register (word) | |
10001000 | MOV | Memory (byte), Register (byte) | |
10001001 | MOV | Memory (word), Register (word) | |
10001010 | MOV | Register (byte), Memory (byte) | |
10001011 | MOV | Register (word), Memory (word) | |
10001100 | MOV | Memory (word), Segment Register | |
10001011 | LDEA | Register (word), Memory (word) | |
10001110 | MOV | Segment Register, Memory (word) | |
10001111 | POP | Memory (word) | |
10010000 | NOP | ||
10010001 | XCH | AW , CW |
|
10010010 | XCH | AW , DW |
|
10010011 | XCH | AW , BW |
|
10010100 | XCH | AW , SP |
|
10010101 | XCH | AW , BP |
|
10010110 | XCH | AW , IX |
|
10010111 | XCH | AW , IY |
|
10011000 | CVTBW | ||
10011001 | CVTWL | ||
10011010 | CALL | Immediate (double word) | |
10011011 | POLL | ||
10011100 | PUSH | PSW | |
10011101 | POP | PSW | |
10011110 | MOV | PSW , AH |
|
10011111 | MOV | AH , PSW |
|
10100000 | MOV | AL , Direct Memory (byte) |
|
10100001 | MOV | AW , Direct Memory (word) |
|
10100010 | MOV | Direct Memory (byte), AL |
|
10100011 | MOV | Direct Memory (word), AW |
|
10100100 | MOVBKB | [IY] , [IX] |
|
10100101 | MOVBKW | [IY] , [IX] |
|
10100110 | CMPBKB | [IX] , [IY] |
|
10100111 | CMPBKW | [IX] , [IY] |
|
10101000 | TEST | AL , Immediate (byte) |
|
10101001 | TEST | AW , Immediate (word) |
|
10101010 | STMB | [IY] | |
10101011 | STMW | [IY] | |
10101100 | LDMB | [IX] | |
10101101 | LDMW | [IX] | |
10101110 | CMPMB | [IY] | |
10101111 | CMPMW | [IY] | |
10110000 | MOV | Register (byte), Immediate (byte) | |
10110001 | MOV | Register (byte), Immediate (byte) | |
10110010 | MOV | Register (byte), Immediate (byte) | |
10110011 | MOV | Register (byte), Immediate (byte) | |
10110100 | MOV | Register (byte), Immediate (byte) | |
10110101 | MOV | Register (byte), Immediate (byte) | |
10110110 | MOV | Register (byte), Immediate (byte) | |
10110111 | MOV | Register (byte), Immediate (byte) | |
10111000 | MOV | Register (word), Immediate (word) | |
10111001 | MOV | Register (word), Immediate (word) | |
10111010 | MOV | Register (word), Immediate (word) | |
10111011 | MOV | Register (word), Immediate (word) | |
10111100 | MOV | Register (word), Immediate (word) | |
10111101 | MOV | Register (word), Immediate (word) | |
10111110 | MOV | Register (word), Immediate (word) | |
10111111 | MOV | Register (word), Immediate (word) | |
11000000 | Shift group: see below | Memory (byte), Immediate (byte) | |
11000001 | Shift group: see below | Memory (word), Immediate (byte) | |
11000010 | RETN | Immediate (word) | |
11000011 | RETN | ||
11000100 | MOV | DS1 , Register (word), Memory (double word) |
|
11000101 | MOV | DS0 , Register (word), Memory (double word) |
|
11000110 | MOV | Memory (byte), Immediate (byte) | |
11000111 | MOV | Memory (word), Immediate (word) | |
11001000 | PREPARE | Immediate (word), Immediate (byte) | |
11001001 | DISPOSE | ||
11001010 | RETF | Immediate (word) | |
11001011 | RETF | ||
11001100 | BRK | 3 | |
11001101 | BRK | Immediate (byte) | |
11001110 | BRKV | ||
11001111 | RETI | ||
11010000 | Shift group: see below | Memory (byte), 1 |
|
11010001 | Shift group: see below | Memory (word), 1 |
|
11010010 | Shift group: see below | Memory (byte), CL |
|
11010011 | Shift group: see below | Memory (word), CL |
|
11010100 | CVTBD | Immediate (byte) | |
11010101 | CVTDB | Immediate (byte) | |
11010110 | SALC | ||
11010111 | TRANS | [BW] | |
11011000 | FPO1 | Memory | |
11011001 | FPO1 | Memory | |
11011010 | FPO1 | Memory | |
11011011 | FPO1 | Memory | |
11011100 | FPO1 | Memory | |
11011101 | FPO1 | Memory | |
11011110 | FPO1 | Memory | |
11011111 | FPO1 | Memory | |
11100000 | DBNZNE | Displacement (byte, sign-extended) | |
11100001 | DBNZE | Displacement (byte, sign-extended) | |
11100010 | DBNZ | Displacement (byte, sign-extended) | |
11100011 | BCWZ | Displacement (byte, sign-extended) | |
11100100 | IN | AL , Immediate (byte) |
|
11100101 | IN | AW , Immediate (byte) |
|
11100110 | OUT | Immediate (byte), AL |
|
11100111 | OUT | Immediate (byte), AW |
|
11101000 | CALL | Displacement (word) | |
11101001 | BR | Displacement (word) | |
11101010 | BR | Immediate (double word) | |
11101011 | BR | Displacement (byte, sign-extended) | |
11101100 | IN | AL , DW |
|
11101101 | IN | AW , DW |
|
11101110 | OUT | DW , AL |
|
11101111 | OUT | DW , AW |
|
11110000 | BUSLOCK | ||
11110001 | Invalid | ||
11110010 | REPNE, REPNZ | ||
11110011 | REP, REPE, REPZ | ||
11110100 | HALT | ||
11110101 | NOT1 | CY | |
11110110 | Group 1: see below | * (byte) |
|
11110111 | Group 1: see below | * (word) |
|
11111000 | CLR1 | CY | |
11111001 | SET1 | CY | |
11111010 | DI | ||
11111011 | EI | ||
11111100 | CLR1 | DIR | |
11111101 | SET1 | DIR | |
11111110 | Group 2: see below | * (byte) |
|
11111111 | Group 2: see below | * (word) |
[note 1] |
On other V Series CPUs, opcode 00001111 is the first byte of
a "group 3" set of instructions. None of the instructions in group 3 are
available on V30MZ, and this opcode is undefined.
|
[note 2] |
On other V Series CPUs, opcodes 01100100 and
01100101 are for REPNC and REPC
prefixes respectively that control repetition of
block instructions depending on the state of the
CY flag. On V30MZ, they are treated as regular undefined
opcodes and do not function as prefixes.
|
[note 3] |
On other V Series CPUs, opcodes 01100110 and
01100111 belong to an FPO2 instruction that
provides additional commands to a floating-point coprocessor. On V30MZ,
they are treated as regular undefined opcodes and do not have a memory
operand.
|
Instructions in the immediate group always have a memory operand. Bits 3-5 of the memory operand byte contain a sub-opcode that identifies the operation of an instruction in the immediate group. The operands for instructions in the immediate group are shown in the list above.
Sub-Opcode | Name | Mnemonic |
---|---|---|
000 | Add | ADD |
001 | Or | OR |
010 | Add with Carry | ADDC |
011 | Subtract with Carry | SUBC |
100 | And | AND |
101 | Subtract | SUB |
110 | Exclusive Or | XOR |
111 | Compare | CMP |
Instructions in the shift group always have a memory operand. Bits 3-5 of the memory operand byte contain a sub-opcode that identifies the operation of an instruction in the shift group. The operands for instructions in the shift group are shown in the list above.
Sub-Opcode | Name | Mnemonic |
---|---|---|
000 | Rotate Left | ROL |
001 | Rotate Right | ROR |
010 | Rotate Left with Carry | ROLC |
011 | Rotate Right with Carry | RORC |
100 | Shift Left | SHL |
101 | Shift Right | SHR |
110 | - | Invalid, has a side effect [note] |
111 | Shift Right Arithmetic | SHRA |
[note] |
Even though sub-opcode 110 is undefined and has no
intended operation, it still has a memory operand and produces a result
of zero, which is stored to either the memory offset or the register as
applicable.
|
Instructions in group 1 always have a memory operand. Bits 3-5 of the memory operand byte contain a sub-opcode that identifies the operation of an instruction in group 1. The operands for instructions in group 1 depend on the operation, given in the list below. The size of the operands depends on bit 0 of the opcode byte and is given in the list above.
Sub-Opcode | Name | Mnemonic | Operands |
---|---|---|---|
000 | Test | TEST | Memory (byte or word), Immediate (byte or word) |
001 | - | Invalid | Memory [note] |
010 | Not | NOT | Memory (byte or word) |
011 | Negate | NEG | Memory (byte or word) |
100 | Multiply Unsigned | MULU | Memory (byte or word) |
101 | Multiply Signed | MUL | Memory (byte or word) |
110 | Divide Unsigned | DIVU | Memory (byte or word) |
111 | Divide Signed | DIV | Memory (byte or word) |
[note] |
Even though sub-opcode 001 is undefined and has no
corresponding operation, it has a memory operand and any additional bytes
of instruction code required by it are present. If the memory operand
specifies an offset, no memory is actually accessed.
|
Instructions in group 2 always have a memory operand. Bits 3-5 of the memory operand byte contain a sub-opcode that identifies the operation of an instruction in group 2. The operands for instructions in group 2 depend on the operation, given in the list below. The size of the operands may depend on bit 0 of the opcode byte and, if so, is given in the list above.
Sub-Opcode | Name | Mnemonic | Operands |
---|---|---|---|
000 | Increment | INC | Memory (byte or word) |
001 | Decrement | DEC | Memory (byte or word) |
010 | Call | CALL | Memory (word) |
011 | Call | CALL | Memory (double word) |
100 | Branch | BR | Memory (word) |
101 | Branch | BR | Memory (double word) |
110 | Push | PUSH | Memory (word) |
111 | - | Invalid | Memory [note] |
[note] |
Even though sub-opcode 111 is undefined and has no
corresponding operation, it has a memory operand and any additional bytes
of instruction code required by it are present. If the memory operand
specifies an offset, no memory is actually accessed.
|
V30MZ is largely similar to the Intel 8086, but many registers and instructions underwent name changes. The lists below contain the corresponding names for each processor.
Registers
Byte | Word | Other | Flags | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
|
|
Instructions
|
|
|
|
|
Registers
Byte | Word | Other | Flags | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
|
|
Instructions
|
|
|
|
|
Instructions
V30MZ | 8086 | AT&T | |||
---|---|---|---|---|---|
CALL | 32-bit immediate | CALL | 32-bit immediate | LCALL | 32-bit immediate |
CVTBW | CBW | CBTW | |||
CVTWL | CWD | CWTD | |||
BR | 32-bit immediate | JMP | 32-bit immediate | LJMP | 32-bit immediate |
RETF | RETF | LRET |
Color models provide a DMA feature to quickly transfer data from the bus into WRAM. On the monochrome model, or a color model with color mode disabled, none of the DMA features are available: its I/O ports do nothing when written and are undefined when read.
DMA transfers are in word units and both the source and destination addresses are word-aligned. Transfers cannot read from cartridge SRAM as the source because its data interface is 8-bit, and the DMA controller explicitly prohibits attempting any transfers there.
The DMA feature is intended to be used by the program to perform memory transfers. The CPU is paused during a DMA operation and resumes after the DMA operation completes.
The memory source for DMA transfers is configured through the following I/O ports:
0x40 | Word | GDMA_SOURCE_L | General-purpose DMA source address (lower 16 bits) |
0x42 | Word | GDMA_SOURCE_H | General-purpose DMA source address (upper 4 bits) |
The lowest bit of GDMA_SOURCE_L
is read-only and is always
clear. Bits 4-15 of GDMA_SOURCE_H
have no significance and are
undefined when read.
GDMA_SOURCE_L
and GDMA_SOURCE_H
together form the
full 20-bit physical address used as the memory source for DMA transfers.
The memory destination for DMA transfers is always into
WRAM (0x00000
- 0x0FFFF
). The
16-bit destination address is configured through the following I/O port:
0x44 | Word | GDMA_DESTINATION | General-purpose DMA destination address |
The lowest bit of GDMA_DESTINATION
is read-only and is always
clear.
The size of the data to transfer with DMA is configured through the following I/O port:
0x46 | Word | GDMA_COUNTER | General-purpose DMA data transfer amount |
GDMA_COUNTER
specifies the total size of the transfer in bytes.
The lowest bit is read-only and is always clear.
The DMA transfer operation is configured through the following I/O port:
0x48 | Byte | GDMA_CTRL | General purpose DMA control |
7 | 6 | 5 | 0 | ||||
Enb |
Dir |
- | |||||
1 | 1 | 6 |
- | R | These bits have no significance and are undefined when read. |
Enb | W | When set, the DMA operation is initiated. When clear, no action is taken. Clear when read. |
Dir | R/W | When clear, the source and destination addresses are incremented after each transfer. When set, they are decremented after each transfer. |
GDMA_SOURCE_L
, GDMA_SOURCE_H
,
GDMA_DESTINATION
and GDMA_COUNTER
are all modified
during the DMA operation. The source and destination addresses are modified
by the counter amount in the direction specified by Dir
, and
GDMA_COUNTER
becomes zero.
Upon initiating the DMA operation, the CPU is suspended until it completes. The total number of CPU cycles taken by the DMA operation is given with the following formula:
TotalCycles = 5 + 2 * GDMA_COUNTER
If GDMA_COUNTER
is already zero or the source address is within
cartridge SRAM (0x10000
-
0x1FFFF
), no DMA operation is performed and the program resumes
immediately.
Editor's Note: Research is needed to determine the behavior when the source and/or destination addresses reach the end of the allowed range. Do they roll over and keep going?
Editor's Note: Research is needed to determine what happens if a DMA operation that began outside of SRAM reaches SRAM. Does it terminate prematurely?
WonderSwan contains an LCD panel for image output that is 224×144 pixels with a 13.25 ms (≈ 75.47 Hz) configurable refresh rate. The monochrome model can produce 16 activation levels, and color models can produce 12-bit RGB.
Contents
Display Control
Characters
Screens
Sprites
Palettes
Windows
Segments
Interrupts
Pixel patterns are 8×8 units called characters. Two layers of background maps called screens present tiled grids of characters that can be scrolled around within the viewport. Sprites are individual character objects that can be positioned at any arbitrary position in the image. A window feature can be used to mask a region of the image where sprites and one of the screens are able to be drawn.
A number of interrupts are available for monitoring LCD events. This includes counting lines of output and finishing the display of an entire image.
The display unit is always active and cannot be turned on or off. Individual graphical features can be enabled or disabled.
Top-level display features are configured through the following I/O port:
0x00 | Word | DISPLAY_CTRL | Display control |
Monochrome |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Color |
|
- | R | These bits have no function and are undefined when read. |
Border | R/W | The index into the monochrome color map of the backdrop color. |
Palette | R/W | The index of the color palette containing the backdrop color. Values 8 through 15 are sprite palettes 0 through 7 respectively. |
Color | R/W | The index of the color within the above palette of the backdrop color. |
S2WC | R/W |
While S2WE is set, draws screen 2
pixels only outside the window bounds when
clear or only inside the window bounds when set.
|
S2WE | R/W | When set, the screen 2 window is enabled. |
SPRWE | R/W | When set, the sprite window is enabled. |
SPR | R/W | When set sprites are enabled. |
SCR2 | R/W | When set, screen 2 is enabled. |
SCR1 | R/W | When set, screen 1 is enabled. |
If color mode is disabled, this port uses the "Monochrome" format. If color mode is enabled, this port uses the "Color" format.
The backdrop color is used when drawing the image if no graphics occupy a given pixel.
If color mode is not enabled, Border
specifies the index into the
color map of the gradation level to use as the backdrop color. If color mode
is enabled, Palette
is the index of the color palette containing
the backdrop color, and Color
is the index of the color within
that palette of the backdrop color. When running in 2bpp mode, the highest two
bits of Color
are ignored.
Additional LCD panel operations are configured through the following I/O port:
0x14 | Byte | LCD_IF_CTRL | LCD interface control |
7 | 2 | 1 | 0 | ||||
- | Cont |
Slp |
|||||
6 | 1 | 1 |
- | R | These bits have no significance and are undefined when read. |
Cont | R | Using low contrast when clear or high contrast when set. Undefined on monochrome and SwanCrystal. |
Slp | R/W | Put the LCD into sleep mode when clear or normal operation when set. |
Cont
is available on WonderSwan Color even while
color mode is disabled.
While in sleep mode, the LCD is disabled and will not display an image. On
the monochrome model and SwanCrystal, it will display white pixels. On
WonderSwan Color, it will display black pixels. Slp
has
significance regarding the corresponding Slp
field in
LCD_VOLUME. If either or both
ports specify a sleep state, the display will be blanked.
VBlank interrupts are still processed while in sleep mode.
Editor's Note: Research is needed to determine whether other video interrupts continue to function while in sleep mode.
Although the LCD unit has 144 rows of pixels, the video component processes 159 rows by default, with the extras not being visible in the display. The number of extra rows can be configured by the program, thereby affecting the refresh rate of the image.
The refresh rate can be configured through the following I/O ports:
0x16 | Byte | LCD_VTOTAL | LCD total line count |
0x17 | Byte | LCD_VSYNC | LCD back porch line count |
All 8 bits of both ports are read/write.
LCD_VTOTAL
specifies the total number of rows of pixels per
frame, minus 1. Its initial value at system reset
is 0x9E
, which corresponds to 159 lines.
LCD_VSYNC
specifies the number of lines in the image following
the "back porch" phase of the timing process. Its initial value at system
reset is 0x9B
, which corresponds to 155 lines.
In order to synchronize the image properly with the display, these ports
should be configured such that there are 4 "back porch" lines in the video
signal. When configured properly, the value in LCD_VSYNC
should
be 3 less than the value in LCD_VTOTAL
.
If the number of lines specfied by LCD_VTOTAL
is less than 144,
fewer lines will be processed each frame than there are physical rows of
pixels on the LCD unit. In this situation, only the top
LCD_VTOTAL
+ 1 lines are displayed, and all remaining lines are
white pixels. Since the frame never reaches the bottom of the image,
VBLANK interrupts are not requested
and the VBLANK_COUNTUP
timer never
updates.
LCD_VTOTAL
is 255, no image is displayed and the LCD unit
displays white pixels.
Every row of pixels takes ≈ 83.33 µs (= 12,000 Hz) to process. The initial number of 159 lines works out to 12,000 Hz / 159 ≈ 75.47 frames per second.
Caution: Supplying an odd value for LCD_VTOTAL
produces
anomlous behavior on SwanCrystal and may damage the LCD unit. The behavior
on the monochrome model is the same as when using even values. As a
precaution, only use even values for LCD_VTOTAL
.
Editor's Note: These ports are undocumented and are not intended for
developer use. The names LCD_VTOTAL
and LCD_VSYNC
are conjectural and have been produced by the WonderSwan community.
Editor's Note: Need to check if odd values are problematic on WonderSwan Color.
The fundamental graphical element on WonderSwan is the character, or "tile", which is an 8×8 pixel image with 2 or 4 bits per pixel. The monochrome model only supports 2bpp, while color models additionally support 4bpp. Characters are located at fixed addresses in WRAM:
0x02000 - 0x03FFF |
Characters |
0x04000 - 0x0BFFF [color]
|
Characters |
[color] | These addresses are only available in color mode. When accessed on the monochrome model or on a color model with color mode disabled, they function as open bus. |
Each 2bpp character occupies 16 bytes and each 4bpp character occupies 32 bytes.
The bit depth and color capability of characters is specified with the SYSTEM_CTRL2 I/O port. 4bpp character modes are only available while color mode is enabled. When color mode is disabled, there is memory for 512 characters. When color mode is enabled, there is memory for 1,024 characters of either bit depth.
The base address for 2bpp character memory is 0x02000
, and the
base address for 4bpp character memory is 0x04000
. The WRAM
organization for each color depth is as follows:
Address | 2bpp modes | 4bpp modes |
---|---|---|
0x02000 - 0x03FFF |
2bpp characters 0 - 511 | Scratch memory |
0x04000 - 0x05FFF |
2bpp characters 512 - 1,023 | 4bpp characters 0 - 255 |
0x06000 - 0x0BFFF |
Scratch memory | 4bpp characters 256 - 1,023 |
Characters may be encoded as planes, where each byte represents a single bit for each of the 8 pixels on a particular row within the character. The bits from multiple bytes are used to determine the value for any given pixel.
Regardless of bit depth, planar characters are encoded as rows of pixels from top to bottom. For each row of pixels, all of the bit planes appear as consecutive bytes in order from least significant to most significant: the first byte of the row contains the least significant bit for each pixel in that row, and the last byte of the row contains the most significant pixel bit. Within each byte, pixels are ordered with the highest bit on the left and the lowest bit on the right.
4bpp characters may be encoded linearly, where all of the bits for each pixel are located within the same byte.
Packed characters are encoded as rows of pixels from top to bottom. For each row of pixels, the four bytes represent adjacent pairs of pixels in order from left to right: the first byte of the row contains the left-most two pixels in the row, and the fourth byte contains the right-most two pixels. Within each byte, pixels are ordered with the high nibble on the left and the low nibble on the right.
WonderSwan features two scrollable background layers called screens. Each screen is a 32×32 character grid (256×256 pixels). Screen 1 is always the back-most element in the image, whereas screen 2 may appear in front of or behind various sprites. Screen 2 may interact with the window feature.
The DISPLAY_CTRL I/O port is used in part to configure screens:
0x00 | Word | DISPLAY_CTRL | Display control |
15 | 2 | 1 | 0 | ||||||||||||
- | SCR2 |
SCR1 |
|||||||||||||
14 | 1 | 1 |
- | These bits do not pertain to screens. | |
SCR2 | R/W | When set, screen 2 is enabled. |
SCR1 | R/W | When set, screen 1 is enabled. |
When both screens are enabled, screen 2 will appear in front of screen 1.
Memory for screens is located in WRAM. Screens have a 15-bit base address, with bits 0-10 being clear and bits 11-14 being configurable through the following I/O port:
0x07 | Byte | SCR_AREA | SCR character definition area specification |
7 | 4 | 3 | 0 | ||||
S2_VRAM | S1_VRAM | ||||||
4 | 4 |
S2_VRAM | R/W | Bits 11-14 of the base address for screen 2. |
S1_VRAM | R/W | Bits 11-14 of the base address for screen 1. |
When color mode is disabled, the highest bit of
each field is clear and read-only, yielding a maximum screen base address of
0x03800
. When color mode is enabled, all 4 bits are available,
yielding a maximum screen base address of 0x07800
.
Each screen occupies 0x800
bytes. It is comprised of 1,024
elements, arranged as a 32×32-element grid, left-to-right then
top-to-bottom.
Screen elements are 16 bits in the following format:
15 | 14 | 13 | 12 | 9 | 8 | 0 | |||||||||
Vm |
Hm |
Bank |
palette | character | |||||||||||
1 | 1 | 1 | 4 | 9 |
Vm | When set, the character is flipped vertically. |
Hm | When set, the character is flipped horizontally. |
Bank |
When color mode is enabled, serves as a bit 9
for character . Ignored otherwise.
|
palette | The index of the palette to use when drawing the character. |
character | The index of the character to draw. |
The default position of a screen places it such that the top-left pixel of the display is occupied by the top-left pixel of the first element in the screen. The position within the screen that corresponds to the top-left pixel of the display can be configured through the following I/O ports:
0x10 | Byte | SCR1_SCRL_X | SCR1 scroll (X axis) |
0x11 | Byte | SCR1_SCRL_Y | SCR1 scroll (Y axis) |
0x12 | Byte | SCR2_SCRL_X | SCR2 scroll (X axis) |
0x13 | Byte | SCR2_SCRL_Y | SCR2 scroll (Y axis) |
The format of all four ports is the same:
7 | 0 | ||||||
Scroll | |||||||
8 |
Scroll | R/W | Scrolling offset |
As Y
increases, the screen will appear to move "up" relative to
the display. As X
increases, the screen will appear to move
"left" relative to the display.
If the right or bottom edge of the screen is reached before the image has finished drawing, the screen will repeat by continuing at the left or top edge respectively.
Since a screen is exactly 256 pixels in both dimensions, the signedness of these ports is not relevant.
Individual characters can appear anywhere in the scene by using them as sprites, or "objects". Up to 128 sprites may be used at once.
The DISPLAY_CTRL I/O port is used in part to configure sprites:
0x00 | Word | DISPLAY_CTRL | Display control |
15 | 3 | 2 | 1 | 0 | |||||||||||
- | SPR |
- | |||||||||||||
13 | 1 | 2 |
- | These bits do not pertain to sprites. | |
SPR | R/W | When set, sprites are enabled. |
Memory for sprites is located in WRAM. Sprites have a 15-bit base address, with bits 0-8 being clear and bits 9-14 being configurable through the following I/O port:
0x04 | Byte | SPR_AREA | SPR character definition area specification |
7 | 6 | 5 | 0 | ||||
- | SPR_VRAM | ||||||
2 | 6 |
- | R | These bits have no significance and are undefined when read. |
SPR_VRAM | R/W | Bits 9-14 of the base address for sprites. |
When color mode is disabled, the highest bit of
SPR_VRAM
is clear and read-only, yielding a maximum sprite base
address of 0x03E00
. When color mode is enabled, all 6 bits are
available, yielding a maximum sprite base address of 0x07E00
.
The range of sprites to draw in the scene is configured through the following I/O ports:
0x05 | Byte | SPR_START_NO | SPR drawing first character number |
7 | 6 | 0 | |||||
- | start | ||||||
1 | 7 |
- | R | This bit has no significance and is undefined when read. |
start | R/W | Index of the first sprite to include |
0x06 | Byte | SPR_CNT | Number of SPR characters |
7 | 0 | ||||||
count | |||||||
8 |
count | R/W | Number of sprites to include. |
When the image is being drawn, sprites indexed start
through
start + count - 1
will be included in the image. If the range
specifies sprite indexes greater than 127, the next sprite after sprite 127
will be sprite 0 and the sequence will continue from there. Values greater
than 128 in count
have undefined behavior.
Sprite elements are 4 bytes in size, organized into 2 words with the following format:
0 |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
1 |
|
Vm | If set, the character graphic will be reversed vertically. |
Hm | If set, the character graphic will be reversed horizontally. |
Pr | When clear, the sprite appears behind screen 2. When set, it appears in front of screen 2. |
Ct | While the sprite window is enabled, draws sprite pixels only inside the window bounds when clear or only outside the window bounds when set. |
palette | Index of the sprite palette defining the sprite's colors. |
character | Index of the character to draw. |
x | The horizontal coordinate of the left edge of the sprite from the left edge of the image. |
y | The vertical coordinate of the top edge of the sprite from the top edge of the image. |
x
and y
are ostensibly unsigned, although values
248 through 255 will place the sprite to the left of/above the left/top edges
of the image as though the values were signed. They can be conceptualized as
the lowest 8 bits of a signed number in the range of -8 to +247.
When color mode is enabled, only the first 512 characters are available for use in sprites. These are the same 512 that can be used with color mode disabled.
When multiple sprites occupy the same pixel, only one will be visible in the output. For each applicable sprite for a given position in the output, in the order given by SPR_START_NO and SPR_CNT, the first sprite whose pixel is both opaque and not obscured by screen 2 will be used in the output.
Only the first 32 sprites positioned over a given row of pixels, in the order
given by SPR_START_NO
and SPR_CNT
, can be used in
the output. The 33rd and all subsequent sprites for that row of
pixels will be skipped. This remains the case regardless of whether or not
any of the first 32 sprites on the row are entirely off-screen or obscured by
screen 2.
A palette is a mapping between pixel values and colors. Palettes work differently depending on whether or not color mode is enabled. In monochrome mode, palettes are configured through I/O ports and the entire image consists of 8 shades of gray from a selection of 16 possible shades. In color mode, palettes are configured in memory and color elements are 12-bit RGB.
Regardless of whether color mode is enabled, there are 16 palettes total: 8 for screens and 8 for sprites, numbered 0 through 7 for each type. While operating in 2bpp modes, palettes 0 through 3 treat pixel value zero as opaque, while palettes 4 through 7 treat pixel value zero as transparent (invisible). While operating in 4bpp modes, all palettes treat pixel value zero as transparent.
A global backdrop color is used when drawing the image if no graphics occupy a given pixel. It is configured through the DISPLAY_CTRL I/O register:
0x00 | Word | DISPLAY_CTRL | Display control |
Monochrome |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Color |
|
- | These bits do not pertain to the backdrop color. | |
Border | R/W | The index into the monochrome color map of the backdrop color. |
Palette | R/W | The index of the color palette containing the backdrop color. |
Color | R/W | The index of the color within the above palette of the backdrop color. |
If color mode is not enabled, Border
specifies the index into the color map of the
gradation level to use as the backdrop color.
If color mode is enabled, Palette
is the index of the color
palette containing the backdrop color, and Color
is the index of
the color within that palette of the backdrop color. When running in 2bpp
mode, the highest two bits of Color
are ignored.
In monochrome mode, the display is capable of displaying 16 distinct shades of gray. However, only 8 of these shades can be used within a single image. The exact 8 shades to use are specified in the color map, which serves as a sort of master palette for the entire image.
The 8 values in the color map represent the specific gradation levels‐or shades of gray‐for each corresponding palette value. Gradation level 0 represents white (the LCD segment is fully "off") and gradation level 15 represents black (the LCD segment is fully "on"). The intensity of intermediate gradation levels transitions linearly from one extreme to the other.
The color map is configured through the following I/O ports:
0x1C | Byte | LCD_GRAY_01 | LCD LUT #0/#1 |
0x1D | Byte | LCD_GRAY_23 | LCD LUT #2/#3 |
0x1E | Byte | LCD_GRAY_45 | LCD LUT #4/#5 |
0x1F | Byte | LCD_GRAY_67 | LCD LUT #6/#7 |
The format of all four ports is the same:
7 | 4 | 3 | 0 | ||||
Color1 | Color0 | ||||||
4 | 4 |
Color1 | R/W | Gradation level for high-order color index. |
Color0 | R/W | Gradation level for low-order color index. |
Each port supplies the gradation levels for two palette values.
Color0
supplies the gradation level for the lesser palette value
and Color1
supplies the gradation level for the greater palette
value. For example, Color1
in LCD_GRAY_23
supplies
the gradation level for palette value 3.
There are 16 4-color palettes in monochrome mode. Each color value refers to one of the entries in the color map.
Palettes are configured through the following I/O ports:
0x20 | Word | SCR_LUT_0 | SCR character LUT #0 |
0x22 | Word | SCR_LUT_1 | SCR character LUT #1 |
0x24 | Word | SCR_LUT_2 | SCR character LUT #2 |
0x26 | Word | SCR_LUT_3 | SCR character LUT #3 |
0x28 | Word | SCR_LUT_4 | SCR character LUT #4 |
0x2A | Word | SCR_LUT_5 | SCR character LUT #5 |
0x2C | Word | SCR_LUT_6 | SCR character LUT #6 |
0x2E | Word | SCR_LUT_7 | SCR character LUT #7 |
0x30 | Word | SPR_LUT_0 | SPR character LUT #0 |
0x32 | Word | SPR_LUT_1 | SPR character LUT #1 |
0x34 | Word | SPR_LUT_2 | SPR character LUT #2 |
0x36 | Word | SPR_LUT_3 | SPR character LUT #3 |
0x38 | Word | SPR_LUT_4 | SPR character LUT #4 |
0x3A | Word | SPR_LUT_5 | SPR character LUT #5 |
0x3C | Word | SPR_LUT_6 | SPR character LUT #6 |
0x3E | Word | SPR_LUT_7 | SPR character LUT #7 |
The format of all sixteen ports is the same:
15 | 14 | 12 | 11 | 10 | 8 | 7 | 6 | 4 | 3 | 2 | 0 | ||||
- | c3 | - | c2 | - | c1 | - | c0 | ||||||||
1 | 3 | 1 | 3 | 1 | 3 | 1 | 3 |
- | R | These bits have no function and are undefined when read. |
c3 | R/W | The value for color 3 |
c2 | R/W | The value for color 2 |
c1 | R/W | The value for color 1 |
c0 | R/W | The value for color 0 |
When color mode is enabled, palettes are configured in WRAM. There are 16 16-color palettes defined with RGB triplets.
Palette memory is located in WRAM at the following addresses:
0x0FE00 - 0x0FE1F |
Screen color palette 0 |
0x0FE20 - 0x0FE3F |
Screen color palette 1 |
0x0FE40 - 0x0FE5F |
Screen color palette 2 |
0x0FE60 - 0x0FE7F |
Screen color palette 3 |
0x0FE80 - 0x0FE9F |
Screen color palette 4 |
0x0FEA0 - 0x0FEBF |
Screen color palette 5 |
0x0FEC0 - 0x0FEDF |
Screen color palette 6 |
0x0FEE0 - 0x0FEFF |
Screen color palette 7 |
0x0FF00 - 0x0FF1F |
Sprite color palette 0 |
0x0FF20 - 0x0FF3F |
Sprite color palette 1 |
0x0FF40 - 0x0FF5F |
Sprite color palette 2 |
0x0FF60 - 0x0FF7F |
Sprite color palette 3 |
0x0FF80 - 0x0FF9F |
Sprite color palette 4 |
0x0FFA0 - 0x0FFBF |
Sprite color palette 5 |
0x0FFC0 - 0x0FFDF |
Sprite color palette 6 |
0x0FFE0 - 0x0FFFF |
Sprite color palette 7 |
Each of the 16 palettes defines 16 color entries at 2 bytes per entry for a total of 32 bytes per palette. Each color entry is a word with the following format:
15 | 12 | 11 | 8 | 7 | 4 | 3 | 0 | ||||||||
- | R | G | B | ||||||||||||
4 | 4 | 4 | 4 |
- | These bits are not used by palettes. |
R | The color's red intensity. |
G | The color's green intensity. |
B | The color's blue intensity. |
Palette colors are RGB triplets with 4 bits per channel. The color
0x000
is black and the color 0xFFF
is white.
In 2bpp mode, only color entries 0 through 3 are used from each palette, with the remaining 12 entries being unused.
Windows can be used to configure clipping regions within the image that can apply to screen 2 and sprites. The region is a rectangle that can be positioned arbitrarily, and can either mask the corresponding pixels from appearing inside the rectangle, or only allow them to appear inside the rectangle.
The DISPLAY_CTRL I/O port is used in part to configure windows:
0x00 | Word | DISPLAY_CTRL | Diplay control |
15 | 6 | 5 | 4 | 3 | 2 | 0 | |||||||||
- | S2WE |
S2WC |
SPRWE |
- | |||||||||||
10 | 1 | 1 | 1 | 3 |
- | These bits do not pertain to windows. | |
S2WE | R/W | When set, the screen 2 window is enabled. |
S2WC | R/W |
While S2WE is set, draws screen 2 pixels only inside the
window bounds when clear or only outside the window bounds when set.
|
SPRWE | R/W | When set, the sprite window is enabled. |
The window clipping behavior for sprites is configured for each sprite individually. For more information, see Sprites § Memory.
Windows are positioned through the following I/O ports:
0x08 | Byte | SCR2_WIN_X1 | SCR2 Window upper left (X axis) |
0x09 | Byte | SCR2_WIN_Y1 | SCR2 Window upper left (Y axis) |
0x0A | Byte | SCR2_WIN_X2 | SCR2 lower right of window (X axis) |
0x0B | Byte | SCR2_WIN_Y2 | SCR2 lower right of window (Y axis) |
0x0C | Byte | SPR_WIN_X1 | SPR window upper left (X axis) |
0x0D | Byte | SPR_WIN_Y1 | SPR window upper left (Y axis) |
0x0E | Byte | SPR_WIN_X2 | SPR window bottom right (X axis) |
0x0F | Byte | SPR_WIN_Y2 | SPR window bottom right (Y axis) |
The "SCR2_
" ports apply to the screen 2 window and the
"SPR_
" ports apply to the sprite window.
All eight of these ports are 8-bit unsigned numbers. For each window, the corresponding ports have the following significance:
X1 | Index of the left-most column of pixels of the window from the left edge of the image. |
X2 | Index of the right-most column of pixels of the window from the left edge of the image. |
Y1 | Index of the top-most row of pixels of the window from the top edge of the image. |
Y2 | Index of the bottom-most row of pixels of the window from the top edge of the image. |
X2
and Y2
specify the last column and row of pixels
to include in the window, respectively. Consequently, the width of the window
in pixels is X2 - X1 + 1
and the height is
Y2 - Y1 + 1
.
For each window, if X2
is less than X1
or
Y2
is less than Y1
, then the entire image is
considered to be outside of the window's bounds.
Ancillary to the main pixels of the LCD display, additional segments are available along one of the edges for use as status indicators. The program can turn these on and off as needed.
Segments are configured through the following I/O port:
0x15 | Byte | LCD_SEG_DATA | Segment display data |
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
- | A3 |
A2 |
A1 |
Hr |
Vt |
Sl |
|
2 | 1 | 1 | 1 | 1 | 1 | 1 |
- | R | These bits have no significance and are undefined when read. |
A3 | R/W | Aux 3, large circle. |
A2 | R/W | Aux 2, medium circle. |
A1 | R/W | Aux 1, small circle. |
Hr | R/W | Horizontal orientation. |
Vt | R/W | Vertical orientation. |
Sl | R/W | Sleep, shooting star. |
When the bit for a segment is set, that segment will be turned on. When the bit is clear, the segment will be turned off.
Additional information regarding segments is available through the following I/O port:
0x1A | Byte | LCD_VOLUME | LCD volume status |
7 | 4 | 3 | 2 | 1 | 0 | ||
- | On |
Vol | - | Slp |
|||
3 | 1 | 2 | 1 | 1 |
- | R | These bits have no significance and are clear when read. |
On | R | Set when the LCD volume icon is being displayed, or cleared otherwise. |
Vol | R | Indicates the current state of the LCD volume icon. |
Slp | R/W | Put the LCD into sleep mode when set or normal operation when clear. |
The individual bits in Vol
are used to enable or disable the
literal LCD segments. Has the following significance:
0 | Sound disabled |
1 | Medium volume (color models only) |
2 | Low volume |
3 | High volume |
While in sleep mode, the LCD is disabled and will not display an image. On
the monochrome model and SwanCrystal, it will display white pixels. On
WonderSwan Color, it will display black pixels. Slp
has
significance regarding the corresponding Slp
field in
LCD_IF_CTRL. If either or both
ports specify a sleep state, the display will be blanked.
VBlank interrupts are still processed while in sleep mode.
Editor's Note: This port is undocumented and is not intended for developer
use. The name LCD_VOLUME
is conjectural and has been produced by
the WonderSwan community.
The video unit supports four different interrupts that the program can use during image processing. For information regarding software setup, see Managing Interrupts.
Requests an interrupt when a specific row of pixels is being displayed. This interrupt has the relative vector index +4 and is configured through the following I/O ports:
0x02 | Byte | LCD_LINE | Drawing line position |
0x03 | Byte | LCD_INTERRUPT | Drawing line interrupt |
Both ports are 8-bit, unsigned numbers. Each represents a specific row of
pixels, with zero being the top row and increasing values moving down the
image. LCD_LINE
is read-only and returns the index of the row of
pixels currently being displayed. LCD_INTERRUPT
is read/write
and is used to specify the index of the row of pixels to use with the
interrupt.
When LCD_LINE
is updated by the video unit and the value matches
LCD_INTERRUPT
, the interrupt will be requested.
Requests an interrupt every time a full frame is displayed. This interrupt has the relative vector index +6 and is always active: it needs not be configured.
This interrupt is requested at the end of pixel row 143, when incrementing LCD_LINE. The number of rows of pixels to display is configured through LCD_VTOTAL: if fewer than 144 rows are specified, this interrupt will never be requested.
HBLANK_COUNTUP
and
VBLANK_COUNTUP
HBLANK_COUNTUP
requests an interrupt after a configurable number
of rows of pixels are displayed and has the relative vector index +7.
VBLANK_COUNTUP
requests an interrupt after a configurable number
of full frames are displayed and has the relative vector index +5.
These interrupts are collectively known as the timers. Each one has a counter value that is decremented each time the corresponding video action (H-blank or V-blank) occurs. When the counter reaches zero, the interrupt is requested. The counter can then optionally reset to a configurable value.
Timer functionality is configured through the following I/O port:
0xA2 | Word | TIMER_CTRL | Timer control |
15 | 4 | 3 | 2 | 1 | 0 | ||||||||||
- | VAuto |
VEnb |
HAuto |
HEnb |
|||||||||||
12 | 1 | 1 | 1 | 1 |
- | R | These bits have no significance and are undefined when read. |
VAuto | R/W | When set, the V-blank counter is reloaded once it reaches zero. |
VEnb | R/W | When set, the V-blank counter is enabled. |
HAuto | R/W | When set, the H-blank counter is reloaded once it reaches zero. |
HEnb | R/W | When set, the H-blank counter is enabled. |
The timer counters are configured through the following I/O ports:
0xA4 | Word | H_BLANK_TIMER | H-Blank timer reload |
0xA6 | Word | V_BLANK_TIMER | V-Blank timer reload |
0xA8 | Word | H_BLANK_COUNTER | H-Blank timer count |
0xAA | Word | V_BLANK_COUNTER | V-Blank timer count |
All four counter ports are 16-bit, unsigned numbers. The
"H_BLANK_
" ports pertain to HBLANK_COUNTUP
and the
"V_BLANK_
" ports pertain to VBLANK_COUNTUP
. Each
represents the number of blanking periods (and therefore counter updates)
until the interrupt fires. The "_TIMER
" ports are read/write and
supply the reload value when HAuto
and/or VAuto
is
set. The "_COUNTER
" ports are read-only and return the current
counter values.
Writing to a "_TIMER
" port will immediately initialize the
corresponding "_COUNTER
" port to the same value. If the reload
value is zero, the interrupt will never occur because it specifically watches
for the value to be decremented from 1 to 0.
If a timer is configured to repeat through HAuto
or
VAuto
as appropriate, the current counter value will reset to
the reload value once the counter reaches zero. In this situation, the
counter will never actually return the value zero when read.
H-blank occurs after processing all 224 visible pixels for each row in the display. It continues to occur for non-visible rows that are processed during the vertical blanking interval as specified by LCD_VTOTAL.
V-blank occurs after processing all 144 visible rows of pixels. The counter is decremented at the end of pixel row 143, when incrementing LCD_LINE. The number of rows of pixels to display is configured through LCD_VTOTAL: if fewer than 144 rows are specified, the counter will never decrement.
While enabled, H-blank counts always occur every ≈ 83.33 µs (=
12,000 Hz). When used with the value 1 in H_BLANK_TIMER
, this
interrupt is useful as a PCM audio timer. For more information, see
Voice.
Editor's Note: WonderWitch refers to a non-repeating timer as "one-shot" and a repeating timer as "auto preset".
Editor's Note: Research is needed to determine how long H-blank lasts. It might process 256 pixels' worth of time in order to give the program a moment to implement a raster effect.
Overview
Overview
Output Procedure
Features
PCM Waveforms
Output
Sound DMA
Channels
Stereo Levels
Frequency
Voice
Sweep
Noise
Hyper Voice
WonderSwan's sound unit has 4 channels, all of which can produce tones by sampling from PCM waveform memory and three of which have additional operating modes. Color models also support a sound DMA feature and an additional streaming PCM channel called Hyper Voice.
Channels are named 1 through 4 and have the following features:
• |
Channels 1-4
|
||||||
• |
Channel 2
|
||||||
• |
Channel 3
|
||||||
• |
Channel 4
|
||||||
• |
(Color mode only) Hyper Voice
|
Peripherals include a built-in monaural speaker, a volume button and a separate 3.5 mm headphone adapter that connects through the external port on the console. Audio output from the mixer is 24,000 Hz, 8-bit digital mono for the internal speaker and 16-bit digital stereo for the headphone adapter.
An input sample is produced for each of the audio channels. Wave samples come directly from wave memory, and noise samples are generated according to the noise generation algorithm. If a channel is not active, 0 is used for its input sample. This section refers to the left and right channel output streams in singular, but the algorithm applies to each stream independently.
For each active channel:
♦ |
If the channel is neither channel 2 in voice
mode nor Hyper Voice
|
||
◊ |
Otherwise, if the channel is channel 2 in voice mode
|
||
◊ |
Otherwise, if the channel is Hyper Voice and the destination is a
headphone adapter
|
||
◊ |
Otherwise, if the channel is Hyper Voice and the destination is the
internal speaker
|
The outputs for all channels are then added together to produce the preliminary combined output sample.
If the destination is the internal speaker, the left and right preliminary combined outputs are added together. The resulting 11-bit value is then shifted right by the number of bits specified in SND_OUT_CTRL and the lowest 8 bits are used as the final output value.
If the destination is a connected headphone adapater, the left and right preliminary combined outputs are taken directly. The signed 16-bit values are shifted left 5 bits and the lowest 16 bits are used as the final output values.
Regardless of destination, output is sampled at 24,000 Hz. Upon receiving the output from the WonderSwan, the headphone adapter will use linear interpolation to double the sampling rate to 48,000 Hz prior to converting to analog.
Editor's Note: Research is needed to verify masking with large outputs from Hyper Voice used in conjunction with the other channels.
When converting to analog, the VSU implements an RC circuit to block the DC bias, effectively producing a first-order high-pass filter with a very low cutoff frequency. This prevents the output voltage from being exclusively non-negative without affecting the audible significance of the stream.
The RC circuit is implemented with a 10 kΩ resistor and a 1 µF capacitor, resulting in a cutoff frequency of 1 / (2π × 10000 × 0.000001) ≈ 15.915 Hz. It can be discretized with an arbitrary sampling rate using the following formulas:
RC | = | 10000 × 0.000001 = 0.01 |
α | = | RC / (RC + 1 / SamplingRateHz) |
Then, for each sample:
Output[n] = α × ( Output[n - 1] + Input[n] - Input[n - 1] )
SamplingRateHz is 24,000 for the internal speaker and 48,000 for the headphone adapter.
Editor's Note: The RC circuit components shown above are known to be present in the headphone adapter. Research is needed to determine the sepcifics of the DAC process used for the internal speaker.
Wave generation is performed by reading samples from PCM wave memory. Sound channels 1-4 are capable of producing tones as waves. PCM wave memory is located in WRAM at the address specified by the following I/O port:
0x8F | Byte | SND_WAVERAM | Sound waveform definition area specification |
7 | 0 | ||||||
wave_p | |||||||
8 |
wave_p | R/W | Memory address of PCM wave samples, shifted right 6 bits. |
To determine the address in WRAM of the PCM wave samples, shift the value of
wave_p
left 6 bits.
PCM wave memory is 64 bytes, organized as 4 consecutive groups of 16 bytes. Each group applies to one of the sound channels 1 through 4, with the first group applying to channel 1 and so-forth.
Each group of 16 bytes defines 32 PCM samples. All 32 samples taken together represent one period of a tone's waveform. Samples are 4 bits in size and unsigned. Two samples are packed into each byte, with the low bits of the byte specifying the value of the earlier sample and the high bits specifying the later sample.
Sound generation is controlled through the following I/O port:
0x90 | Byte | SND_CH_CTRL | Sound channel control |
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
N | S | V | - | Enb4 |
Enb3 |
Enb2 |
Enb1 |
1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
- | R | This bit has no significance and is undefined when read. |
N | R/W | When set, channel 4 operates in noise mode. When clear, channel 4 operates in wave mode. |
S | R/W | When set, the sweep function is enabled for channel 3. |
V | R/W | When set, channel 2 operates in voice mode. When clear, channel 2 operates in wave mode. |
Enb4 | R/W | When set, channel 4 is enabled and will produce sound. When clear, channel 4 is silent. |
Enb3 | R/W | When set, channel 3 is enabled and will produce sound. When clear, channel 3 is silent. |
Enb2 | R/W | When set, channel 2 is enabled and will produce sound. When clear, channel 2 is silent. |
Enb1 | R/W | When set, channel 1 is enabled and will produce sound. When clear, channel 1 is silent. |
If V
is set (channel 2 is operating in voice mode), channel 2
will always prodouce output even if Enb2
is clear.
While a channel is enabled, all timing states associated with it are updated according to its configuration. This includes the PCM waveform sampling position, the sweep feature and the pseudorandom number generator. While a channel is disabled, none of its timing states are updated.
Even when channel 2 is operating in voice mode or channel 4 is operating in noise mode, their PCM waveform sampling positions continue to be updated according to their frequency settings.
There is no way to specify or reset a channel's PCM waveform sampling position. It will only be updated by the sound subsystem while the channel is active.
Hardware output is configured through the following I/O port:
0x91 | Byte | SND_OUT_CTRL | Sound output control |
7 | 6 | 4 | 3 | 2 | 1 | 0 | |
ConH |
- | EnbH |
RngS | EnbS |
|||
1 | 3 | 1 | 2 | 1 |
- | R | These bits have no significance and are undefined when read. |
ConH | R | Set when a headphone cable is connected, or clear otherwise. |
EnbH | R/W | When set, output is sent to the headphone adapter. |
RngS | R/W | Specifies the range of bits to use for internal speaker output (see below). |
EnbS | R/W | When set, output is sent to the internal speaker. |
ConH
indicates that a headphone adapter is present and a 3.5 mm
audio cable is plugged into it. If connected, audio is only delivered to the
headphone adapter; if disconnected, audio is only delivered to the internal
speaker.
The internal speaker processes 8-bit output, but the digital mixer produces
11-bit samples after mixing all 4 channels. RngS
specifies which
8 of these 11 bits to use as the output: the 11-bit sample is shifted right
by the number of bits given by RngS
, and the lowest 8 bits of
the result are used as the output. See also:
Output Procedure.
The mixer's output data (not including Hyper Voice) is available through the following I/O registers:
0x96 | Word | SND_OUT_R | Right channel sound output |
0x98 | Word | SND_OUT_L | Left channel sound output |
0x9A | Word | SND_OUT_M | Internal speaker sound output |
All three ports are read-only.
SND_OUT_R
and SND_OUT_L
are the final 10-bit mixer
values for the right and left headphone outputs respectively. The highest 6
bits of both ports are always clear.
SND_OUT_M
is the final 11-bit mixer value for the internal
speaker output. The highest 5 bits of this port are always clear.
Editor's Note: These ports are undocumented and are not intended for
developer use. The names SND_OUT_R
, SND_OUT_L
and
SND_OUT_M
are conjectural and have been produced by the
WonderSwan community.
Editor's Note: Research is needed to determine whether these ports are present on the monochrome model.
Color models provide a DMA feature for streaming PCM output automatically. On the monochrome model, or a color model with color mode disabled, none of the sound DMA features are available: its I/O ports do nothing when written and are undefined when read.
Sound DMA transfers are in byte units.
The memory source for sound DMA transfers is configured through the following I/O ports:
0x4A | Word | SDMA_SOURCE_L | Sound DMA source address (lower 16 bits) |
0x4C | Word | SDMA_SOURCE_H | Sound DMA source address (upper 4 bits) |
Bits 4-15 of SDMA_SOURCE_H
have no significance and are
undefined when read.
SDMA_SOURCE_L
and SDMA_SOURCE_H
together form the
full 20-bit physical address used as the
memory source for DMA transfers. Each time a byte is transferred, it is read
from the memory pointed to by these ports, then the pointer in these ports is
updated in preparation of the next transfer.
The size of the data to transfer with sound DMA transfers is configured through the following I/O ports:
0x4E | Word | SDMA_COUNTER_L | Sound DMA data transfer amount (lower 16 bits) |
0x50 | Word | SDMA_COUNTER_H | Sound DMA data transfer amount (upper 4 bits) |
Bits 4-15 of SDMA_COUNTER_H
have no significance and are
undefined when read.
SDMA_COUNTER_L
and SDMA_COUNTER_H
together form the
number of bytes remaining to be transferred using DMA transfers. Each time a
byte is transferred, the counter in these ports is decremented in preparation
of the next transfer. When the value reaches zero, the DMA operation
completes.
The DMA transfer operation is configured through the following I/O port:
0x52 | Byte | SDMA_CTRL | Sound DMA control |
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Enb |
Dir |
- | Dest |
Rep |
? | Rate | |
1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
- | R | This bit has no significance and is undefined when read. |
Enb | R/W | When set, transfers are enabled. When clear, transfers are disabled. |
Dir | R/W | When clear, the source address is incremented after each transfer. When set, the source address is decremented after each transfer. |
Dest | R/W | When clear, the transfer destination is SND_VOL_2. When set, the transfer destination is Hyper Voice. |
Rep | R/W | When set, the transfer operation will repeat (see below). |
? | R/W | The significance of this bit is not known. When set, the DMA feature doesn't appear to function. |
Rate | R/W | The amount of time between transfers (see below). |
When Rep
is set, the current values in
SDMA_SOURCE_L
, SDMA_SOURCE_H
,
SDMA_COUNTER_L
and SDMA_COUNTER_H
are remembered in
the DMA controller. Once the counter reaches zero while Rep
is
set, all four ports are replaced with the previously remembered values,
thereby repeating the operation from the beginning.
Rate
determines the interval between DMA transfers:
0 | 4,000 Hz | = | 250.00 µs |
1 | 6,000 Hz | ≈ | 166.67 µs |
2 | 12,000 Hz | ≈ | 83.33 µs |
3 | 24,000 Hz | ≈ | 41.67 µs |
If color mode is disabled while sound DMA is active, sound DMA will be paused until color mode is re-enabled. Once color mode is active again, sound DMA will continue to operate where it left off.
Sound channels 1 through 4 have volume settings for each of the left and right stereo outputs. Stereo levels are configured through the following I/O ports:
0x88 | Byte | SND_VOL_1 | Sound channel 1 volume |
0x89 | Byte | SND_VOL_2 | Sound channel 2 volume |
0x8A | Byte | SND_VOL_3 | Sound channel 3 volume |
0x8B | Byte | SND_VOL_4 | Sound channel 4 volume |
7 | 4 | 3 | 0 | ||||
Left | Right | ||||||
4 | 4 |
Left | R/W | Left stereo level. |
Right | R/W | Right stereo level. |
Each field controls the output level of the corresponding stereo stream. The level scales linearly with 0 being silence and 15 being maximum amplitude.
Because the built-in speaker is monaural, the stereo levels ports are primarily intended for use with a headphone adapter.
A channel's frequency specifies the interval at which it produces new PCM waveform or pseudorandom noise samples. Frequencies are configured through the following I/O ports:
0x80 | Word | SND_FREQ_1 | Sound channel 1 frequency |
0x82 | Word | SND_FREQ_2 | Sound channel 2 frequency |
0x84 | Word | SND_FREQ_3 | Sound channel 3 frequency |
0x86 | Word | SND_FREQ_4 | Sound channel 4 frequency |
15 | 11 | 10 | 0 | ||||||||||||
- | freq | ||||||||||||||
5 | 11 |
- | R | These bits have no significance and are clear when read. |
freq | R/W | The unsigned frequency divider setting. |
The sound unit is clocked at 3.072 MHz. freq
subtracted from
2,048 gives the number of clocks per sample within a sound channel's PCM wave
memory or between pseudorandom noise samples. For this reason, higher values
for freq
correspond to higher-pitched audible frequencies. In
effect, freq
divides the main clock rate through the following
formula:
SampleRateHz = 3072000 Hz / (2048 - freq)
Because there are 32 PCM samples in one period of a waveform, the effective audible tone of a wave channel is given with the following formulas:
ToneHz = SampleRateHz / 32
ToneHz = 96000 Hz / (2048 - freq)
Sound channel 2 is capable of outputting 8-bit raw PCM samples. This involves a mode of operation distinct from the one that processes PCM waveform memory. Channel 2's mode of operation is configured through the SND_CH_CTRL I/O port:
0x90 | Byte | SND_CH_CTRL | Sound channel control |
7 | 6 | 5 | 4 | 0 | |||
- | V | - | |||||
2 | 1 | 5 |
- | R/W | These bits do not pertain to voice mode. |
V | R/W | When set, channel 2 operates in voice mode. When clear, channel 2 operates in wave mode. |
While voice mode is enabled, the SND_VOL_2 I/O port has a different format:
0x89 | Byte | SND_VOL_2 | Sound channel 2 volume |
7 | 0 | ||||||
Sample | |||||||
8 |
Sample | R/W | The raw PCM output sample. Unsigned. |
While voice mode is enabled, channel 2's volume is controlled through the following I/O port:
0x94 | Byte | SND_VOL_CH2 | Sound channel 2 voice volume |
7 | 4 | 3 | 2 | 1 | 0 | ||
- | LH |
LF |
RH |
RF |
|||
4 | 1 | 1 | 1 | 1 |
- | R | These bits have no significance and are undefined when read. |
LH | R/W |
Left channel half volume when set. Has no effect when LF is
set.
|
LF | R/W | Left channel full volume when set. |
RH | R/W |
Right channel half volume when set. Has no effect when RF is
set.
|
RF | R/W | Right channel full volume when set. |
Half volume takes the sample value in SND_VOL_2
and shifts it
right 1 bit. If neither the "half" nor "full" bit is set for a stereo level,
the output for that level will be silent.
When output is being sent to the internal speaker, the left and right voice
samples are added together. This may produce a sample value in excess of 8
bits, which can be corrected for by using the half-volume settings
LH
and RH
.
On the monochrome model, voice mode is intended to be used in conjunction
with the HBLANK_COUNTUP
interrupt. On color models, it may also be used with
sound DMA.
Sound channel 3 is capable of modifying its frequency automatically. Channel 3's sweep feature is configured through the SND_CH_CTRL I/O port:
0x90 | Byte | SND_CH_CTRL | Sound channel control |
7 | 6 | 5 | 0 | ||||
- | S | - | |||||
1 | 1 | 6 |
- | R/W | These bits do not pertain to the sweep feature. |
S | R/W | When set, the sweep function is enabled for channel 3. |
While the sweep feature is enabled, channel 3's frequency setting is updated automatically over time. Modifications are defined with the amount by which to change the frequency setting and the time between updates. These are configured through the following I/O ports:
0x8C | Byte | SND_SWEEP | Sound channel 3 sweep amount |
7 | 0 | ||||||
sweep | |||||||
8 |
sweep | R/W | The signed amount to add to the frequency setting. |
Each time a frequency modification occurs, the signed value in
sweep
is added to
SND_FREQ_3. When the frequency
setting reaches the minimum of zero or the maximum of 2,047, the next
modification will cause the setting to "wrap around" and continue counting
from the other extreme. Reading from SND_FREQ_3
yields the
current effective frequency setting after modification.
0x8D | Byte | SND_SWEEP_TIME | Sound channel 3 sweep step time |
7 | 5 | 4 | 0 | ||||
- | steptime | ||||||
3 | 5 |
- | R | These bits have no significance and are undefined when read. |
steptime | R/W | The amount of time between frequency modifications, in units of ≈ 2.67 ms, minus 1. Unsigned. |
The sweep feature is clocked at 375 Hz. steptime
plus 1 gives
the number of clocks per frequency modification.
Sound channel 4 is capable of outputting pseudorandom noise. This involves a mode of operation distinct from the one that processes PCM waveform memory. Channel 4's mode of operation is configured through the SND_CH_CTRL I/O port:
0x90 | Byte | SND_CH_CTRL | Sound channel control |
7 | 6 | 0 | |||||
N | - | ||||||
1 | 7 |
- | R/W | These bits do not pertain to noise mode. |
N | R/W | When set, channel 4 operates in noise mode. When clear, channel 4 operates in wave mode. |
While noise mode is enabled, channel 4's samples are produced using a pseudorandom noise generator instead of being read from PCM waveform memory. The noise generator is a 15-bit linear feedback shift register with a configurable tap location. Output is binary: noise is only either high or low. The noise generator is configured through the following I/O port:
0x8E | Byte | SND_NOISE_CTRL | Sound channel 4 noise control |
7 | 5 | 4 | 3 | 2 | 0 | ||
- | Enable |
Reset |
Tap | ||||
3 | 1 | 1 | 3 |
- | R | These bits have no significance and are undefined when read. |
Enable | R/W | When set, the pseudorandom function is enabled. When clear, it is disabled. |
Reset | W | When set, the shift register is cleared to all zeroes. Clear when read. |
Tap | R/W | Specifies the bit to use in noise generation (see below). |
While both channel 4 and the noise feature are enabled, the noise feature
will be active and will update the shift register at the
frequency specified by
SND_FREQ_4
, even if channel 4 is in wave mode.
Tap
specifies the bit within the shift register to use as the
feedback source in noise generation. Different bits will produce pseudorandom
bit sequences of different lengths before the sequences repeat:
0 | Bit 14 | Sequence length of 32,767 |
1 | Bit 10 | Sequence length of 1,953 |
2 | Bit 13 | Sequence length of 254 |
3 | Bit 4 | Sequence length of 217 |
4 | Bit 8 | Sequence length of 73 |
5 | Bit 6 | Sequence length of 63 |
6 | Bit 9 | Sequence length of 42 |
7 | Bit 11 | Sequence length of 28 |
Bit positions listed above are zero-based. That is, bit 0 is the bit at
position 0x0001
and bit 14 is the bit at position
0x4000
.
The current value in the sift register can be retrieved through the following I/O port:
0x92 | Word | SND_RANDOM | Pseudo-random number |
15 | 14 | 0 | |||||||||||||
0 | Random | ||||||||||||||
1 | 15 |
0 | R | This bit is always zero. |
Random | R | The current value of the pseudorandom shift register. |
If the sound noise is to be used as a source of randomness but channel 4 is not needed for producing audio, it can be silenced by setting its stereo levels to zero in SND_VOL_4.
Noise generation begins by initializing the 15-bit shift register to all
zeroes. This happens when setting Reset
in
SND_NOISE_CONTROL.
For each pseudorandom sample, the following algorithm takes place:
▪ |
From the shift register, bit 7 (0x0080 ) is XORed with the bit
at Tap and the result inverted to produce a pseudorandom bit.
|
▪ | The value in the register is shifted left one bit. |
▪ | The pseudorandom bit is used as the new bit 0 of the shift register. |
▪ | The pseudorandom bit is scaled to 15 to produce the output sample. |
Color models provide a fifth, 16-bit sound channel to stream PCM output to a headphone adapter. On the monochrome model, or a color model with color mode disabled, Hyper Voice is not available: its I/O ports do nothing when written and are undefined when read.
If no headphone cable is connected (and output is being directed to the internal speaker), Hyper Voice will not produce any audio: it is exclusively available for use with headphones.
Hyper Voice is intended to be used via sound DMA. As such, it accepts sample inputs as 8-bit units, which are converted to 16-bit through a configurable function.
Hyper Voice is configured through the following I/O port:
0x6A | Word | HYPERV_CTRL | Hyper Voice Control |
15 | 14 | 13 | 12 | 11 | 8 | 7 | 6 | 4 | 3 | 2 | 1 | 0 | |||
- | Mode | Pty |
- | Enb |
Rate | Fmt | Shift | ||||||||
1 | 2 | 1 | 4 | 1 | 3 | 2 | 2 |
- | R | These bits have no significance and are undefined when read. |
Mode | R/W | Specifies the output mode (see below). |
Pty | W | When set, the output is reset to the left channel (see below). Undefined when read. |
Enb | R/W | When set, the channel is enabled. When clear, it is disabled. |
Rate | R/W | The internal sampling rate (see below). |
Fmt | R/W | Specifies how to convert 8-bit sample inputs to 16-bit (see below). |
Shift | R/W | Number of bits to shift during 8-bit to 16-bit sample conversion (see below). |
Mode
specifies the Hyper Voice output mode:
0 | Stereo |
1 | Mono, left only |
2 | Mono, right only |
3 | Mono, both sides |
When Mode
is 0 (stereo) and an 8-bit sample is delivered to
Hyper Voice, the stereo channel it is assigned to alternates between left and
right. When Pty
is set, Hyper Voice is explicitly reset to
receive the next 8-bit sample into the left channel.
Rate
determines how often the Hyper Voice channel output
updates using its most recent input:
0 | 24,000 Hz | ≈ | 41.67 µs |
1 | 12,000 Hz | = | 83.33 µs |
2 | 8,000 Hz | = | 125.00 µs |
3 | 6,000 Hz | ≈ | 166.67 µs |
4 | 4,800 Hz | ≈ | 208.33 µs |
5 | 4,000 Hz | = | 250.00 µs |
6 | 3,000 Hz | ≈ | 333.33 µs |
7 | 2,000 Hz | = | 500.00 µs |
Fmt
specifies how to convert 8-bit sample inputs to 16-bit:
0 | Unsigned, shift |
1 | Unsigned, subtract 256, shift |
2 | Signed, shift |
3 | Signed, do not shift |
Shift
specifies the number of bits to shift the 16-bit sample
value to the right prior to sending it to the mixer. When Fmt
is
not 3, a sign-propagating right shift is performed on the sample value.
The following I/O ports directly specify 16-bit sample outputs to Hyper Voice:
0x64 | Word | HYPERV_L | Left channel Hyper Voice |
0x66 | Word | HYPERV_R | Right channel Hyper Voice |
These ports are write-only and are undefined when read. They exactly specify the 16-bit sample values that will be used as the output.
HYPERV_L
and HYPERV_R
must be used with word
accesses. Byte accesses have indeterminate operation and generally don't
change the Hyper Voice state.
The following I/O ports directly specify 8-bit sample inputs into Hyper Voice:
0x68 | Byte | HYPERV_SL | Left channel Hyper Voice input |
0x69 | Byte | HYPERV_SR | Right channel Hyper Voice input |
These ports specify the 8-bit sample values that are converted to 16-bit
according to the value of Fmt
in
HYPERV_CTRL.
0x64 | Byte | HYPERV_LL | Left channel Hyper Voice (lower byte) |
0x65 | Byte | HYPERV_LH | Left channel Hyper Voice (upper byte) |
0x66 | Byte | HYPERV_RL | Right channel Hyper Voice (lower byte) |
0x67 | Byte | HYPERV_RH | Right channel Hyper Voice (upper byte) |
0x68 | Byte | HYPERV_SL | Hyper Voice shadow (lower byte) |
0x69 | Byte | HYPERV_SH | Hyper Voice shadow (upper byte) |
Editor's Note: Research is needed to determine whether values can be read
from HYPERV_SL
and HYPERV_SR
.
Editor's Note: Research is needed to determine whether values written to
HYPERV_SL
and HYPERV_SR
are immediately transformed
to 16-bit or if that happens the next time Hyper Voice updates according to
HYPERV_CTRL.Rate
.
WonderSwan has 11 input buttons: two quartets of directional buttons called X and Y, a Start button, and two independent buttons called A and B. The four buttons of each of the X and Y groups are numbered 1 through 4, such as X1 or Y2.
The device is designed to operate in two orientations: horizontal with the WonderSwan logo upright, or vertical rotated 90° couter-clockwise relative to the horizontal orientation. In the horizontal orientation, the X buttons are used as directional input and the A and B buttons are used for actions. In the vertical orientation, the Y buttons are used for directional input and the X buttons are used for actions.
Generally speaking, the Y buttons are less accessible in the horizontal orientation, and the A and B buttons are less accessible in the vertical orientation. Both orientations use the Start button for menu navigation and pausing.
The current state of the buttons can be inspected with the following port:
0xB5 | Byte | KEY_SCAN | Key scan |
7 | 6 | 5 | 4 | 3 | 0 | ||
- | Action |
X | Y | Keys | |||
1 | 1 | 1 | 1 | 4 |
- | This bit has no significance and is undefined when read. | |
Action | R/W | When set, action keys are polled. |
X | R/W | When set, the X buttons are polled. |
Y | R/W | When set, the Y buttons are polled. |
Keys | R |
Significance depends on Action , X and
Y (see below).
|
Action
, X
and Y
select which buttons
have their state loaded into Keys
when subsequently reading from
this port. When the bit is set, the corresponding buttons are loaded into
Keys
, and when the bit is clear, the corresponding buttons are
masked and will not be loaded into Keys
.
The following chart lists which buttons are loaded into the individual bits
of Keys
for each of the control bits written to the port:
Keys | Action | X | Y |
---|---|---|---|
1000 | B | X4 | Y4 |
0100 | A | X3 | Y3 |
0010 | Start | X2 | Y2 |
0001 | - | X1 | Y1 |
The bit marked -
does not correspond to any button and is
undefined when read.
When a button is pressed, its corresponding bit in Keys
is set.
If more than one of Action
, X
and Y
are set simultaneously, the value of Keys
is the bitwise OR of
the corresponding button bits.
The program should wait a few CPU cycles between writing to KEY
and reading from it, in order for the hardware state to stabilize. The
recommended implementation is to use the
ADJ4A instruction, which takes 10
cycles while using only one byte.
Setting all three of Action
, X
and Y
while keys are not being read will minimize power consumption by the keypad
component.
The de facto standard bit mask of the full key state is provided by the WonderWith API. It specifies a 16-bit value with the following format:
15 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ||
- | Y4 |
Y3 |
Y2 |
Y1 |
X4 |
X3 |
X2 |
X1 |
B | A | Start |
- | |||
4 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
The keypad supports an interrupt that the
program can use to respond to button presses. For information regarding
software setup, see Managing
Interrupts. The keypad interrupt is called KEY
and has the
relative vector index +1.
There are no configuration settings for the keypad interrupt: it is enabled or disabled through INT_ENABLE directly.
Key interrupts are requested whenever any bit in the Keys
field
of KEY_SCAN transitions from clear to
set. Depending on which sets of buttons are selected by the
Action
, X
or Y
fields, interrupts can
be restricted to a subset of the buttons. Due to the bitwise-OR behavior when
activating multiple sets this way, the key interrupt can also be requested
whenever any button is pressed.
Overview
Overview
Ports
Contents
Instructions
ERAL - Erase All
ERASE - Erase
EWDS - Erase/Write Disable
EWEN - Erase/Write Enable
READ - Read
WRAL - Write All
WRITE - Write
The console contains a small EEPROM chip that is used to store system-wide settings, such as owner profile information, power-on states for volume and contrast, and the programmable logo startup screen. The EEPROM contained in the WonderSwan itself is known as the internal EEPROM (IEEPROM). Additionally, some WonderSwan games contain an EEPROM chip to store save data.
Mechanically, these EEPROM components have a serial interface with a set of instructions for accessing its data, using a protocol called Microwire. WonderSwan provides designated I/O ports for use by the CPU that stage values to send to, and to hold values received from, the EEPROM components.
The capacity of the memory depends on the use case: 64 words for internal EEPROM on the monochrome model and color models with color mode disabled, 1,024 words for internal EEPROM on color models with color mode enabled, and may be absent or any size within cartridges. Memory addresses are indexed by word: address 1 represents the second 16-bit data unit in memory.
If color mode is disabled on a color model, all internal EEPROM interactions behave as they do on the monochrome model.
The EEPROM components have a write-enabled state that must be activated prior to modifying the contents of their memory. If a write or erase instruction is attempted while writes are disabled, the instruction will be ignored. During system reset, writes are disabled in order to prevent accidental modification of EEPROM contents. However, the boot programs in all WonderSwan models activate write enable mode for the internal EEPROM and leave it active when launching the program on the cartridge.
Warning: Since the BANDAI logo startup screen is processed from internal EEPROM data on color models, it is possible to produce an internal EEPROM configuration that cannot advance past the boot procedure, and which persists after power-off. Specific fields in the ROM header can be configured to allow the system to supply a default boot screen and allow all of internal EEPROM to be updated by the program in the event a corruption needs to be repaired. For more information, see ROM Header.
When accessing internal EEPROM I/O ports on the monochrome model, byte accesses to odd port addresses function as open bus. Odd byte accesses on color models, even byte accesses on all models, and all accesses to cartridge EEPROM I/O ports all function normally.
The following I/O ports are used to stage and receive data used in EEPROM communications:
0xBA | Word | IN_SERIAL_DATA | Internal serial ROM data |
0xC4 | Word | CART_SERIAL_DATA | Cartridge serial ROM data |
15 | 0 | ||||||||||||||
Data | |||||||||||||||
16 |
Data | R/W | Bits used during an internal EEPROM communication. |
For read operations, this port contains the data received from the EEPROM. For write operations, the contents of this port are sent to the EEPROM for storage.
Editor's Note: The name CART_SERIAL_DATA
is conjectural and has
been produced by the WonderSwan community.
The following I/O ports configures the instruction to send in an EEPROM communication:
0xBC | Word | IN_SERIAL_COM | Internal serial ROM command address |
0xC6 | Word | CART_SERIAL_COM | Cartridge serial ROM command address |
The exact binary format of these ports depend on the number of address bits in the EEPROM being accessed:
6 bits | Internal EEPROM on monochrome model or color model with color mode disabled. |
6 bits | 1 Kbit cartridge EEPROM |
8 bits | 2 Kbit and 4 Kbit cartridge EEPROM |
10 bits | Internal EEPROM on color model with color mode enabled. |
10 bits | 8 Kbit and 16 Kbit cartridge EEPROM |
The size of the cartridge EEPROM, if any, can be determined by inspecting the save type field in the ROM header.
Given the number of address bits as n, the format of these ports is as follows:
Opcode ≠ 0
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||
Opcode = 0
|
|
Z | W | See below. |
SB | R/W | Start bit. Must be set in order for an instruction to be initiated. |
Opcode | R/W | The instruction to perform (see below). |
Address | R/W |
The word address to access in EEPROM memory. Absent when
Opcode is 0.
|
Subop | R/W | Extended opcode. Present when Opcode is 0. |
X | R/W | These bits are ignored, but hold state when written. |
The conents of these ports are sent verbatim to the respective EEPROM
components, and must match the expected format. All 16 bits are clocked, and
if the first bit that is set is not in the SB
position, the
EEPROM component will not process the instruction. Ensure that all of the
bits in Z
are clear.
Opcode
specifies which operation to perform during execution of
the instruction:
0 | Extended opcode (see below) |
1 | WRITE |
2 | READ |
3 | ERASE |
If Opcode
is 0, the highest 2 bits of Address
are
used as a sub-opcode field, and all lower-order bits of Address
have no significance. The sub-opcode specifies which of the additional
operations to perform:
0 | EWDS | Erase/Write Disable |
1 | WRAL | Write All |
2 | ERAL | Erase All |
3 | EWEN | Erase/Write Enable |
The instruction will be sent to the EEPROM component when the appropriate bit is sent in IN_SERIAL_CTRL or CART_SERIAL_CTRL as appropriate.
Editor's Note: The name CART_SERIAL_COM
is conjectural and has
been produced by the WonderSwan community.
Editor's Note: Not all original cartridges have been exhaustively inspected regarding the number of address bits in the EEPROM commands. It is possible that the list above is not comprehensive.
Editor's Note: Research is needed to determine whether Z
is
handled automatically by the internal EEPROM controller, and whether its
state is retained when switching back and forth between color mode.
The following I/O ports manage communication with the EEPROM components:
0xBE | Word | IN_SERIAL_CTRL | Internal serial ROM status |
0xC8 | Byte | CART_SERIAL_CTRL | Cartridge serial ROM status |
15 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ||||||
- | P | E | W | R | - | Ready |
Done |
||||||||
8 | 1 | 1 | 1 | 1 | 2 | 1 | 1 |
- | R |
These bits have no significance and are clear when read. Not present in
CART_SERIAL_CTRL , which is a byte port.
|
P | R/W |
When set in IN_SERIAL_CTRL , enters write-protected mode (see
below). Not present in CART_SERIAL_CTRL , where it is clear
when read.
|
E | W | When set, intended to initiate an ERAL, ERASE, EWDS or EWEN instruction. Clear when read. |
W | W | When set, intended to initiate a WRAL or WRITE instruction. Clear when read. |
R | W | When set, intended to initiate a READ instruction. Clear when read. |
Ready | R | Clear when the EEPROM component is busy, or is set when it is idle. |
Done | R | Set when a read operation is completes (see below). |
Once write-protected mode is activated on the internal EEPROM, it cannot be
cleared and will remain active until the next system reset. While active, all
words in the internal EEPROM from address 0x30
and above cannot
be written by the program.
The boot program will set P
unless bit 7 of byte 9 (game
version) in the ROM header is set. If this bit is
set, the cartridge program will be able to modify the entire contents of
internal EEPROM as long as it itself does not set P
.
The E
, W
and R
bits all initiate
communication with the EEPROM component. Each has a different behavior
depending on the exact instructions that they are intended to be used with,
and will still function this way even if the contents of
IN_SERIAL_COM or
CART_SERIAL_COM specify a
different instruction. The following behaviors correspond to each bit:
E |
Sends the bits in IN_SERIAL_COM or
CART_SERIAL_COM and takes no further action.
|
W |
Sends the bits in IN_SERIAL_COM or
CART_SERIAL_COM followed by the bits in
IN_SERIAL_DATA or
CART_SERIAL_DATA.
|
R |
Sends the bits in IN_SERIAL_COM or
CART_SERIAL_COM then receives bits into
IN_SERIAL_DATA or CART_SERIAL_DATA.
|
Only one of E
, W
or R
may be set in
order for any action to take place. If more than one is set (or if none are
set), nothing will happen.
After P
is set on the internal EEPROM to activate
write-protected mode, the console will prevent the W
action
whenever Address
in IN_SERIAL_COM
is ≥
0x30
. This coincides with the start of the user profile data and
extends through any custom boot startup screen data. In this situation,
Ready
will remain set.
Done
is cleared when R
is set in
IN_SERIAL_CTRL
or when E
or W
is set
in CART_SERIAL_CTRL
.
Editor's Note: The name CART_SERIAL_CTRL
is conjectural and has
been produced by the WonderSwan community.
Editor's Note: Need to verify that only one control bit can be set at once.
The contents of cartridge EEPROM depend on the cartridge and the program it contains.
The contents of internal EEPROM are as follows. Although EEPROM addresses index 16-bit words, the contents are organized as a byte stream. This document describes the contents of internal EEPROM as a byte buffer with the low byte of each word coming before the high byte. For each field, the byte offset, word address and size in bytes are provided.
On the monochrome model or a color model with color
mode disabled, the internal EEPROM only exposes the first 128 bytes to
the program. All remaining data beginning at word address 0x040
are only accessible when color mode is enabled.
Internal EEPROM contents in the word address range 0x000
-
0x041
pertain to system settings:
Offset | Address | Size | Description |
---|---|---|---|
0x000 | 0x000 | 96 | Program data |
0x060 | 0x030 | 16 | Owner name |
0x070 | 0x038 | 2 | Owner birthday year (high byte first) |
0x072 | 0x039.L | 1 | Owner birthday month |
0x073 | 0x039.H | 1 | Owner birthday day |
0x074 | 0x03A.L | 1 | Owner sex |
0x075 | 0x03A.H | 1 | Owner blood type |
0x076 | 0x03B.L | 1 | Copy of ROM header field Publisher ID from the previous boot |
0x077 | 0x03B.H | 1 | Copy of ROM header field Color from the previous boot |
0x078 | 0x03C.L | 1 | Copy of ROM header field Game ID from the previous boot |
0x079 | 0x03C.H | 3 | (Unknown) |
0x07C | 0x03E.L | 1 | Number of times the cartridge has been changed (see below) |
0x07D | 0x03E.H | 1 | Number of times the owner name has been changed |
0x07E | 0x03F | 2 | Number of times the system has booted |
0x080 | 0x040 | 3 | (Unknown) |
0x083 | 0x041.H | 1 | Extra system settings |
Program data may be written by the cartridge program even when write-protected mode is active. The exact purpose of this region is not known, but it is likely that developers needed to receive authorization from BANDAI before storing data here.
The owner name encodes 16 characters as one-byte units with the following character set:
-0 | -1 | -2 | -3 | -4 | -5 | -6 | -7 | -8 | -9 | -A | -B | -C | -D | -E | -F | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0- | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | |
1- | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U |
2- | V | W | X | Y | Z | ♥ | ♪ | + | - | ? | . |
Byte value 0x00
is the space character. If the name is less than
16 characters, all remaining characters should be spaces. The convention for
reading the owner name from internal EEPROM trims spaces from the right.
Byte values 0x2B
and greater are not intended to be used as
characters in the owner name and will have unspecified significance in any
program that processes them.
The owner birthday is encoded as binary-coded decimal for all three fields. The bytes of the year are exchanged within its word: the low 8 bits are the higher 2 digits and the high 8 bits are the lower 2 digits.
Owner sex may be one of the following values:
0x00 | ? |
0x01 | Male |
0x02 | Female |
Owner blood type may be one of the following values:
0x00 | ? |
0x01 | A |
0x02 | B |
0x03 | O |
0x04 | AB |
The ROM header fields for the current cartridge are compared against the
values in internal EEPROM from the previous boot prior to updating the values
in internal EEPROM. Unless all three bytes match, the value in the low byte
of 0x3E
is incremented.
The values in the low and high bytes of 0x3E
and the word in
0x3F
will not be incremented if they are already the maximum
unsigned value (0xFF
for the bytes and 0xFFFF
for
the word).
The extra system settings byte has the following structure:
7 | 6 | 5 | 2 | 1 | 0 | ||
Enb |
Cont |
- | Vol | ||||
1 | 1 | 4 | 2 |
- | These bits have no significance and are ignored. |
Enb | When set, the boot screen is processed from internal EEPROM. When clear, a default boot screen is used. |
Cont | For WonderSwan Color, set when the "high contrast" setting is on, or clear otherwise. |
Vol | The initial volume setting, with 0=silent and 3=max volume. |
Color models can present a custom boot screen when the device is powered on.
Internal EEPROM contents in the word address range 0x042
-
0x3FF
pertain to the boot screen:
Offset | Address | Size | Description |
---|---|---|---|
0x084 | 0x042.L | 1 | Boot screen name color |
0x085 | 0x042.H | 1 | (Unknown) |
0x086 | 0x043.L | 1 | Boot screen data size setting |
0x087 | 0x043.H | 1 | Boot screen start frame number |
0x088 | 0x044.L | 1 | Boot screen end frame number |
0x089 | 0x044.H | 1 | Boot screen sprite count |
0x08A | 0x045.L | 1 | Boot screen color settings |
0x08B | 0x045.H | 1 | Boot screen character count |
0x08C | 0x046 | 2 | Boot screen palette offset |
0x08E | 0x047 | 2 | Boot screen character offset |
0x090 | 0x048 | 2 | Boot screen map offset |
0x092 | 0x049 | 2 | Boot screen map destination (horizontal) |
0x094 | 0x04A | 2 | Boot screen map destination (vertical) |
0x096 | 0x04B.L | 1 | Boot screen map character width |
0x097 | 0x04B.H | 1 | Boot screen map character height |
0x098 | 0x04C | 4 | Boot screen VBlank vector (segment and offset) |
0x09C | 0x04E.L | 1 | Boot screen name X (horizontal) |
0x09D | 0x04E.H | 1 | Boot screen name Y (horizontal) |
0x09E | 0x04F.L | 1 | Boot screen name X (vertical) |
0x09F | 0x04F.H | 1 | Boot screen name Y (vertical) |
0x0A0 | 0x050 | 2 | (Unknown) |
0x0A2 | 0x052 | 2 | Boot screen sound sample offset |
0x0A4 | 0x053 | * |
Boot screen sound data offsets (see below) |
Remainder | Boot screen program and data |
The console boot program sets up WRAM in the following way:
0x00000 |
Working memory |
0x00800 |
Screen 1 map |
0x01000 |
Screen 2 map |
0x01800 |
Sprites |
0x02000 |
Characters |
0x04000 |
(Not used) |
0x06000 |
Copy of internal EEPROM data beginning from byte offset
0x080
|
0x06780 |
(Unknown) |
0x08000 |
(Not used) |
0x0FE00 |
Palettes |
"Offset" fields in EEPROM data are relative to WRAM address
0x06000
.
The boot screen name color may be one of the following RGB values as described in Palettes (Color):
0x00 |
0x000
|
0x08 |
0x07F
|
|
0x01 |
0xF00
|
0x09 |
0x00F
|
|
0x02 |
0xF70
|
0x0A |
0x70F
|
|
0x03 |
0xFF0
|
0x0B |
0xF0F
|
|
0x04 |
0x7F0
|
0x0C |
0xF07
|
|
0x05 |
0x0F0
|
0x0D |
0xFFF
|
|
0x06 |
0x0F7
|
0x0E |
0x777
|
|
0x07 |
0x0FF
|
0x0F |
0x777
|
The boot screen data size setting specifies the number of bytes to copy from
internal EEPROM beginning at byte offset 0x080
into WRAM at
address 0x06000
. May be one of the following values:
0x00 | 0x380 bytes |
0x01 | 0x780 bytes |
The boot screen color settings byte has the following structure:
7 | 6 | 5 | 4 | 0 | |||
Bpp |
- | Palettes | |||||
1 | 2 | 5 |
- | These bits have no significance and are ignored. |
Bpp | Characters are processed as 1 bit per pixel when clear and 2 bits per pixel planar when set. |
Palettes | The number of palettes to load from EEPROM data. |
The console boot program will supply an empty second bit plane for 1bpp
characters when loading them into WRAM. The character memory beginning at
WRAM address 0x02000
is always in 2bpp planar format.
The boot screen map destination fields depend on whether the boot screen is
being displayed with horizontal or vertical orientation according to the
orientation flag in the ROM header. They are
offsets relative to WRAM address 0x00800
, to be copied into the
map for screen 1.
The boot screen VBlank vector is a formal 32-bit segment/offset pair that is
used by the console boot program to run code defind in internal EEPROM data
during VBlank. The VBlank code in the EEPROM is
expected to be located in segment 0x0600
and return with an
out-of-segment RET instruction with a
0xCB
opcode. When it returns, the following
register configuration is required:
PS | 0x0600 |
DS0 | 0x0600 |
SS | 0x0000 |
Boot screen sound data offsets are a list of 16-bit offsets into WRAM address
0x06000
. One offset may be provided for each
sound channel used by the custom boot screen, and the
list is terminated by specifying the offset 0xFFFF
.
Editor's Note: Research is needed to determine the behavior of invalid name color values.
Editor's Note: Research is needed to determine the behavior of invalid size setting values.
Editor's Note: Need to verify the memory map. The console boot program itself needs to be mapped somewhere.
Editor's Note: Research is needed to determine how sprites are initialized.
Perhaps it loads them from an offset located at byte offset
0x0A0
?
Editor's Note: Need to verify the significance of the data size setting.
Editor's Note: Research is needed to determine the exact significance of the start and end frame fields.
Editor's Note: Research is needed to determine exactly how map contents are processed in the vertical orientation.
Editor's Note: Research is needed to determine exactly how the name is positioned in the vertical orientation.
Editor's Note: Research is needed to determine how many sound channels are to be used by the custom boot screen.
Editor's Note: Research is needed to determine how many sound samples are loaded.
Editor's Note: Research is needed to determine the significance of the sound data.
Erases the entire contents of EEPROM such that every bit of every word becomes set.
This instruction is issued with the following port confuguration:
IN_SERIAL_COM CART_SERIAL_COM |
SB | 1 |
Opcode | 0 | |
Subop | 2 | |
IN_SERIAL_CTRL CART_SERIAL_CTRL |
E | 1 |
While the instruction is underway, Ready
will be clear in
IN_SERIAL_CTRL
or CART_SERIAL_CTRL
. When the
instruction completes, Ready
will be set.
If writes are not enabled via EWEN, this instruction will be ignored.
Editor's Note: This instruction is not guaranteed to be supported on all cartridges with EEPROM.
Editor's Note: Need to verify whether the implementation prohibits this instruction from being used on internal EEPROM.
Erases the contents of the specified word in internal EEPROM such that every bit in the word becomes set.
This instruction is issued with the following port confuguration:
IN_SERIAL_COM CART_SERIAL_COM |
SB | 1 |
Opcode | 3 | |
Address | The word address to erase. | |
IN_SERIAL_CTRL CART_SERIAL_CTRL |
E | 1 |
While the instruction is underway, Ready
will be clear in
IN_SERIAL_CTRL
or CART_SERIAL_CTRL
. When the
instruction completes, Ready
will be set.
If writes are not enabled via EWEN, this instruction will be ignored.
Editor's Note: Need to verify whether the implementation prohibits this instruction from being used on internal EEPROM.
Deactivates write-enable status. While writes are disabled, ERAL, ERASE, WRAL and WRITE instructions will be ignored.
This instruction is issued with the following port confuguration:
IN_SERIAL_COM CART_SERIAL_COM |
SB | 1 |
Opcode | 0 | |
Subop | 0 | |
IN_SERIAL_CTRL CART_SERIAL_CTRL |
E | 1 |
While the instruction is underway, Ready
will be clear in
IN_SERIAL_CTRL
or CART_SERIAL_CTRL
. When the
instruction completes, Ready
will be set.
Activates write-enable status. While writes are enabled, ERAL, ERASE, WRAL and WRITE instructions can be used.
This instruction is issued with the following port confuguration:
IN_SERIAL_COM CART_SERIAL_COM |
SB | 1 |
Opcode | 0 | |
Subop | 3 | |
IN_SERIAL_CTRL CART_SERIAL_CTRL |
E | 1 |
While the instruction is underway, Ready
will be clear in
IN_SERIAL_CTRL
or CART_SERIAL_CTRL
. When the
instruction completes, Ready
will be set.
Reads the value of the specified word in EEPROM and stores it in IN_SERIAL_DATA or CART_SERIAL_DATA.
This instruction is issued with the following port confuguration:
IN_SERIAL_COM CART_SERIAL_COM |
SB | 1 |
Opcode | 2 | |
Address | The word address to read. | |
IN_SERIAL_CTRL CART_SERIAL_CTRL |
R | 1 |
While the instruction is underway, Done
will be clear in
IN_SERIAL_CTRL
or CART_SERIAL_CTRL
. When the
instruction completes, Done
will be set and the value can be
input from IN_SERIAL_DATA
or CART_SERIAL_DATA
.
Editor's Note: When reading from internal EEPROM, the boot program and
WonderWitch API poll Done
in a loop and abort if it stays clear
for 32 consecutive iterations.
Writes the specified value to the entire contents of EEPROM.
This instruction is issued with the following port confuguration:
IN_SERIAL_COM CART_SERIAL_COM |
SB | 1 |
Opcode | 0 | |
Subop | 1 | |
IN_SERIAL_DATA CART_SERIAL_DATA |
Data | The word value to write. |
IN_SERIAL_CTRL CART_SERIAL_CTRL |
W | 1 |
While the instruction is underway, Ready
will be clear in
IN_SERIAL_CTRL
or CART_SERIAL_CTRL
. When the
instruction completes, Ready
will be set.
If writes are not enabled via EWEN, this instruction will be ignored.
Editor's Note: This instruction is not guaranteed to be supported on all cartridges with EEPROM.
Editor's Note: Need to verify whether the implementation prohibits this instruction from being used on internal EEPROM.
Writes the specified value to the specified word in EEPROM.
This instruction is issued with the following port confuguration:
IN_SERIAL_COM CART_SERIAL_COM |
SB | 1 |
Opcode | 1 | |
Address | The word address to write. | |
IN_SERIAL_DATA CART_SERIAL_DATA |
Data | The word value to write. |
IN_SERIAL_CTRL CART_SERIAL_CTRL |
W | 1 |
While the instruction is underway, Ready
will be clear in
IN_SERIAL_CTRL
or CART_SERIAL_CTRL
. When the
instruction completes, Ready
will be set.
If writes are not enabled via EWEN,
or if P
has been set in IN_SERIAL_CTRL
and
Address
in IN_SERIAL_COM
≥ 0x30
,
this instruction will be ignored.
Editor's Note: The boot program polls Ready
in a loop and aborts
if it stays clear for 0x1600
consecutive iterations.
Editor's Note: Even if write-protected mode is in effect for internal EEPROM,
it is possible to write the value 0x0000
to any word address by
setting R
in IN_SERIAL_CTRL
instead of
W
and monitoring Done
in
IN_SERIAL_CTRL
. The reason this works is because the console
clocks another 16 bits in anticipation of receiving a value from the EEPROM,
but since Opcode
= 1, the EEPROM is also expecting a value and
interprets the quiet pin state as 16 zeroes.
A cartridge with a 2003 mapper may contain a real-time clock (RTC) component for keeping track of time using only power from a battery inside the cartridge itself. The 2003 mapper is responsible for communicating with both the program and the RTC.
Contents
Registers
Ports
Commands
Interrupts
The RTC component holds its state in a small set of registers.
A 56-bit register that holds the current real date and time information. Organized into 7 bytes with the following format:
0 |
|
4 |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
1 |
|
5 |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2 |
|
6 |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
3 |
|
- | R | These bits have no significance and are clear when read. |
Year | R/W | The last two digits of the calendar year. |
Month | R/W | The 1-based index of the calendar month. |
Date | R/W | The 1-based day of the calendar month. |
Day | R/W | The zero-based day of the calendar week. |
AMPM | R/W | Specifies time in AM when clear and PM when set. |
Hour | R/W | The hour of the time. |
Minute | R/W | The minute of the time. |
Second | R/W | The second of the time. |
All fields except AMPM
express numbers in binary-coded
decimal (BCD) format.
When writing date and time information, each field has a valid BCD range. If the value being written is not within this range, a default value is substituted for that field:
Field | Range | Default |
---|---|---|
Year | 00 to 99 | 00 |
Month | 01 to 12 | 01 |
Date | 01 to 31 [note] | 01 |
Day | 0 to 6 | 0 |
Hour (12-hour) |
00 to 11 | 00 |
Hour (24-hour) |
00 to 23 | 00 |
Minute | 00 to 59 | 00 |
Second | 00 to 59 | 00 |
[note] | If the specified day of the month is not valid for the specified month (accounting for leap years), the date will be advanced to the first day of the following month. |
The RTC component does not specify which day of the week corresponds to each
numeric value in Day
.
While in 24-hour mode, the value read from AMPM
will be clear if
Hour
is 11 or less, or will be set otherwise. While in 24-hour
mode, writes to AMPM
are ignored.
Editor's Note: The highest-order bit of the seconds byte will indicate when the RTC component is in test mode, but the 2003 mapper cannot activate test mode. This bit will always be clear when read.
An 8-bit register that holds processing state and accepts commands. Has the following format:
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
POWER |
1224 |
INTAE |
- | INTME |
- | INTFE |
- |
1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
- | R | These bits have no significance and are clear when read. |
POWER | R | Set if a power cycle occurred, or clear otherwise (see below). |
1224 | R/W | Specifies 12-hour mode when clear or 24-hour mode when set. |
INTAE | R/W | Used to configure the interrupt mode (see below). |
INTME | R/W | Used to configure the interrupt mode. |
INTFE | R/W | Used to configure the interrupt mode. |
If the RTC component loses power, POWER
will become set. The
most likely cause for this is if the battery in the cartridge dies, meaning
POWER
also signals a loss of RTC data. POWER
is
cleared whenever the status register is read or a reset command is issued.
The value of 1224
influences the range of values read from and
written to the Hour
field in the real-time
data register.
INTAE
, INTME
and INTFE
jointly specify
the RTC's interrupt mode:
INTAE | INTME | INTFE | Mode |
---|---|---|---|
0 | 0 | 0 | Disabled |
(Any) | 0 | 1 | Selected frequency steady |
(Any) | 1 | 0 | Per-minute edge |
(Any) | 1 | 1 | Per-minute steady |
1 | 0 | 0 | Alarm |
Supplies additional configuration when the RTC's interrupt mode is either alarm or selected frequency steady.
This register holds 16 bits of data and is organized into two bytes. It is
intended to by write-only: reads will give the byte values 0xFF
,
0xFF
and set the contents of the register to 0xFF
,
0xFF
.
When the RTC's interrupt mode is alarm, this register has the following format:
0 |
|
||||||||||||||||||||||||||||||||||||||||
1 |
|
- | W | These bits are not used in alarm mode. |
AMPM | W | The AM/PM state to match for the alarm. |
Hour | W | The hour to match for the alarm. |
Minute | W | The minute to match for the alarm. |
For information regarding interrupt opearation, see Alarm.
When the RTC's interrupt mode is selected frequency steady, this register has the following format:
0 |
|
||||||||||||||||||||||||||||||||||||||||
1 |
|
Each bit corresponds to a square wave signal with a duty cycle of 50% high followed by low with a period of the specified frequency. When the bit is set, the signal is enabled; when the bit is clear, the signal is disabled.
For information regarding interrupt opearation, see Selected Frequency Steady.
RTC data is output to and input from the following I/O port:
0xCB | Byte | RTC_DATA | RTC data |
7 | 0 | ||||||
Data | |||||||
8 |
Data | R/W | Bits used during an RTC communication. |
For read operations, this port contains data received from the RTC. For write operations, the contents of this port are sent to the RTC for processing.
RTC communications are managed through the following port:
0xCA | Byte | RTC_CTRL | RTC control |
7 | 6 | 5 | 4 | 3 | 1 | 0 | |
Ready |
- | Active |
Cmd | WR |
|||
1 | 2 | 1 | 3 | 1 |
- | R | These bits have no significance and are clear when read. |
Ready | R |
Set when the program should access RTC_DATA , or clear
otherwise.
|
Active | R/W | When set, a communication with the RTC is underway. |
Cmd | R/W | The RTC command code to process. |
WR | R/W | Performs a write operation when clear or a read operation when set. |
Any output to RTC_CTRL
will reset the 2003
mapper's RTC handling to the start of the specified command. If the
program outputs to RTC_CTRL
before processing for the previous
command completes, the states of the 2003 mapper and the RTC will become
desynchronized and produce undefined behavior until such a time they fall
into sync with one another again.
During command processing, the program should not access
RTC_DATA
while Ready
is clear. When the 2003 mapper
is ready for the program to manage more data, Ready
will be set
automatically.
When a valid RTC command completes, Active
will be cleared
automatically.
Cmd
specifies what kind of RTC command is being initiated:
0 | Reset |
1 | Status register access |
2 | Real-time data register access, begin at byte 0 |
3 | Real-time data register access, begin at byte 4 |
4 | Alarm time/frequency duty setting register access |
5 | No operation |
6 | Invalid |
7 | Invalid |
When WR
is clear, the command is a write command. When
WR
is set, the command is a read command. For information
regarding communications, see Commands.
Editor's Note: Outputs to RTC_CTRL
will send a control byte to
the RTC. The value of the control byte is 0x60
ORed with the
lower 4 bits of RTC_CTRL
. If RTC_CTRL
is outputted
to in the middle of an incomplete write command, it is possible for the bits
of the control byte to be stored in an RTC register.
Outputting to RTC_CTRL will initiate
a read or a write command. Data will either be transfered into
RTC_DATA for reads or out of
RTC_DATA
for writes.
When multiple bytes are being transferred, the program will need to access
RTC_DATA
multiple times. When the 2003
mapper has finished processing a byte and is ready for the program to
handle data, Ready
will be set in RTC_CTRL
, which
the program can check before performing an access to RTC_DATA
.
As soon as RTC_DATA
is accessed as required, command processing
resumes.
When the program outputs to RTC_CTRL
, the 2003 mapper performs
an algorithm equivalent to the following:
♦ |
If an invalid command was specified:
|
||||||||||||||||||||||||||
♦ |
For each byte to be processed:
|
||||||||||||||||||||||||||
▪ | Set Ready in RTC_CTRL |
||||||||||||||||||||||||||
▪ | Clear Active in RTC_CTRL |
Note that this algorithm begins as soon as RTC_CTRL
is outputted
to, meaning a value should be staged in RTC_DATA
in advance of
write operations.
If Ready
is set after command processing terminates, it will be
cleared the next time the program accesses RTC_DATA
. This is the
case regardless of whether that access is an input or an output, and
regardless of whether the RTC operation was a read or a write.
Editor's note: During a read operation, outputs to RTC_DATA
are
ignored if both Ready
and Active
are set in
RTC_CTRL
. Research is needed to determine whether outputs to
RTC_DATA
are always ignored during read operations while
Active
is set.
Erases the contents of the registers so that all the fields have their default values.
This command is initiated by outputting the following to RTC_CTRL:
Active | 1 |
Cmd | 0 |
WR | (Any) |
This command does not transfer any bytes with the RTC. After this command completes, the contents of the registers will be as follows:
Real-time data register:
|
||||||||||||||||
Status register:
|
||||||||||||||||
Alarm time/frequency duty setting register: | ||||||||||||||||
0x00 , 0x00
|
Performs a read or write operation on the status register.
This command is initiated by outputting the following to RTC_CTRL:
Active | 1 |
Cmd | 1 |
WR | (As appropriate) |
This command transfers 1 byte that exactly matches the format of the status register.
Performs a read or write operation on the real-time data register.
This command is initiated by outputting the following to RTC_CTRL:
Active | 1 |
Cmd | 2 (begin at byte 0), or 3 (begin at byte 4) |
WR | (As appropriate) |
The real-time data register contains 7 bytes of data: 4 date fields followed
by 3 time fields. Cmd
2 transfers all 7 bytes beginning with
byte 0 (Year
), and Cmd
3 transfers 3 bytes and only
accesses the time fields beginning with byte 4 (Hour
).
Performs a read or write operation on the alarm time/frequency duty setting register.
This command is initiated by outputting the following to RTC_CTRL:
Active | 1 |
Cmd | 4 |
WR | (As appropriate) [note] |
[note] | The alarm time/frequency duty setting register is not intended to be read. Attempting to read from it has anomalous behavior described below. |
This command transfers 2 bytes. When performing a write operation, the bytes
exactly match the format of the alarm time/frequency duty setting register.
The register is intended to be write-only: performing a read operation on it
will return the bytes 0xFF
, 0xFF
and replace the
contents of the register with 0xFF
, 0xFF
.
Performs no meaningful operation.
This command is initiated by outputting the following to RTC_CTRL:
Active | 1 |
Cmd | 5 |
WR | (As appropriate) |
This command transfers 2 bytes, but otherwise doesn't do anything. Performing
a read operation will return the bytes 0xFF
, 0xFF
.
Does not initiate any command. This condition applies when either of the following is outputted to RTC_CTRL:
Active | 0 |
Cmd | (Any) |
WR | (Any) |
or:
Active | 1 |
Cmd | 6 or 7 |
WR | (Any) |
After issuing an invalid command, the 2003 mapper will immediately await another command.
The 2003 mapper can use the RTC to request a cartridge interrupt. RTC interrupts are managed through the status register.
Changing interrupt modes affects the request state according to the behavior of the new mode.
The RTC will not request an interrupt.
This interrupt mode is set when the following is configured in the status register:
INTAE | 0 |
INTME | 0 |
INTFE | 0 |
When switching to this mode, any ongoing interrupt request will stop being requested.
The RTC will request an interrupt according to a signal configured through the alarm time/frequency duty setting register.
This interrupt mode is set when the following is configured in the status register:
INTAE | (Any) |
INTME | 0 |
INTFE | 1 |
The alarm time/frequency duty setting register specifies the enabled state of 16 signals, each with a different frequency. All signals have a 50% duty cycle where the start of the high phase is aligned with the edge of the real-time seconds counter. Whenever one or more of the enabled signals is high, an interrupt will be requested.
The RTC will request an interrupt at the start of every real-time minute.
This interrupt mode is set when the following is configured in the status register:
INTAE | (Any) |
INTME | 1 |
INTFE | 0 |
Once an interrupt request begins in this mode, it will continue to be requested until the interrupt mode is changed to disabled. If the interrupt mode is subsequently changed to per-minute edge during the first 10 ms of the minute, another interrupt request will occur.
The RTC will request an interrupt at the start of every real-time minute.
This interrupt mode is set when the following is configured in the status register:
INTAE | (Any) |
INTME | 1 |
INTFE | 1 |
Once an interrupt request begins in this mode, it will continue to be requested until 30 seconds have gone by or the interrupt mode is changed to disabled. If the interrupt mode is subsequently changed to per-minute steady during the first 10 ms of the minute, another interrupt request will occur.
The RTC will request an interrupt whenever the contents of the alarm time/frequency duty setting register exactly match bytes 4 and 5 of the real-time data register.
This interrupt mode is set when the following is configured in the status register:
INTAE | 1 |
INTME | 0 |
INTFE | 0 |
Bytes 4 and 5 of the real-time data register specify the
AMPM
/Hour
fields and the Minute
field
respectively. Bit 6 of the first byte and bit 7 of the second byte are not
considered, but otherwise an interrupt will be requested whenever the alarm
time exactly matches the current hour and minute.
The alarm time/frequency duty setting register can store any bits in the time
fields, even those that the real-time data register can never contain. This
includes invalid combinations of AMPM
and Hour
, and
out-of-range digits for Hour
and Minute
. If the
alarm time bits do not exactly match the current time bits, the RTC will not
request an interrupt.
System components are initialized in the following ways when the WonderSwan is powered on.
The following registers are initialized on reset:
DS0 | 0x0000 |
DS1 | 0x0000 |
PC | 0x0000 |
PS | 0xFFFF |
PSW | 0xF002 [note] |
SS | 0x0000 |
[note] |
All fields in PSW are cleared on reset. The only bits that
are set are among those with fixed state.
|
All other registers are undefined on reset.
The following cartridge ports are initialized on reset:
LINEAR_ADDR_OFF | 0xFF |
RAM_BANK | 0xFF |
RAM_BANK_L | 0xFF |
RAM_BANK_H | 0xFF |
ROM_BANK_0 | 0xFF |
ROM_BANK_0_L | 0xFF |
ROM_BANK_0_H | 0xFF |
ROM_BANK_1 | 0xFF |
ROM_BANK_1_L | 0xFF |
ROM_BANK_1_H | 0xFF |
Writes are disabled on reset, but the boot program always enables them before launching the cartridge program.
Write-protected mode is disabled on reset. Unless bit 7 of byte 9 (game version) in the ROM header is set, the boot program will activate write-protected mode.
The following ports are initialized on reset:
LCD_VTOTAL | 0x9E |
LCD_VSYNC | 0x9B |
Editor's Note: Research is needed to determine exactly what state the video features are in upon reset, and what parts of it are initialized by the boot program. For all intents and purposes, it appears that after the boot program runs, all features are is disabled.
WonderSwan - Sacred Tech Scroll
March 17, 2023
Written by Guy Perfect
Special thanks to the following individuals:
WSMan
August 19, 2016
Revision 7
Written by Alex "trap15" Marshall
Link
WonderSwan SplashBuilder
October 10, 2019
GitHub project
Written by Godzil
Link
Everything You Never Wanted to Know about the WonderSwan RTC
December 18, 2020
NesDev.org forum post
Written by lidnariq
Link
WStech
Version 2.1
Written by Judge and Dox
Link
16-Bit V Series™ Instruction User's Manual
September 2000
Document No. U11301EJ5V0UMJ1 (5th edition)
Written by Renesas Technology Corporation
Download
The 8086 Family User's Manual
October 1979
Document No. 9800722-03
Written by Intel Corporation
Link
V30MZ™ Preliminary User's Manual
January 2002
Document No. A13761EJ1V1UM00 (1st edition)
Written by Renesas Technology Corporation
Download
Real-Time Clock S-3511A
Revision 1.4_00
Written by Seiko Epson Corporation
Download
x86 instruction listings
Wikipedia page
Link
And countless hours of original research.