aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile27
-rw-r--r--README.md28
-rw-r--r--roms/audio.rombin959 -> 0 bytes
-rw-r--r--roms/automata.rombin243 -> 0 bytes
-rw-r--r--roms/bifurcan.rombin634 -> 0 bytes
-rw-r--r--roms/controller.rombin958 -> 0 bytes
-rw-r--r--roms/dvd.rombin307 -> 261 bytes
-rw-r--r--roms/file.load.rombin1230 -> 0 bytes
-rw-r--r--roms/file.save.rombin108 -> 0 bytes
-rw-r--r--roms/hover.rombin493 -> 0 bytes
-rw-r--r--roms/label.rombin1434 -> 0 bytes
-rw-r--r--roms/multichannel.audio.rombin1228 -> 0 bytes
-rw-r--r--roms/noodle.rombin7274 -> 0 bytes
-rw-r--r--roms/polycat.rombin793 -> 0 bytes
-rw-r--r--roms/proportional_fonts.rombin1330 -> 0 bytes
-rw-r--r--roms/screen.rombin595 -> 0 bytes
-rw-r--r--roms/shapes.rombin1147 -> 0 bytes
-rw-r--r--roms/theme.rombin3152 -> 0 bytes
-rw-r--r--roms/wallpaper.rombin181 -> 0 bytes
-rw-r--r--src/common.h11
-rw-r--r--src/config.c13
-rw-r--r--src/debug.c206
-rw-r--r--src/devices.c303
-rw-r--r--src/file.c69
-rw-r--r--src/input.c203
-rw-r--r--src/main.c527
-rw-r--r--src/ppu.c524
-rw-r--r--src/ppu.h6
-rw-r--r--src/profiling.c157
-rw-r--r--src/rom.c5
-rw-r--r--src/uxn-core.c36
-rw-r--r--src/uxn-core.s2721
-rw-r--r--src/uxn.c4269
-rw-r--r--src/uxn.h57
-rw-r--r--tools/bin2carr/Makefile47
-rw-r--r--tools/bin2carr/src/main.c232
-rw-r--r--tools/bin2carr/src/shorthand.h35
38 files changed, 4230 insertions, 5247 deletions
diff --git a/.gitignore b/.gitignore
index 7810e33..4a050fe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
1build 1build
2roms
2src/uxn/roms/boot.c 3src/uxn/roms/boot.c
diff --git a/Makefile b/Makefile
index 100c861..8da65eb 100644
--- a/Makefile
+++ b/Makefile
@@ -15,8 +15,9 @@ LIBGBA += $(LIBGBA_DIR)/lib/libmm.a
15SRC_DIR := src 15SRC_DIR := src
16BUILD_DIR := build 16BUILD_DIR := build
17SRC_MAIN := $(SRC_DIR)/main.c 17SRC_MAIN := $(SRC_DIR)/main.c
18ROM := $(BUILD_DIR)/rom.c 18UXN_ROM := roms/dvd.rom
19ROM_SRC := roms/dvd.rom 19ROM_FILE := $(BUILD_DIR)/uxn.rom
20ROM_OBJ := $(BUILD_DIR)/rom.o
20ASM_FILES := $(wildcard $(SRC_DIR)/*.s) 21ASM_FILES := $(wildcard $(SRC_DIR)/*.s)
21WATCH_SRC := $(shell find $(SRC_DIR) -name *.c -or -name *.s -or -name *.h) 22WATCH_SRC := $(shell find $(SRC_DIR) -name *.c -or -name *.s -or -name *.h)
22INC_DIRS := $(shell find $(SRC_DIR) -type d) 23INC_DIRS := $(shell find $(SRC_DIR) -type d)
@@ -29,16 +30,13 @@ TARGET := uxngba
29ELF := $(BUILD_DIR)/$(TARGET).elf 30ELF := $(BUILD_DIR)/$(TARGET).elf
30BIN := $(BUILD_DIR)/$(TARGET).gba 31BIN := $(BUILD_DIR)/$(TARGET).gba
31 32
32# Target tools.
33TOOLS_BIN2CARR := tools/bin2carr/build/bin2carr
34
35# Compiler and linker configuration. 33# Compiler and linker configuration.
36CC := $(DEVKITBIN)/arm-none-eabi-gcc 34CC := $(DEVKITBIN)/arm-none-eabi-gcc
37OBJCOPY := $(DEVKITBIN)/arm-none-eabi-objcopy 35OBJCOPY := $(DEVKITBIN)/arm-none-eabi-objcopy
38ARCH := -mthumb -mthumb-interwork 36ARCH := -mthumb -mthumb-interwork
39SPECS := -specs=gba.specs 37SPECS := -specs=gba.specs
40CONFIG := 38CONFIG :=
41CFLAGS := -Wall -Wextra -pedantic -Wno-incompatible-pointer-types 39CFLAGS := -Wall -Wextra -pedantic -Wno-incompatible-pointer-types -Wno-unused-variable -Wno-unused-function -Wno-unused-parameter
42CFLAGS += -fno-strict-aliasing 40CFLAGS += -fno-strict-aliasing
43CFLAGS += -mcpu=arm7tdmi -mtune=arm7tdmi $(ARCH) 41CFLAGS += -mcpu=arm7tdmi -mtune=arm7tdmi $(ARCH)
44CFLAGS += $(INC_FLAGS) 42CFLAGS += $(INC_FLAGS)
@@ -62,17 +60,23 @@ endif
62 60
63main: $(BUILD_DIR) $(ROM) $(BIN) 61main: $(BUILD_DIR) $(ROM) $(BIN)
64 62
65$(ROM): $(TOOLS_BIN2CARR) 63# Creates the rom object file from the given UXN_ROM.
66 ./tools/bin2carr/build/bin2carr -n uxn_rom -e u16 -o $(ROM) $(ROM_SRC) 64$(ROM_FILE):
65 cp $(UXN_ROM) $(ROM_FILE)
66
67$(ROM_OBJ): $(ROM_FILE)
68 $(OBJCOPY) --rename-section .data=.rodata \
69 -I binary -O elf32-littlearm $(ROM_FILE) $(ROM_OBJ)
67 70
68# Strip and fix header to create final .gba file. 71# Strip and fix header to create final .gba file.
69$(BIN): $(ELF) 72$(BIN): $(ELF)
70 $(OBJCOPY) -v -O binary $(ELF) $(BIN) 73 $(OBJCOPY) -v -O binary $(ELF) $(BIN)
71 $(DEVKITTOOLS)/gbafix $(BIN) 74 $(DEVKITTOOLS)/gbafix $(BIN)
75 rm $(ROM_FILE)
72 76
73# Link files. 77# Link files.
74$(ELF): $(SRC_MAIN) $(WATCH_SRC) 78$(ELF): $(SRC_MAIN) $(WATCH_SRC) $(ROM_OBJ) | $(BUILD_DIR)
75 $(CC) $(CFLAGS) $(LDFLAGS) -o $(ELF) $(SRC_MAIN) $(ASM_FILES) $(LDLIBS) 79 $(CC) $(CFLAGS) $(LDFLAGS) -o $(ELF) $(SRC_MAIN) $(ASM_FILES) $(LDLIBS) $(ROM_OBJ)
76 80
77# Create build directory if needed. 81# Create build directory if needed.
78$(BUILD_DIR): 82$(BUILD_DIR):
@@ -85,6 +89,3 @@ run: main
85# Remove build directory. 89# Remove build directory.
86clean: 90clean:
87 rm -rf $(BUILD_DIR) 91 rm -rf $(BUILD_DIR)
88
89$(TOOLS_BIN2CARR):
90 make -C tools/bin2carr
diff --git a/README.md b/README.md
index dbc90c0..baadcc9 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,13 @@
1# UXNGBA 1# UXNGBA
2 2
3This is a port of the [UXN virtual machine][uxn] for the GBA. It is currently at 3This is a port of the [UXN virtual machine][uxn] for the GBA. UXN is a project
4an early stage, but is capable of running simple demos that make use of the 4created by the artist collective and research studio [100 rabbits][100r]. It can
5screen or console devices, including the beautiful DVD bouncing. 5be used to write small graphical applications, tools and games. Programs written
6for UXN are distributed via bytecode compiled roms, akin to classic console
7emulators. For this project, uxn roms are embedded directly in the .gba rom.
6 8
7[uxn]: https://wiki.xxiivv.com/site/uxn.html 9[uxn]: https://wiki.xxiivv.com/site/uxn.html
10[100r]: https://100r.co/
8 11
9## Building from source 12## Building from source
10 13
@@ -27,16 +30,13 @@ If everything is properly installed, you should be able to run `make` to compile
27the program into a `uxngba.gba` rom. If you have `mgba-qt` installed, you can 30the program into a `uxngba.gba` rom. If you have `mgba-qt` installed, you can
28test it with: `make run`. 31test it with: `make run`.
29 32
30To use a specific UXN compiled rom, you can pass it as the `ROM_SRC` make 33To use a specific UXN compiled rom, you can pass it as the `UXN_ROM` make
31parameter: 34parameter:
32 35
33``` 36```
34make run ROM_SRC=roms/noodle.rom 37make run UXN_ROM=roms/noodle.rom
35``` 38```
36 39
37If you have compiled a rom already and want to change it, you probably want to
38use `make clean` beforehand.
39
40[devkitpro]: https://devkitpro.org/ 40[devkitpro]: https://devkitpro.org/
41 41
42## Configuration 42## Configuration
@@ -49,14 +49,14 @@ macros on compile time as described below.
49### Input method order 49### Input method order
50 50
51Uxngba currently supports three different control schemes that can be cycled by 51Uxngba currently supports three different control schemes that can be cycled by
52pressing the SELECT button: `CONTROL_CONTROLLER`, `CONTROL_MOUSE` and 52pressing the L or R buttons: `CONTROL_CONTROLLER`, `CONTROL_MOUSE` and
53`CONTROL_KEYBOARD`. To select the order and available methods set the 53`CONTROL_KEYBOARD`. To select the order and available methods set the
54`CONTROL_METHODS` macro on compile time. For example, [noodle][noodle] doesn't 54`CONTROL_METHODS` macro on compile time. For example, [noodle][noodle] doesn't
55make much use of the controller scheme, and we may want to use the mouse as the 55make much use of the controller scheme, and we may want to use the mouse as the
56default input method. This can be achieved with the following command: 56default input method. This can be achieved with the following command:
57 57
58``` 58```
59make run ROM_SRC=roms/noodle.rom CONFIG="-DCONTROL_METHODS=CONTROL_MOUSE,CONTROL_KEYBOARD" 59make run UXN_ROM=roms/noodle.rom CONFIG="-DCONTROL_METHODS=CONTROL_MOUSE,CONTROL_KEYBOARD"
60``` 60```
61 61
62### Audio quality 62### Audio quality
@@ -69,11 +69,11 @@ a good quality-performance compromise. A high quality and low-fi audio modes can
69be selected by setting the `AUDIO_HIFI` or `AUDIO_LOFI` macros: 69be selected by setting the `AUDIO_HIFI` or `AUDIO_LOFI` macros:
70 70
71``` 71```
72make run ROM_SRC=roms/audio.rom CONFIG="-DAUDIO_HIFI" 72make run UXN_ROM=roms/audio.rom CONFIG="-DAUDIO_HIFI"
73 73
74 or 74 or
75 75
76make run ROM_SRC=roms/audio.rom CONFIG="-DAUDIO_LOFI" 76make run UXN_ROM=roms/audio.rom CONFIG="-DAUDIO_LOFI"
77``` 77```
78 78
79### Text layer 79### Text layer
@@ -81,10 +81,12 @@ make run ROM_SRC=roms/audio.rom CONFIG="-DAUDIO_LOFI"
81When writing text to the screen (for example using the console device) the text 81When writing text to the screen (for example using the console device) the text
82will be drawn by default on the foreground layer. This can be controlled by 82will be drawn by default on the foreground layer. This can be controlled by
83setting the `TEXT_MODE` option to 0 for foreground mode or 1 for background 83setting the `TEXT_MODE` option to 0 for foreground mode or 1 for background
84mode. 84mode. The text layer can be omitted if using the TEXT_DISABLE macro.
85 85
86``` 86```
87make run CONFIG="-DTEXT_MODE=1" 87make run CONFIG="-DTEXT_MODE=1"
88
89make run CONFIG="-DTEXT_DISABLE=1"
88``` 90```
89 91
90### Performance metrics 92### Performance metrics
diff --git a/roms/audio.rom b/roms/audio.rom
deleted file mode 100644
index 15c8f2d..0000000
--- a/roms/audio.rom
+++ /dev/null
Binary files differ
diff --git a/roms/automata.rom b/roms/automata.rom
deleted file mode 100644
index 9c0b3f7..0000000
--- a/roms/automata.rom
+++ /dev/null
Binary files differ
diff --git a/roms/bifurcan.rom b/roms/bifurcan.rom
deleted file mode 100644
index 92e613f..0000000
--- a/roms/bifurcan.rom
+++ /dev/null
Binary files differ
diff --git a/roms/controller.rom b/roms/controller.rom
deleted file mode 100644
index eb672b3..0000000
--- a/roms/controller.rom
+++ /dev/null
Binary files differ
diff --git a/roms/dvd.rom b/roms/dvd.rom
index 9d47e7d..f62603d 100644
--- a/roms/dvd.rom
+++ b/roms/dvd.rom
Binary files differ
diff --git a/roms/file.load.rom b/roms/file.load.rom
deleted file mode 100644
index 1f486ee..0000000
--- a/roms/file.load.rom
+++ /dev/null
Binary files differ
diff --git a/roms/file.save.rom b/roms/file.save.rom
deleted file mode 100644
index 6d8debb..0000000
--- a/roms/file.save.rom
+++ /dev/null
Binary files differ
diff --git a/roms/hover.rom b/roms/hover.rom
deleted file mode 100644
index 3c59f52..0000000
--- a/roms/hover.rom
+++ /dev/null
Binary files differ
diff --git a/roms/label.rom b/roms/label.rom
deleted file mode 100644
index fc5fd9c..0000000
--- a/roms/label.rom
+++ /dev/null
Binary files differ
diff --git a/roms/multichannel.audio.rom b/roms/multichannel.audio.rom
deleted file mode 100644
index e737701..0000000
--- a/roms/multichannel.audio.rom
+++ /dev/null
Binary files differ
diff --git a/roms/noodle.rom b/roms/noodle.rom
deleted file mode 100644
index 4776074..0000000
--- a/roms/noodle.rom
+++ /dev/null
Binary files differ
diff --git a/roms/polycat.rom b/roms/polycat.rom
deleted file mode 100644
index cc9df69..0000000
--- a/roms/polycat.rom
+++ /dev/null
Binary files differ
diff --git a/roms/proportional_fonts.rom b/roms/proportional_fonts.rom
deleted file mode 100644
index ff8291b..0000000
--- a/roms/proportional_fonts.rom
+++ /dev/null
Binary files differ
diff --git a/roms/screen.rom b/roms/screen.rom
deleted file mode 100644
index 6c62fc5..0000000
--- a/roms/screen.rom
+++ /dev/null
Binary files differ
diff --git a/roms/shapes.rom b/roms/shapes.rom
deleted file mode 100644
index 9e6acfb..0000000
--- a/roms/shapes.rom
+++ /dev/null
Binary files differ
diff --git a/roms/theme.rom b/roms/theme.rom
deleted file mode 100644
index 58d0e41..0000000
--- a/roms/theme.rom
+++ /dev/null
Binary files differ
diff --git a/roms/wallpaper.rom b/roms/wallpaper.rom
deleted file mode 100644
index 114f465..0000000
--- a/roms/wallpaper.rom
+++ /dev/null
Binary files differ
diff --git a/src/common.h b/src/common.h
index 0d6c89f..bbe6b52 100644
--- a/src/common.h
+++ b/src/common.h
@@ -419,12 +419,16 @@ dma_transfer_fill(void *dst, volatile u32 src, u32 count, int channel, u32 optio
419inline void 419inline void
420dma_copy(void *dst, const void *src, u32 size, int channel) { 420dma_copy(void *dst, const void *src, u32 size, int channel) {
421 dma_transfer_copy(dst, src, size / 4, channel, DMA_CHUNK_32 | DMA_ENABLE); 421 dma_transfer_copy(dst, src, size / 4, channel, DMA_CHUNK_32 | DMA_ENABLE);
422 // Stall for 2 cycles in case we call this function more than once.
423 asm("nop"); asm("nop");
422} 424}
423 425
424// Fill the dst location with the word set at src. 426// Fill the dst location with the word set at src.
425inline void 427inline void
426dma_fill(void *dst, vu32 src, u32 size, int channel) { 428dma_fill(void *dst, vu32 src, u32 size, int channel) {
427 dma_transfer_fill(dst, src, size / 4, channel, DMA_CHUNK_32 | DMA_ENABLE); 429 dma_transfer_fill(dst, src, size / 4, channel, DMA_CHUNK_32 | DMA_ENABLE);
430 // Stall for 2 cycles in case we call this function more than once.
431 asm("nop"); asm("nop");
428} 432}
429 433
430// 434//
@@ -731,6 +735,7 @@ wait_vsync(void) {
731#define LEN(ARR) (sizeof(ARR) / sizeof((ARR)[0])) 735#define LEN(ARR) (sizeof(ARR) / sizeof((ARR)[0]))
732 736
733// Fixed-point arithmetic for (i.P) numbers. 737// Fixed-point arithmetic for (i.P) numbers.
738#define FP_NUM(A,P) ((A) << (P))
734#define FP_MUL(A,B,P) (((A) * (B)) >> (P)) 739#define FP_MUL(A,B,P) (((A) * (B)) >> (P))
735#define FP_DIV(A,B,P) (((A) << (P)) / (B)) 740#define FP_DIV(A,B,P) (((A) << (P)) / (B))
736#define FP_LERP(Y0,Y1,X,P) ((Y0) + FP_MUL((X), ((Y1) - (Y0)), P)) 741#define FP_LERP(Y0,Y1,X,P) ((Y0) + FP_MUL((X), ((Y1) - (Y0)), P))
@@ -745,4 +750,10 @@ wait_vsync(void) {
745#define EWRAM_CODE __attribute__((section(".ewram"), long_call)) 750#define EWRAM_CODE __attribute__((section(".ewram"), long_call))
746#define EWRAM_BSS __attribute__((section(".sbss"))) 751#define EWRAM_BSS __attribute__((section(".sbss")))
747 752
753//
754// Compiler hints.
755//
756
757#define UNROLL_LOOPS __attribute__((optimize("unroll-loops")))
758
748#endif // GBAEXP_COMMON_H 759#endif // GBAEXP_COMMON_H
diff --git a/src/config.c b/src/config.c
new file mode 100644
index 0000000..278cf66
--- /dev/null
+++ b/src/config.c
@@ -0,0 +1,13 @@
1#if !defined(TEXT_MODE) || TEXT_MODE == 0
2#define TEXT_LAYER FG_BACK
3#else
4#define TEXT_LAYER BG_BACK
5#endif
6
7#ifndef CONTROL_METHODS
8#define CONTROL_METHODS CONTROL_CONTROLLER,CONTROL_MOUSE,CONTROL_KEYBOARD
9#endif
10
11#define PROF_ENABLE 0
12#define TEXT_DISABLE 1
13#define SOUND_DISABLE 0
diff --git a/src/debug.c b/src/debug.c
new file mode 100644
index 0000000..fe3077f
--- /dev/null
+++ b/src/debug.c
@@ -0,0 +1,206 @@
1typedef enum DebugFlags {
2 SHOW_ROM = (1 << 0),
3 SHOW_WST = (1 << 1),
4 SHOW_RST = (1 << 2),
5 SHOW_ZP = (1 << 3),
6 SHOW_DEV1 = (1 << 4),
7 SHOW_DEV2 = (1 << 6),
8} DebugFlags;
9
10void
11print_debug_info(u8 flags) {
12 txt_position(0, 0);
13 if (flags & SHOW_ROM) {
14 txt_printf("\nROM");
15 for (size_t i = 0; i < 128; i++) {
16 if (i % 8 == 0) {
17 txt_printf("\n");
18 }
19 if (i % 2 == 0) {
20 txt_printf(" ");
21 }
22 txt_printf("%02x", uxn_ram[i + PAGE_PROGRAM]);
23 }
24 txt_printf("\n");
25 }
26 if (flags & SHOW_DEV1) {
27 txt_printf("\nSYSTEM");
28 for (size_t i = 0; i < (0 + 16); i++) {
29 if (i % 8 == 0) {
30 txt_printf("\n");
31 }
32 txt_printf(" ");
33 txt_printf("%02x", device_data[i]);
34 }
35 txt_printf("\nCONSOLE");
36 for (size_t i = 0x10; i < (0x10 + 16); i++) {
37 if (i % 8 == 0) {
38 txt_printf("\n");
39 }
40 txt_printf(" ");
41 txt_printf("%02x", device_data[i]);
42 }
43 txt_printf("\nSCREEN");
44 for (size_t i = 0x20; i < (0x20 + 16); i++) {
45 if (i % 8 == 0) {
46 txt_printf("\n");
47 }
48 txt_printf(" ");
49 txt_printf("%02x", device_data[i]);
50 }
51 txt_printf("\nCONTROLLER");
52 for (size_t i = 0x80; i < (0x80 + 16); i++) {
53 if (i % 8 == 0) {
54 txt_printf("\n");
55 }
56 txt_printf(" ");
57 txt_printf("%02x", device_data[i]);
58 }
59 txt_printf("\nMOUSE");
60 for (size_t i = 0x90; i < (0x90 + 16); i++) {
61 if (i % 8 == 0) {
62 txt_printf("\n");
63 }
64 txt_printf(" ");
65 txt_printf("%02x", device_data[i]);
66 }
67 txt_printf("\nDATETIME");
68 for (size_t i = 0xc0; i < (0xc0 + 16); i++) {
69 if (i % 8 == 0) {
70 txt_printf("\n");
71 }
72 txt_printf(" ");
73 txt_printf("%02x", device_data[i]);
74 }
75 }
76 if (flags & SHOW_DEV2) {
77 txt_printf("\nAUDIO 1");
78 for (size_t i = 0x30; i < (0x30 + 16); i++) {
79 if (i % 8 == 0) {
80 txt_printf("\n");
81 }
82 txt_printf(" ");
83 txt_printf("%02x", device_data[i]);
84 }
85 txt_printf("\nAUDIO 2");
86 for (size_t i = 0x40; i < (0x40 + 16); i++) {
87 if (i % 8 == 0) {
88 txt_printf("\n");
89 }
90 txt_printf(" ");
91 txt_printf("%02x", device_data[i]);
92 }
93 txt_printf("\nAUDIO 3");
94 for (size_t i = 0x50; i < (0x50 + 16); i++) {
95 if (i % 8 == 0) {
96 txt_printf("\n");
97 }
98 txt_printf(" ");
99 txt_printf("%02x", device_data[i]);
100 }
101 txt_printf("\nAUDIO 4");
102 for (size_t i = 0x60; i < (0x60 + 16); i++) {
103 if (i % 8 == 0) {
104 txt_printf("\n");
105 }
106 txt_printf(" ");
107 txt_printf("%02x", device_data[i]);
108 }
109 txt_printf("\nFILE 1");
110 for (size_t i = 0xa0; i < (0xa0 + 16); i++) {
111 if (i % 8 == 0) {
112 txt_printf("\n");
113 }
114 txt_printf(" ");
115 txt_printf("%02x", device_data[i]);
116 }
117 txt_printf("\nFILE 2");
118 for (size_t i = 0xb0; i < (0xb0 + 16); i++) {
119 if (i % 8 == 0) {
120 txt_printf("\n");
121 }
122 txt_printf(" ");
123 txt_printf("%02x", device_data[i]);
124 }
125 }
126 if (flags & SHOW_WST) {
127 txt_printf("\nWST (");
128 txt_printf("SIZE: %d)", wst_ptr - (uintptr_t)wst);
129 for (size_t i = 0; i < 128; i++) {
130 if (i % 8 == 0) {
131 txt_printf("\n");
132 }
133 if (i >= (wst_ptr - (uintptr_t)wst)) {
134 txt_printf("%02x ", 0);
135 } else {
136 txt_printf("%02x ", wst[i]);
137 }
138 }
139 }
140 if (flags & SHOW_RST) {
141 txt_printf("RST (");
142 txt_printf("SIZE: %d)", rst_ptr - (uintptr_t)rst);
143 for (size_t i = 0; i < 128; i++) {
144 if (i % 8 == 0) {
145 txt_printf("\n");
146 }
147 if (i >= (rst_ptr - (uintptr_t)rst)) {
148 txt_printf("%02x ", 0);
149 } else {
150 txt_printf("%02x ", rst[i]);
151 }
152 }
153 }
154 if (flags & SHOW_ZP) {
155 txt_printf("RAM (ZP)\n");
156 for (size_t i = 0; i < 128; i++) {
157 if (i % 8 == 0) {
158 txt_printf("\n");
159 }
160 txt_printf("%02x ", uxn_ram[i]);
161 }
162 }
163 if (flags == 0) {
164 txt_printf("\nRAM (ZP)");
165 for (size_t i = 0; i < 32; i++) {
166 if (i % 8 == 0) {
167 txt_printf("\n");
168 }
169 if (i % 2 == 0) {
170 txt_printf(" ");
171 }
172 txt_printf("%02x", uxn_ram[i]);
173 }
174 txt_printf("\nWST (");
175 txt_printf("SIZE: %d)", wst_ptr - (uintptr_t)wst);
176 for (size_t i = 0; i < 32; i++) {
177 if (i % 8 == 0) {
178 txt_printf("\n");
179 }
180 if (i % 2 == 0) {
181 txt_printf(" ");
182 }
183 if (i >= (wst_ptr - (uintptr_t)wst)) {
184 txt_printf("%02x", 0);
185 } else {
186 txt_printf("%02x", wst[i]);
187 }
188 }
189 txt_printf("\nRST (");
190 txt_printf("SIZE: %d)", rst_ptr - (uintptr_t)rst);
191 for (size_t i = 0; i < 32; i++) {
192 if (i % 8 == 0) {
193 txt_printf("\n");
194 }
195 if (i % 2 == 0) {
196 txt_printf(" ");
197 }
198 if (i >= (rst_ptr - (uintptr_t)rst)) {
199 txt_printf("%02x", 0);
200 } else {
201 txt_printf("%02x", rst[i]);
202 }
203 }
204 }
205}
206
diff --git a/src/devices.c b/src/devices.c
new file mode 100644
index 0000000..6a1ed28
--- /dev/null
+++ b/src/devices.c
@@ -0,0 +1,303 @@
1static time_t seconds = 1693475007;
2
3#define RAM_PAGES 0x10
4
5void
6deo_console(u8 *dev, u8 port) {
7 switch(port) {
8 case 0x8:
9 txt_putc(dev[port]);
10 return;
11 case 0x9:
12 txt_printf("ERROR: %c");
13 txt_putc(dev[port]);
14 return;
15 }
16}
17
18u16
19dei_screen(u8 *dev, u8 port) {
20 switch(port) {
21 case 0x0:
22 case 0x8:
23 case 0xa:
24 case 0xc: return PEEK2(dev + port);
25 case 0x2: return SCREEN_WIDTH;
26 case 0x4: return SCREEN_HEIGHT;
27 default: return dev[port];
28 }
29}
30
31u16
32dei_mouse(u8 *dev, u8 port) {
33 switch(port) {
34 case 0x0:
35 case 0x2:
36 case 0x4:
37 case 0xa:
38 case 0xc: return PEEK2(dev + port);
39 default: return dev[port];
40 }
41}
42
43void
44deo_screen(u8 *dev, u8 port) {
45 switch(port) {
46 case 0xe: {
47 u8 ctrl = dev[0xe];
48 u8 color = ctrl & 0x3;
49 u16 x0 = PEEK2(dev + 0x8);
50 u16 y0 = PEEK2(dev + 0xa);
51 u8 *layer = (ctrl & 0x40) ? FG_BACK : BG_BACK;
52 if(ctrl & 0x80) {
53 u16 x1 = SCREEN_WIDTH - 1;
54 u16 y1 = SCREEN_HEIGHT - 1;
55 if(ctrl & 0x10) x1 = x0, x0 = 0;
56 if(ctrl & 0x20) y1 = y0, y0 = 0;
57 PROF(screen_fill(layer, x0, y0, x1, y1, color), ppu_fill_cycles);
58 } else {
59 PROF(ppu_pixel(layer, x0, y0, color), ppu_pixel_cycles);
60 if(dev[0x6] & 0x1) POKE2(dev + 0x8, x0 + 1); /* auto x+1 */
61 if(dev[0x6] & 0x2) POKE2(dev + 0xa, y0 + 1); /* auto y+1 */
62 }
63 break;
64 }
65 case 0xf: {
66 u8 ctrl = dev[0xf];
67 u8 move = dev[0x6];
68 u8 length = move >> 4;
69 u8 twobpp = !!(ctrl & 0x80);
70 u8 *layer = (dev[0xf] & 0x40) ? FG_BACK : BG_BACK;
71 u8 color = ctrl & 0xf;
72 u16 x = PEEK2(dev + 0x8), dx = (move & 0x1) << 3;
73 u16 y = PEEK2(dev + 0xa), dy = (move & 0x2) << 2;
74 u16 addr = PEEK2(dev + 0xc), addr_incr = (move & 0x4) << (1 + twobpp);
75 int flipx = (ctrl & 0x10), fx = flipx ? -1 : 1;
76 int flipy = (ctrl & 0x20), fy = flipy ? -1 : 1;
77 for(size_t i = 0; i <= length; i++) {
78 u8 *sprite = &uxn_ram[addr];
79 if (twobpp) {
80 PROF(ppu_2bpp(layer,
81 x + dy * i * fx,
82 y + dx * i * fy,
83 sprite,
84 color,
85 flipx, flipy), ppu_chr_cycles);
86 } else {
87 PROF(ppu_1bpp(layer,
88 x + dy * i * fx,
89 y + dx * i * fy,
90 sprite,
91 color,
92 flipx, flipy), ppu_icn_cycles);
93 }
94 addr += addr_incr;
95 }
96 if(move & 0x1) POKE2(dev + 0x8, x + dx * fx); /* auto x+8 */
97 if(move & 0x2) POKE2(dev + 0xa, y + dy * fy); /* auto y+8 */
98 if(move & 0x4) POKE2(dev + 0xc, addr); /* auto addr+length */
99 break;
100 }
101 }
102}
103
104void
105deo_system(u8 *dev, u8 port) {
106 switch(port) {
107 case 0x2: {
108 // Rom bank switching.
109 u16 addr = PEEK2(dev + port);
110 if(uxn_ram[addr] == 0x01) {
111 u16 length = PEEK2(uxn_ram + addr + 1);
112 u16 a_page = PEEK2(uxn_ram + addr + 1 + 2);
113 u16 a_addr = PEEK2(uxn_ram + addr + 1 + 4);
114 u16 b_page = PEEK2(uxn_ram + addr + 1 + 6);
115 u16 b_addr = PEEK2(uxn_ram + addr + 1 + 8);
116 u8 *ram = uxn_ram + (b_page % RAM_PAGES) * 0x10000;
117 u8 *rom = uxn_rom + (a_page % RAM_PAGES) * 0x10000 - PAGE_PROGRAM;
118 for(size_t i = 0; i < length; i++) {
119 ram[b_addr + i] = rom[a_addr + i];
120 }
121 }
122 } break;
123 case 0x4: {
124 // TODO: Set wst_ptr, but is it the offset instead?
125 } break;
126 case 0x5: {
127 // TODO: Set rst_ptr, but is it the offset instead?
128 } break;
129 case 0x8:
130 case 0x9:
131 case 0xa:
132 case 0xb:
133 case 0xc:
134 case 0xd: {
135 // Setup RGB palette.
136 putcolors(&dev[0x8]);
137 } break;
138 case 0xe: {
139 // TODO: System inspect.
140 } break;
141 }
142}
143
144u16
145dei_system(u8 *dev, u8 port) {
146 switch (port) {
147 case 0x0:
148 case 0x2:
149 case 0x6:
150 case 0x8:
151 case 0xa:
152 case 0xc: return PEEK2(dev + port);
153 case 0x4: {
154 // TODO: Return wst_ptr, but is it the offset instead?
155 } break;
156 case 0x5: {
157 // TODO: Return rst_ptr, but is it the offset instead?
158 } break;
159 }
160 return dev[port];
161}
162
163u16
164dei_datetime(u8 *dev, u8 port) {
165 struct tm *t = gmtime(&seconds);
166 switch(port) {
167 case 0x0: return (t->tm_year + 1900);
168 case 0x1: return (t->tm_year + 1900) >> 8;
169 case 0x2: return t->tm_mon;
170 case 0x3: return t->tm_mday;
171 case 0x4: return t->tm_hour;
172 case 0x5: return t->tm_min;
173 case 0x6: return t->tm_sec;
174 case 0x7: return t->tm_wday;
175 case 0x8: return t->tm_yday;
176 case 0x9: return t->tm_yday >> 8;
177 case 0xa: return t->tm_isdst;
178 }
179 return dev[port];
180}
181
182u16
183dei_audio(u8 *dev, u8 port) {
184 size_t idx = (dev - (device_data + 0x30)) / 16;
185 AudioChannel *c = &channels[idx];
186 switch(port) {
187 case 0x0:
188 case 0x8:
189 case 0xa:
190 case 0x2: // TODO: return the position
191 case 0xc: return PEEK2(dev + port);
192 // case 0x2: {
193 // POKE2(d + 0x2, c->pos);
194 // c->pos <<= 12; // fixed point.
195 // break;
196 // }
197 // case 0x4: return apu_get_vu(idx);
198 // TODO: return the current envelope loudness (0x00-0xff).
199 default: return dev[port];
200 }
201 return dev[port];
202}
203
204void
205deo_audio(u8 *dev, u8 port) {
206 size_t idx = (dev - (device_data + 0x30)) / 16;
207 txt_printf("IDX: %d\n", idx);
208 AudioChannel *c = &channels[idx];
209 if (port == 0xf) {
210 u16 length = 0;
211 u16 adsr = 0;
212 u16 addr = 0;
213 u8 pitch = dev[0xf] & 0x7f;
214 adsr = PEEK2(dev + 0x8);
215 length = PEEK2(dev + 0xa);
216 addr = PEEK2(dev + 0xc);
217 u8 *data = &uxn_ram[addr];
218 u32 vol = MAX(dev[0xe] >> 4, dev[0xe] & 0xf) * 4 / 3;
219 bool loop = !(dev[0xf] & 0x80);
220 update_channel(c, data, length, pitch, adsr, vol, loop);
221 }
222}
223
224u16
225dei_file(u8 *dev, u8 port) {
226 size_t idx = (dev - (device_data + 0xa0)) / 16;
227 UxnFile *c = &uxn_file[idx];
228 switch(port) {
229 case 0x0:
230 case 0x2:
231 case 0x4:
232 case 0x8:
233 case 0xa:
234 case 0xe: return PEEK2(dev + port);
235 case 0xc:
236 case 0xd: {
237 u16 res = file_read(c, &dev[port], 1);
238 POKE2(dev + 0x2, res);
239 return res;
240 }
241 }
242 return dev[port];
243}
244
245void
246deo_file(u8 *dev, u8 port) {
247 size_t idx = (dev - (device_data + 0xa0)) / 16;
248 u16 a, b, res;
249 UxnFile *f = &uxn_file[idx];
250 switch(port) {
251 case 0x5: {
252 a = PEEK2(dev + 0x4);
253 b = PEEK2(dev + 0xa);
254 if(b > 0x10000 - a) {
255 b = 0x10000 - a;
256 }
257 res = file_stat(f, &uxn_ram[a], b);
258 POKE2(dev + 0x2, res);
259 } break;
260 case 0x6: {
261 // TODO: no file deletion for now
262 // res = file_delete();
263 // POKE2(dev + 0x2, res);
264 } break;
265 case 0x9: {
266 a = PEEK2(dev + 0x8);
267 res = file_init(f, &uxn_ram[a]);
268 POKE2(dev + 0x2, res);
269 } break;
270 case 0xd: {
271 a = PEEK2(dev + 0xc);
272 b = PEEK2(dev + 0xa);
273 if(b > 0x10000 - a) {
274 b = 0x10000 - a;
275 }
276 res = file_read(f, &uxn_ram[a], b);
277 POKE2(dev + 0x2, res);
278 } break;
279 case 0xf: {
280 a = PEEK2(dev + 0xe);
281 b = PEEK2(dev + 0xa);
282 if(b > 0x10000 - a) {
283 b = 0x10000 - a;
284 }
285 res = file_write(f, &uxn_ram[a], b, dev[0x7]);
286 POKE2(dev + 0x2, res);
287 } break;
288 }
289}
290
291void
292deo_stub(u8 *dev, u8 port) {
293 (void)dev;
294 (void)port;
295}
296
297u16
298dei_stub(u8 *dev, u8 port) {
299 if (port == 0) {
300 return PEEK2(dev);
301 }
302 return dev[port];
303}
diff --git a/src/file.c b/src/file.c
index a45d59f..6dba2f9 100644
--- a/src/file.c
+++ b/src/file.c
@@ -13,65 +13,68 @@ WITH REGARD TO THIS SOFTWARE.
13 13
14#include "posprintf.h" 14#include "posprintf.h"
15 15
16static File f = {0}; 16typedef struct {
17static char *current_filename = ""; 17 File f;
18 char *filename;
19 enum {
20 IDLE,
21 FILE_READ,
22 FILE_WRITE,
23 } state;
24} UxnFile;
18 25
19static enum { 26static UxnFile uxn_file[2];
20 IDLE,
21 FILE_READ,
22 FILE_WRITE,
23} file_state;
24 27
25void 28void
26file_reset(void) { 29file_reset(UxnFile *f) {
27 f = (File){0}; 30 f->f = (File){0};
28 file_state = IDLE; 31 f->state = IDLE;
29} 32}
30 33
31u16 34u16
32file_init(void *filename) { 35file_init(UxnFile *f, void *filename) {
33 file_reset(); 36 file_reset(f);
34 current_filename = filename; 37 f->filename = filename;
35 return 0; 38 return 0;
36} 39}
37 40
38u16 41u16
39file_read(void *dest, u16 len) { 42file_read(UxnFile *f, void *dest, u16 len) {
40 if(file_state != FILE_READ) { 43 if(f->state != FILE_READ) {
41 file_reset(); 44 file_reset(f);
42 f = fs_open_file(current_filename, FS_OPEN_READ); 45 f->f = fs_open_file(f->filename, FS_OPEN_READ);
43 file_state = FILE_READ; 46 f->state = FILE_READ;
44 } 47 }
45 if (f.index == FS_NULL) { 48 if (f->f.index == FS_NULL) {
46 return 0; 49 return 0;
47 } 50 }
48 return fs_read(dest, len, &f); 51 return fs_read(dest, len, &f->f);
49} 52}
50 53
51u16 54u16
52file_write(void *src, u16 len, u8 flags) { 55file_write(UxnFile *f, void *src, u16 len, u8 flags) {
53 if(file_state != FILE_WRITE) { 56 if(f->state != FILE_WRITE) {
54 file_reset(); 57 file_reset(f);
55 OpenMode mode = (flags & 0x01) ? FS_OPEN_APPEND : FS_OPEN_WRITE; 58 OpenMode mode = (flags & 0x01) ? FS_OPEN_APPEND : FS_OPEN_WRITE;
56 f = fs_open_file(current_filename, mode); 59 f->f = fs_open_file(f->filename, mode);
57 file_state = FILE_WRITE; 60 f->state = FILE_WRITE;
58 } 61 }
59 if (f.index == FS_NULL) { 62 if (f->f.index == FS_NULL) {
60 return 0; 63 return 0;
61 } 64 }
62 return fs_write(src, len, &f); 65 return fs_write(src, len, &f->f);
63} 66}
64 67
65u16 68u16
66file_stat(void *dest, u16 len) { 69file_stat(UxnFile *f, void *dest, u16 len) {
67 if(len < strlen(current_filename) + 7) { 70 if(len < strlen(f->filename) + 7) {
68 return 0; 71 return 0;
69 } 72 }
70 if (f.index == FS_NULL) { 73 if (f->f.index == FS_NULL) {
71 posprintf(dest, "!!!! %s\n", current_filename); 74 posprintf(dest, "!!!! %s\n", f->filename);
72 } else { 75 } else {
73 u16 file_size = fs_file_size(&f); 76 u16 file_size = fs_file_size(&f->f);
74 posprintf(dest, "%04x %s\n", (unsigned int)file_size, current_filename); 77 posprintf(dest, "%04x %s\n", (unsigned int)file_size, f->filename);
75 } 78 }
76 return 0; 79 return 0;
77} 80}
diff --git a/src/input.c b/src/input.c
new file mode 100644
index 0000000..c78864d
--- /dev/null
+++ b/src/input.c
@@ -0,0 +1,203 @@
1typedef enum {
2 CONTROL_CONTROLLER,
3 CONTROL_MOUSE,
4 CONTROL_KEYBOARD,
5} ControlMethod;
6
7const ControlMethod ctrl_methods[] = {
8 CONTROL_METHODS
9};
10static ControlMethod ctrl_idx = 0;
11
12#define MOUSE_DELTA 1
13typedef struct Mouse {
14 int x;
15 int y;
16} Mouse;
17
18static Mouse mouse = {SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2};
19
20void
21handle_input() {
22 poll_keys();
23 if (key_tap(KEY_L) || key_tap(KEY_R)) {
24 // Reset control variables on method switch.
25 switch (ctrl_methods[ctrl_idx]) {
26 case CONTROL_CONTROLLER: {
27 u8 *d = &device_data[0x80];
28 d[2] = 0;
29 uxn_eval_asm(PEEK2(d));
30 d[3] = 0;
31 } break;
32 case CONTROL_MOUSE: {
33 u8 *d = &device_data[0x90];
34 d[6] = 0;
35 d[7] = 0;
36 POKE2(d + 0x2, -10);
37 POKE2(d + 0x4, -10);
38 uxn_eval_asm(PEEK2(d));
39 } break;
40 case CONTROL_KEYBOARD: {
41 toggle_keyboard();
42 } break;
43 }
44
45 // Update ctrl_idx.
46 ctrl_idx = (ctrl_idx + 1 > (int)LEN(ctrl_methods) - 1) ? 0 : ctrl_idx + 1;
47
48 // Initialize controller variables here.
49 if (ctrl_methods[ctrl_idx] == CONTROL_KEYBOARD) {
50 toggle_keyboard();
51 }
52 }
53
54 if (ctrl_methods[ctrl_idx] == CONTROL_CONTROLLER) {
55 u8 *d = &device_data[0x80];
56 // TODO: We don't need ifs if we use KEY_INPUTS directly and maybe just
57 // swap some things if needed.
58 u8 *flag = &d[2];
59 if (key_tap(KEY_A)) {
60 *flag |= 0x01;
61 } else {
62 *flag &= ~0x01;
63 }
64 if (key_tap(KEY_B)) {
65 *flag |= 0x02;
66 } else {
67 *flag &= ~0x02;
68 }
69 if (key_tap(KEY_SELECT)) {
70 *flag |= 0x04;
71 } else {
72 *flag &= ~0x04;
73 }
74 if (key_tap(KEY_START)) {
75 *flag |= 0x08;
76 } else {
77 *flag &= ~0x08;
78 }
79 if (key_tap(KEY_UP)) {
80 *flag |= 0x10;
81 } else {
82 *flag &= ~0x10;
83 }
84 if (key_tap(KEY_DOWN)) {
85 *flag |= 0x20;
86 } else {
87 *flag &= ~0x20;
88 }
89 if (key_tap(KEY_LEFT)) {
90 *flag |= 0x40;
91 } else {
92 *flag &= ~0x40;
93 }
94 if (key_tap(KEY_RIGHT)) {
95 *flag |= 0x80;
96 } else {
97 *flag &= ~0x80;
98 }
99
100 if (key_prev != key_curr) {
101 uxn_eval_asm(PEEK2(d));
102 }
103 d[3] = 0;
104 } else if (ctrl_methods[ctrl_idx] == CONTROL_MOUSE) {
105 u8 *d = &device_data[0x90];
106 // Detect "mouse key press".
107 u8 flag = d[6];
108 bool event = false;
109 if (key_tap(KEY_B)) {
110 event = true;
111 flag |= 0x01;
112 } else if (key_released(KEY_B)) {
113 event = true;
114 flag &= ~0x01;
115 }
116 if (key_tap(KEY_A)) {
117 event = true;
118 flag |= 0x10;
119 } else if (key_released(KEY_A)) {
120 event = true;
121 flag &= ~0x10;
122 }
123
124 // Handle chording.
125 d[6] = flag;
126 if(flag == 0x10 && (d[6] & 0x01)) {
127 d[7] = 0x01;
128 }
129 if(flag == 0x01 && (d[6] & 0x10)) {
130 d[7] = 0x10;
131 }
132
133 // Detect mouse movement.
134 if (key_pressed(KEY_UP)) {
135 event = true;
136 mouse.y = CLAMP(mouse.y - MOUSE_DELTA, 0, SCREEN_HEIGHT - 8);
137 } else if (key_pressed(KEY_DOWN)) {
138 event = true;
139 mouse.y = CLAMP(mouse.y + MOUSE_DELTA, 0, SCREEN_HEIGHT - 8);
140 }
141 if (key_pressed(KEY_LEFT)) {
142 event = true;
143 mouse.x = CLAMP(mouse.x - MOUSE_DELTA, 0, SCREEN_WIDTH - 8);
144 } else if (key_pressed(KEY_RIGHT)) {
145 event = true;
146 mouse.x = CLAMP(mouse.x + MOUSE_DELTA, 0, SCREEN_WIDTH - 8);
147 }
148
149 // Eval mouse.
150 POKE2(d + 0x2, mouse.x);
151 POKE2(d + 0x4, mouse.y);
152 if (event) {
153 uxn_eval_asm(PEEK2(d));
154 }
155 } else if (ctrl_methods[ctrl_idx] == CONTROL_KEYBOARD) {
156 u8 *d = &device_data[0x80];
157 if (key_tap(KEY_LEFT)) {
158 update_cursor(cursor_position - 1);
159 } else if (key_tap(KEY_RIGHT)) {
160 update_cursor(cursor_position + 1);
161 }
162 if (key_tap(KEY_UP) && cursor_position >= KEYBOARD_ROW_SIZE) {
163 update_cursor(cursor_position - KEYBOARD_ROW_SIZE);
164 } else if (key_tap(KEY_DOWN)
165 && cursor_position < LEN(keyboard) - KEYBOARD_ROW_SIZE) {
166 update_cursor(cursor_position + KEYBOARD_ROW_SIZE);
167 }
168 if (key_tap(KEY_B)) {
169 u8 symbol = keyboard[cursor_position].symbol;
170 switch (symbol) {
171 case 0x7f: {
172 // Backspace.
173 d[3] = 0x08;
174 } break;
175 case 0x14: {
176 // New line.
177 d[3] = 0x0d;
178 } break;
179 case 0x18: {
180 // Arrow up.
181 d[2] = 0x10;
182 } break;
183 case 0x19: {
184 // Arrow down.
185 d[2] = 0x20;
186 } break;
187 case 0x1b: {
188 // Arrow left.
189 d[2] = 0x40;
190 } break;
191 case 0x1a: {
192 // Arrow right.
193 d[2] = 0x80;
194 } break;
195 default: {
196 d[3] = symbol;
197 } break;
198 }
199 uxn_eval_asm(PEEK2(d));
200 d[3] = 0;
201 }
202 }
203}
diff --git a/src/main.c b/src/main.c
index 1acae1b..e688bb3 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,474 +1,79 @@
1/* 1/*
2Copyright (c) 2021 Bad Diode 2 Copyright (c) 2021 Bad Diode
3 3
4Permission to use, copy, modify, and distribute this software for any 4 Permission to use, copy, modify, and distribute this software for any
5purpose with or without fee is hereby granted, provided that the above 5 purpose with or without fee is hereby granted, provided that the above
6copyright notice and this permission notice appear in all copies. 6 copyright notice and this permission notice appear in all copies.
7 7
8THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9WITH REGARD TO THIS SOFTWARE. 9 WITH REGARD TO THIS SOFTWARE.
10*/ 10*/
11 11
12#include <string.h> 12#include <string.h>
13#include <time.h> 13#include <time.h>
14 14
15#include "common.h" 15#include "common.h"
16#include "bitmap.h"
17#include "filesystem.c" 16#include "filesystem.c"
18 17
18#include "uxn-core.c"
19
19#include "rom.c" 20#include "rom.c"
20#include "uxn.c"
21#include "ppu.c" 21#include "ppu.c"
22#include "apu.c" 22#include "apu.c"
23#include "file.c" 23#include "file.c"
24#include "text.h" 24#include "text.h"
25 25
26// 26#include "config.c"
27// Config parameters. 27#include "profiling.c"
28// 28#include "input.c"
29 29#include "devices.c"
30#if !defined(TEXT_MODE) || TEXT_MODE == 0 30#include "debug.c"
31#define TEXT_LAYER ppu.fg
32#else
33#define TEXT_LAYER ppu.bg
34#endif
35
36#ifndef CONTROL_METHODS
37#define CONTROL_METHODS CONTROL_CONTROLLER,CONTROL_MOUSE,CONTROL_KEYBOARD
38#endif
39
40#ifdef PROF_ENABLE
41#if PROF_ENABLE == 0
42#define PROF(F,VAR) (profile_start(),(F),(VAR) = profile_stop())
43#elif PROF_ENABLE == 1
44#define PROF(F,VAR) (profile_start(),(F),(VAR) = MAX(profile_stop(), (VAR)))
45#endif
46#ifndef PROF_SHOW_X
47#define PROF_SHOW_X 0
48#endif
49#ifndef PROF_SHOW_Y
50#define PROF_SHOW_Y 0
51#endif
52#define PROF_SHOW() \
53 do { \
54 txt_position((PROF_SHOW_X), (PROF_SHOW_Y));\
55 txt_printf("INPUT: %lu ", input_cycles);\
56 txt_position((PROF_SHOW_X), (PROF_SHOW_Y)+1);\
57 txt_printf("EVAL: %lu ", eval_cycles);\
58 txt_position((PROF_SHOW_X), (PROF_SHOW_Y)+2);\
59 txt_printf("FLIP: %lu ", flip_cycles);\
60 txt_position((PROF_SHOW_X), (PROF_SHOW_Y)+3);\
61 txt_printf("MIX: %lu ", mix_cycles);\
62 } while (0)
63#define PROF_INIT() \
64 u32 flip_cycles = 0;\
65 u32 eval_cycles = 0;\
66 u32 input_cycles = 0;\
67 u32 mix_cycles = 0;
68#else
69#define PROF(F,VAR) (F)
70#define PROF_SHOW()
71#define PROF_INIT()
72#endif
73
74static time_t seconds = 0;
75
76typedef enum {
77 CONTROL_CONTROLLER,
78 CONTROL_MOUSE,
79 CONTROL_KEYBOARD,
80} ControlMethod;
81
82const ControlMethod ctrl_methods[] = {
83 CONTROL_METHODS
84};
85static ControlMethod ctrl_idx = 0;
86
87#define MOUSE_DELTA 1
88typedef struct Mouse {
89 int x;
90 int y;
91} Mouse;
92
93static Ppu ppu;
94static Device *devscreen;
95static Device *devctrl;
96static Device *devmouse;
97static Device *devaudio;
98
99static Mouse mouse = {SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2};
100
101void
102nil_talk(Device *d, u8 b0, u8 w) {
103 (void)d;
104 (void)b0;
105 (void)w;
106}
107
108void
109console_talk(Device *d, u8 b0, u8 w) {
110 char stmp[2];
111 if(!w) {
112 return;
113 }
114 switch(b0) {
115 case 0x8: stmp[0] = d->dat[0x8]; stmp[1] = 0; txt_printf(stmp); break;
116 case 0x9: txt_printf("0x%02x", d->dat[0x9]); break;
117 case 0xb: txt_printf("0x%04x", mempeek16(d->dat, 0xa)); break;
118 case 0xd: txt_printf("%s", &d->mem[mempeek16(d->dat, 0xc)]); break;
119 }
120}
121
122void
123system_talk(Device *d, u8 b0, u8 w) {
124 if(!w) {
125 d->dat[0x2] = d->u->wst.ptr;
126 d->dat[0x3] = d->u->rst.ptr;
127 } else {
128 putcolors(&d->dat[0x8]);
129 }
130 (void)b0;
131}
132
133IWRAM_CODE
134void
135screen_talk(Device *d, u8 b0, u8 w) {
136 if (w) {
137 switch (b0) {
138 case 0x1: {
139 d->vector = mempeek16(d->dat, 0x0);
140 } break;
141 case 0xe: {
142 u16 x, y;
143 u8 layer = d->dat[0xe] & 0x40;
144 DEVPEEK16(x, 0x8);
145 DEVPEEK16(y, 0xa);
146 ppu_pixel(layer ? ppu.fg : ppu.bg, x, y, d->dat[0xe] & 0x3);
147 if(d->dat[0x6] & 0x01) DEVPOKE16(0x8, x + 1); /* auto x+1 */
148 if(d->dat[0x6] & 0x02) DEVPOKE16(0xa, y + 1); /* auto y+1 */
149 } break;
150 case 0xf: {
151 u16 x, y, dx, dy, addr;
152 u8 twobpp = !!(d->dat[0xf] & 0x80);
153 DEVPEEK16(x, 0x8);
154 DEVPEEK16(y, 0xa);
155 DEVPEEK16(addr, 0xc);
156 u8 n = d->dat[0x6] >> 4;
157 dx = (d->dat[0x6] & 0x01) << 3;
158 dy = (d->dat[0x6] & 0x02) << 2;
159 if(addr > 0x10000 - ((n + 1) << (3 + twobpp))) {
160 return;
161 }
162 u8 *layer = (d->dat[0xf] & 0x40) ? ppu.fg : ppu.bg;
163 u8 color = d->dat[0xf] & 0xf;
164 u8 flipx = d->dat[0xf] & 0x10;
165 u8 flipy = d->dat[0xf] & 0x20;
166 for(size_t i = 0; i <= n; i++) {
167 u8 *sprite = &d->mem[addr];
168 if (twobpp) {
169 ppu_2bpp(layer, x + dy * i, y + dx * i, sprite, color, flipx, flipy);
170 } else {
171 ppu_1bpp(layer, x + dy * i, y + dx * i, sprite, color, flipx, flipy);
172 }
173 addr += (d->dat[0x6] & 0x04) << (1 + twobpp);
174 }
175 DEVPOKE16(0xc, addr); /* auto addr+length */
176 DEVPOKE16(0x8, x + dx); /* auto x+8 */
177 DEVPOKE16(0xa, y + dy); /* auto y+8 */
178 } break;
179 default: break;
180 }
181 }
182}
183
184static void
185audio_talk(Device *d, u8 b0, u8 w) {
186 AudioChannel *c = &channels[d - devaudio];
187 if(!w) {
188 if(b0 == 0x2) {
189 mempoke16(d->dat, 0x2, c->pos);
190 c->pos <<= 12; // fixed point.
191 } else if(b0 == 0x4) {
192 // d->dat[0x4] = apu_get_vu(c);
193 }
194 } else if(b0 == 0xf) {
195 u16 length = mempeek16(d->dat, 0xa);
196 u8 *data = &d->mem[mempeek16(d->dat, 0xc)];
197 u8 pitch = d->dat[0xf] & 0x7f;
198 u16 adsr = mempeek16(d->dat, 0x8);
199 u32 vol = MAX(d->dat[0xe] >> 4, d->dat[0xe] & 0xf) * 4 / 3;
200 bool loop = !(d->dat[0xf] & 0x80);
201 update_channel(c, data, length, pitch, adsr, vol, loop);
202 }
203}
204
205void
206datetime_talk(Device *d, u8 b0, u8 w) {
207 (void)b0;
208 (void)w;
209 struct tm *t = gmtime(&seconds);
210 t->tm_year += 1900;
211 DEVPOKE16(0x0, t->tm_year);
212 d->dat[0x2] = t->tm_mon;
213 d->dat[0x3] = t->tm_mday;
214 d->dat[0x4] = t->tm_hour;
215 d->dat[0x5] = t->tm_min;
216 d->dat[0x6] = t->tm_sec;
217 d->dat[0x7] = t->tm_wday;
218 DEVPOKE16(0x08, t->tm_yday);
219 d->dat[0xa] = t->tm_isdst;
220}
221
222void
223file_talk(Device *d, u8 b0, u8 w) {
224 if (w) {
225 u16 a, b, res;
226 switch(b0) {
227 case 0x5: {
228 DEVPEEK16(a, 0x4);
229 DEVPEEK16(b, 0xa);
230 if(b > 0x10000 - a) {
231 b = 0x10000 - a;
232 }
233 res = file_stat(&d->mem[a], b);
234 DEVPOKE16(0x2, res);
235 } break;
236 case 0x6: {
237 // res = file_delete();
238 // DEVPOKE16(0x2, res);
239 } break;
240 case 0x9: {
241 DEVPEEK16(a, 0x8);
242 res = file_init(&d->mem[a]);
243 DEVPOKE16(0x2, res);
244 } break;
245 case 0xd: {
246 DEVPEEK16(a, 0xc);
247 DEVPEEK16(b, 0xa);
248 if(b > 0x10000 - a) {
249 b = 0x10000 - a;
250 }
251 res = file_read(&d->mem[a], b);
252 DEVPOKE16(0x2, res);
253 } break;
254 case 0xf: {
255 DEVPEEK16(a, 0xe);
256 DEVPEEK16(b, 0xa);
257 if(b > 0x10000 - a) {
258 b = 0x10000 - a;
259 }
260 res = file_write(&d->mem[a], b, d->dat[0x7]);
261 DEVPOKE16(0x2, res);
262 } break;
263 }
264 }
265}
266
267void
268init_uxn(Uxn *u) {
269 // Initialize PPU.
270 initppu(&ppu, 30, 20, 0);
271
272 // Enable sound.
273 init_sound();
274
275 // Copy rom to VM.
276 memcpy(u->ram.dat + PAGE_PROGRAM, uxn_rom, sizeof(uxn_rom));
277
278 // Prepare devices.
279 uxn_port(u, 0x0, "system", system_talk);
280 uxn_port(u, 0x1, "console", console_talk);
281 devscreen = uxn_port(u, 0x2, "screen", screen_talk);
282 devaudio = uxn_port(u, 0x3, "audio0", audio_talk);
283 uxn_port(u, 0x4, "audio1", audio_talk);
284 uxn_port(u, 0x5, "audio2", audio_talk);
285 uxn_port(u, 0x6, "audio3", audio_talk);
286 uxn_port(u, 0x7, "---", nil_talk);
287 devctrl = uxn_port(u, 0x8, "controller", nil_talk);
288 devmouse = uxn_port(u, 0x9, "mouse", nil_talk);
289 uxn_port(u, 0xa, "file1", file_talk);
290 uxn_port(u, 0xb, "file2", file_talk); // TODO: support second file device
291 uxn_port(u, 0xc, "datetime", datetime_talk);
292 uxn_port(u, 0xd, "---", nil_talk);
293 uxn_port(u, 0xe, "---", nil_talk);
294 uxn_port(u, 0xf, "---", nil_talk);
295 mempoke16(devscreen->dat, 2, ppu.hor * 8);
296 mempoke16(devscreen->dat, 4, ppu.ver * 8);
297}
298 31
299IWRAM_CODE
300void 32void
301handle_input(Uxn *u) { 33init_uxn() {
302 poll_keys(); 34 // Initialize uxn.
303 if (key_tap(KEY_SELECT)) { 35 u32 fill = 0;
304 // Reset control variables on method switch. 36 dma_fill(uxn_ram, fill, sizeof(uxn_ram), 3);
305 switch (ctrl_methods[ctrl_idx]) { 37 uxn_rom = _binary_build_uxn_rom_start;
306 case CONTROL_CONTROLLER: { 38 uxn_rom_size = (size_t)_binary_build_uxn_rom_size;
307 devctrl->dat[2] = 0; 39 size_t size = MIN(0x10000 - PAGE_PROGRAM, uxn_rom_size);
308 uxn_eval(u, mempeek16(devctrl->dat, 0)); 40 memcpy(uxn_ram + PAGE_PROGRAM, uxn_rom, size);
309 devctrl->dat[3] = 0; 41
310 } break; 42 // Initialize stack and device memory.
311 case CONTROL_MOUSE: { 43 for (size_t i = 0; i < 256; i++) {
312 devmouse->dat[6] = 0; 44 wst[i] = 0;
313 devmouse->dat[7] = 0; 45 rst[i] = 0;
314 mempoke16(devmouse->dat, 0x2, -10); 46 device_data[i] = 0;
315 mempoke16(devmouse->dat, 0x4, -10);
316 uxn_eval(u, mempeek16(devmouse->dat, 0));
317 } break;
318 case CONTROL_KEYBOARD: {
319 toggle_keyboard();
320 } break;
321 }
322
323 // Update ctrl_idx.
324 ctrl_idx = (ctrl_idx + 1 > (int)LEN(ctrl_methods) - 1) ? 0 : ctrl_idx + 1;
325
326 // Initialize controller variables here.
327 if (ctrl_methods[ctrl_idx] == CONTROL_KEYBOARD) {
328 toggle_keyboard();
329 }
330 } 47 }
331 48
332 if (ctrl_methods[ctrl_idx] == CONTROL_CONTROLLER) { 49 // Setup deo/dei maps.
333 // TODO: We don't need ifs if we use KEY_INPUTS directly and mayvbe just 50 for (size_t i = 0; i < 16; i++) {
334 // swap some things if needed. 51 deo_map[i] = (uintptr_t) deo_stub;
335 u8 *flag = &devctrl->dat[2]; 52 dei_map[i] = (uintptr_t) dei_stub;
336 if (key_pressed(KEY_A)) {
337 *flag |= 0x01;
338 } else {
339 *flag &= ~0x01;
340 }
341 if (key_pressed(KEY_B)) {
342 *flag |= 0x02;
343 } else {
344 *flag &= ~0x02;
345 }
346 if (key_pressed(KEY_L)) {
347 *flag |= 0x04;
348 } else {
349 *flag &= ~0x04;
350 }
351 if (key_pressed(KEY_R)) {
352 *flag |= 0x08;
353 } else {
354 *flag &= ~0x08;
355 }
356 if (key_pressed(KEY_UP)) {
357 *flag |= 0x10;
358 } else {
359 *flag &= ~0x10;
360 }
361 if (key_pressed(KEY_DOWN)) {
362 *flag |= 0x20;
363 } else {
364 *flag &= ~0x20;
365 }
366 if (key_pressed(KEY_LEFT)) {
367 *flag |= 0x40;
368 } else {
369 *flag &= ~0x40;
370 }
371 if (key_pressed(KEY_RIGHT)) {
372 *flag |= 0x80;
373 } else {
374 *flag &= ~0x80;
375 }
376
377 uxn_eval(u, mempeek16(devctrl->dat, 0));
378 devctrl->dat[3] = 0;
379 } else if (ctrl_methods[ctrl_idx] == CONTROL_MOUSE) {
380 // Detect "mouse key press".
381 u8 flag = devmouse->dat[6];
382 if (key_tap(KEY_B)) {
383 flag |= 0x01;
384 } else if (key_released(KEY_B)) {
385 flag &= ~0x01;
386 }
387 if (key_tap(KEY_A)) {
388 flag |= 0x10;
389 } else if (key_released(KEY_A)) {
390 flag &= ~0x10;
391 }
392
393 // Handle chording.
394 devmouse->dat[6] = flag;
395 if(flag == 0x10 && (devmouse->dat[6] & 0x01)) {
396 devmouse->dat[7] = 0x01;
397 }
398 if(flag == 0x01 && (devmouse->dat[6] & 0x10)) {
399 devmouse->dat[7] = 0x10;
400 }
401
402 // Detect mouse movement.
403 if (key_pressed(KEY_UP)) {
404 mouse.y = CLAMP(mouse.y - MOUSE_DELTA, 0, SCREEN_HEIGHT - 8);
405 } else if (key_pressed(KEY_DOWN)) {
406 mouse.y = CLAMP(mouse.y + MOUSE_DELTA, 0, SCREEN_HEIGHT - 8);
407 }
408 if (key_pressed(KEY_LEFT)) {
409 mouse.x = CLAMP(mouse.x - MOUSE_DELTA, 0, SCREEN_WIDTH - 8);
410 } else if (key_pressed(KEY_RIGHT)) {
411 mouse.x = CLAMP(mouse.x + MOUSE_DELTA, 0, SCREEN_WIDTH - 8);
412 }
413
414 // Eval mouse.
415 mempoke16(devmouse->dat, 0x2, mouse.x);
416 mempoke16(devmouse->dat, 0x4, mouse.y);
417 uxn_eval(u, mempeek16(devmouse->dat, 0));
418 } else if (ctrl_methods[ctrl_idx] == CONTROL_KEYBOARD) {
419 if (key_tap(KEY_LEFT)) {
420 update_cursor(cursor_position - 1);
421 } else if (key_tap(KEY_RIGHT)) {
422 update_cursor(cursor_position + 1);
423 }
424 if (key_tap(KEY_UP) && cursor_position >= KEYBOARD_ROW_SIZE) {
425 update_cursor(cursor_position - KEYBOARD_ROW_SIZE);
426 } else if (key_tap(KEY_DOWN)
427 && cursor_position < LEN(keyboard) - KEYBOARD_ROW_SIZE) {
428 update_cursor(cursor_position + KEYBOARD_ROW_SIZE);
429 }
430 if (key_tap(KEY_B)) {
431 u8 symbol = keyboard[cursor_position].symbol;
432 switch (symbol) {
433 case 0x7f: {
434 // Backspace.
435 devctrl->dat[3] = 0x08;
436 } break;
437 case 0x14: {
438 // New line.
439 devctrl->dat[3] = 0x0d;
440 } break;
441 case 0x18: {
442 // Arrow up.
443 devctrl->dat[2] = 0x10;
444 } break;
445 case 0x19: {
446 // Arrow down.
447 devctrl->dat[2] = 0x20;
448 } break;
449 case 0x1b: {
450 // Arrow left.
451 devctrl->dat[2] = 0x40;
452 } break;
453 case 0x1a: {
454 // Arrow right.
455 devctrl->dat[2] = 0x80;
456 } break;
457 default: {
458 devctrl->dat[3] = symbol;
459 } break;
460 }
461 uxn_eval(u, mempeek16(devctrl->dat, 0));
462 devctrl->dat[3] = 0;
463 }
464 } 53 }
54 deo_map[0x0] = (uintptr_t) deo_system;
55 dei_map[0x0] = (uintptr_t) dei_system;
56 deo_map[0x1] = (uintptr_t) deo_console;
57 deo_map[0x2] = (uintptr_t) deo_screen;
58 dei_map[0x2] = (uintptr_t) dei_screen;
59 deo_map[0x3] = (uintptr_t) deo_audio;
60 dei_map[0x3] = (uintptr_t) dei_audio;
61 deo_map[0x4] = (uintptr_t) deo_audio;
62 dei_map[0x4] = (uintptr_t) dei_audio;
63 deo_map[0x5] = (uintptr_t) deo_audio;
64 dei_map[0x5] = (uintptr_t) dei_audio;
65 deo_map[0x6] = (uintptr_t) deo_audio;
66 dei_map[0x6] = (uintptr_t) dei_audio;
67 deo_map[0xa] = (uintptr_t) deo_file;
68 dei_map[0xa] = (uintptr_t) dei_file;
69 deo_map[0xb] = (uintptr_t) deo_file;
70 dei_map[0xb] = (uintptr_t) dei_file;
71 dei_map[0xc] = (uintptr_t) dei_datetime;
72 dei_map[0x9] = (uintptr_t) dei_mouse;
465} 73}
466 74
467static Uxn u; 75int
468EWRAM_BSS 76main(void) {
469static u8 umem[KB(65)];
470
471int main(void) {
472 // Adjust system wait times. 77 // Adjust system wait times.
473 SYSTEM_WAIT = SYSTEM_WAIT_CARTRIDGE; 78 SYSTEM_WAIT = SYSTEM_WAIT_CARTRIDGE;
474 79
@@ -479,34 +84,42 @@ int main(void) {
479 irq_init(); 84 irq_init();
480 irs_set(IRQ_VBLANK, sound_vsync); 85 irs_set(IRQ_VBLANK, sound_vsync);
481 86
482 // Initialize VM. 87 // Initialize PPU.
483 dma_fill(&u, 0, sizeof(u), 3); 88 video_init();
484 u.ram.dat = umem;
485 init_uxn(&u);
486 89
487 // Initialize text engine. 90 // Initialize text engine.
91#if !defined(TEXT_DISABLE) || TEXT_DISABLE == 0 || PROF_ENABLE > 0
488 txt_init(1, TEXT_LAYER); 92 txt_init(1, TEXT_LAYER);
489 txt_position(0,0); 93 txt_position(0,0);
94#endif
95
96 // Initialize UXN.
97 init_uxn();
490 98
491 // Initialize sound mixer. 99 // Enable sound.
100#if !defined(SOUND_DISABLE) || SOUND_DISABLE == 0
492 init_sound(); 101 init_sound();
102#endif
493 103
494 // Main loop. 104 // Main loop.
495 uxn_eval(&u, PAGE_PROGRAM);
496 PROF_INIT();
497 u8 frame_counter = 0; 105 u8 frame_counter = 0;
106 PROF(uxn_eval_asm(PAGE_PROGRAM), eval_cycles);
498 while(true) { 107 while(true) {
499 bios_vblank_wait(); 108 bios_vblank_wait();
500 PROF(handle_input(&u), input_cycles); 109 FRAME_START();
501 PROF(uxn_eval(&u, mempeek16(devscreen->dat, 0)), eval_cycles); 110 PROF(handle_input(), input_cycles);
111 PROF(uxn_eval_asm(PEEK2(&device_data[0x20])), eval_cycles);
112#if !defined(SOUND_DISABLE) || SOUND_DISABLE == 0
502 PROF(sound_mix(), mix_cycles); 113 PROF(sound_mix(), mix_cycles);
114#endif
503 PROF_SHOW(); 115 PROF_SHOW();
504 PROF(flipbuf(&ppu), flip_cycles); 116 PROF(flipbuf(), flip_cycles);
505 frame_counter++; 117 frame_counter++;
506 if (frame_counter == 60) { 118 if (frame_counter == 60) {
507 seconds++; 119 seconds++;
508 frame_counter = 0; 120 frame_counter = 0;
509 } 121 }
122 FRAME_END();
510 } 123 }
511 124
512 return 0; 125 return 0;
diff --git a/src/ppu.c b/src/ppu.c
index 018555f..d22b3fd 100644
--- a/src/ppu.c
+++ b/src/ppu.c
@@ -15,6 +15,9 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
15WITH REGARD TO THIS SOFTWARE. 15WITH REGARD TO THIS SOFTWARE.
16*/ 16*/
17 17
18#define NEW_PPU 1
19#define FLIPBUF_DMA 1
20
18#define FG_FRONT ((u32*)(MEM_VRAM)) 21#define FG_FRONT ((u32*)(MEM_VRAM))
19#define BG_FRONT ((u32*)(MEM_VRAM + KB(20))) 22#define BG_FRONT ((u32*)(MEM_VRAM + KB(20)))
20#define FG_BACK ((u32*)(MEM_VRAM + KB(44))) 23#define FG_BACK ((u32*)(MEM_VRAM + KB(44)))
@@ -22,10 +25,23 @@ WITH REGARD TO THIS SOFTWARE.
22#define TILE_MAP ((u32*)(MEM_VRAM + KB(40))) 25#define TILE_MAP ((u32*)(MEM_VRAM + KB(40)))
23#define FONT_DATA ((u32*)(MEM_VRAM + KB(84))) 26#define FONT_DATA ((u32*)(MEM_VRAM + KB(84)))
24 27
28#ifdef DISABLE_BOUNDCHECK_SCREEN
29#define BOUNDCHECK_SCREEN(X,Y)
30#else
31#define BOUNDCHECK_SCREEN(X,Y) if ((X) >= SCREEN_WIDTH || (Y) >= SCREEN_HEIGHT) return;
32#endif
33
34// Swap A and B values without a tmp variable.
35#define SWAP(A, B) (((A) ^= (B)), ((B) ^= (A)), ((A) ^= (B)))
36
37// Swap A and B values to make sure A <= B.
38#define MAYBE_SWAP(A,B) if ((A) > (B)) { SWAP(A,B); }
39
25// Keyboard. 40// Keyboard.
26#define SPRITE_START_IDX 640 41#define SPRITE_START_IDX 640
27 42
28static u32 lut_2bpp[256] = { 43// TODO: Can we put these tables on the VRAM for extra speed?
44static u32 dec_byte_flip_x[256] = {
29 0x00000000, 0x00000001, 0x00000010, 0x00000011, 0x00000100, 45 0x00000000, 0x00000001, 0x00000010, 0x00000011, 0x00000100,
30 0x00000101, 0x00000110, 0x00000111, 0x00001000, 0x00001001, 46 0x00000101, 0x00000110, 0x00000111, 0x00001000, 0x00001001,
31 0x00001010, 0x00001011, 0x00001100, 0x00001101, 0x00001110, 47 0x00001010, 0x00001011, 0x00001100, 0x00001101, 0x00001110,
@@ -80,7 +96,7 @@ static u32 lut_2bpp[256] = {
80 0x11111111 96 0x11111111
81}; 97};
82 98
83static u32 lut2bpp_flipx[256] = { 99static u32 dec_byte[256] = {
84 0x00000000, 0x10000000, 0x01000000, 0x11000000, 0x00100000, 100 0x00000000, 0x10000000, 0x01000000, 0x11000000, 0x00100000,
85 0x10100000, 0x01100000, 0x11100000, 0x00010000, 0x10010000, 101 0x10100000, 0x01100000, 0x11100000, 0x00010000, 0x10010000,
86 0x01010000, 0x11010000, 0x00110000, 0x10110000, 0x01110000, 102 0x01010000, 0x11010000, 0x00110000, 0x10110000, 0x01110000,
@@ -135,54 +151,186 @@ static u32 lut2bpp_flipx[256] = {
135 0x11111111 151 0x11111111
136}; 152};
137 153
154// Blending table
155//
156// | BLEND BITS | COLOR
157// CLR | 0 0 0 0 | 0 1 2 3 T
158// ----+-------------+----------
159// 0x0 | 0 0 0 0 | 0 0 1 2 1
160// 0x1 | 0 0 0 1 | 0 1 2 3 1
161// 0x2 | 0 0 1 0 | 0 2 3 1 1
162// 0x3 | 0 0 1 1 | 0 3 1 2 1
163// 0x4 | 0 1 0 0 | 1 0 1 2 1
164// 0x5 | 0 1 0 1 | * 1 2 3 0
165// 0x6 | 0 1 1 0 | 1 2 3 1 1
166// 0x7 | 0 1 1 1 | 1 3 1 2 1
167// 0x8 | 1 0 0 0 | 2 0 1 2 1
168// 0x9 | 1 0 0 1 | 2 1 2 3 1
169// 0xA | 1 0 1 0 | * 2 3 1 0
170// 0xB | 1 0 1 1 | 2 3 1 2 1
171// 0xC | 1 1 0 0 | 3 0 1 2 1
172// 0xD | 1 1 0 1 | 3 1 2 3 1
173// 0xE | 1 1 1 0 | 3 2 3 1 1
174// 0xF | 1 1 1 1 | * 3 1 2 0
175// ----+-------------+----------
176//
177// Colors 0x5, 0xA and 0xF have transparent background and must be dealt
178// with separately, blending color 0 with existing data in that pixel.
179//
180// We need to do the following:
181//
182// 1. Extract the color row as u32 (4bpp).
183// 2. Split the row into each of its colors.
184// 3. Multiply based on the table, for example for color blend 2: 0123 -> 0231
185// 4. Obtain final color by ORing the colors from each channel.
186//
187// clr0 = blending[0][clr];
188// clr1 = blending[1][clr];
189// clr2 = blending[2][clr];
190// clr3 = blending[3][clr];
191// color = 0x00112233; 0b 0000 0000 0001 0001 0010 0010 0011 0011 0x00112233
192// col1mask = (color & 0x11111111); 0b 0000 0000 0001 0001 0000 0000 0001 0001 0x00110011
193// col2mask = (color & 0x22222222) >> 1; 0b 0000 0000 0000 0000 0001 0001 0001 0001 0x00001111
194// col3mask = (col1mask & col2mask) * 0xF; 0b 0000 0000 0000 0000 0000 0000 1111 1111 0x000000FF
195// col1mask &= ~col3mask; 0b 0000 0000 0000 0000 0000 0000 0001 0001 0x00000011
196// col2mask &= ~col3mask; 0b 0000 0000 0000 0000 0001 0001 0000 0000 0x00001100
197// col3mask = (color & col3mask) & 0x11111111; 0b 0000 0000 0000 0000 0000 0000 0001 0001 0x00000011
198// col0mask = ~(col1mask | col2mask | col3mask) & 0x11111111; 0b 0001 0001 0000 0000 0000 0000 0000 0000 0x11000000
199// color = (clr0 * col0mask) |
200// (clr1 * col1mask) |
201// (clr2 * col2mask) |
202// (clr3 * col3mask);
203//
204// Note that in case of transparent nodes col0mask can be used to mask off the
205// bits we want to pull from the existing framebuffer.
206//
138static u8 blending[5][16] = { 207static u8 blending[5][16] = {
139 {0, 0, 0, 0, 1, 0, 1, 1, 2, 2, 0, 2, 3, 3, 3, 0}, 208 {0, 0, 0, 0, 1, 0, 1, 1, 2, 2, 0, 2, 3, 3, 3, 0}, // Color 0 map.
140 {0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3}, 209 {0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3}, // Color 1 map.
141 {1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1}, 210 {1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1}, // Color 2 map.
142 {2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2}, 211 {2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2}, // Color 3 map.
143 {1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0} 212 {1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0}, // Transparency marker.
144}; 213};
145 214
146static u32 dirty_tiles[21] = {0}; 215static u32 dirty_tiles[21] = {0};
147 216
148void 217void
149putcolors(u8 *addr) { 218putcolors(u8 *addr) {
150 int i; 219 for(size_t i = 0; i < 4; ++i) {
151 for(i = 0; i < 4; ++i) { 220 u8 r = (*(addr + 0 + i / 2) >> (!(i % 2) << 2)) & 0x0f;
152 u8 221 u8 g = (*(addr + 2 + i / 2) >> (!(i % 2) << 2)) & 0x0f;
153 r = (*(addr + i / 2) >> (!(i % 2) << 2)) & 0x0f, 222 u8 b = (*(addr + 4 + i / 2) >> (!(i % 2) << 2)) & 0x0f;
154 g = (*(addr + 2 + i / 2) >> (!(i % 2) << 2)) & 0x0f, 223 Color color = rgb15(
155 b = (*(addr + 4 + i / 2) >> (!(i % 2) << 2)) & 0x0f;
156 PAL_BUFFER_BG[i] = rgb15(
157 (r << 1) | (r >> 3), 224 (r << 1) | (r >> 3),
158 (g << 1) | (g >> 3), 225 (g << 1) | (g >> 3),
159 (b << 1) | (b >> 3)); 226 (b << 1) | (b >> 3));
160 for (size_t j = 0; j < 16; ++j) { 227 PAL_BUFFER_BG[i] = color;
161 PAL_BUFFER_SPRITES[i * 16 + j] = rgb15(
162 (r << 1) | (r >> 3),
163 (g << 1) | (g >> 3),
164 (b << 1) | (b >> 3));
165 }
166 } 228 }
167} 229}
168 230
169IWRAM_CODE 231IWRAM_CODE
170void 232void
171ppu_pixel(u32 *layer, u16 x, u16 y, u8 color) { 233ppu_pixel(u32 *layer, u16 x, u16 y, u8 clr) {
172 if (x >= SCREEN_WIDTH || y >= SCREEN_HEIGHT) return; 234 if (x > SCREEN_WIDTH || y > SCREEN_HEIGHT) return;
173 size_t tile_x = x / 8; 235 size_t tile_x = x / 8;
174 size_t tile_y = y / 8; 236 size_t tile_y = y / 8;
175 size_t start_col = x % 8; 237 size_t start_col = x % 8;
176 size_t start_row = y % 8; 238 size_t start_row = y % 8;
177 size_t pos = (start_row + ((tile_x + tile_y * 32) * 8)); 239 size_t shift_left = start_col * 4;
178 size_t shift = start_col * 4; 240 u32 *dst = &layer[start_row + (tile_x + tile_y * 32) * 8];
179 layer[pos] = (layer[pos] & (~(0xF << shift))) | (color << shift); 241 u32 mask = 0xF << shift_left;
242 *dst = (*dst & ~mask) | (clr << shift_left);
180 dirty_tiles[tile_y] |= 1 << tile_x; 243 dirty_tiles[tile_y] |= 1 << tile_x;
181} 244}
182 245
246static inline
247void
248redraw(void) {
249 for (size_t i = 0; i < 21; i++) {
250 dirty_tiles[i] = 0xFFFFFFFF;
251 }
252}
253
254IWRAM_CODE
255void clear_screen(u32 *layer, u8 clr) {
256 // We have to make sure we leave the last tile blank to use as alpha channel
257 // when moving the BG during double buffering in case we are using that.
258 dma_fill(layer, 0x11111111 * clr, KB(20) - 32, 3);
259 redraw();
260}
261
262IWRAM_CODE
263static inline
264void
265draw_hline(u32 *layer, size_t x0, size_t x1, size_t y0, u8 clr) {
266 BOUNDCHECK_SCREEN(x0, y0);
267 BOUNDCHECK_SCREEN(x1, y0);
268 // Find row positions for the given x/y coordinates.
269 size_t tile_x0 = x0 / 8;
270 size_t tile_x1 = x1 / 8;
271 size_t tile_y = y0 / 8;
272 size_t start_col = x0 % 8;
273 size_t end_col = x1 % 8;
274 size_t start_row = y0 % 8;
275 u32 dirtyflag = (1 << tile_x0) | (1 << tile_x1);
276
277 // Horizontal line. There are 3 cases:
278 // 1. Lines fit on a single tile.
279 // 2. Lines go through 2 tiles, both require partial row updates.
280 // 3. Lines go through 3 or more tiles, first and last tiles use
281 // partial row updates, rows in the middle can write the entire
282 // row.
283 size_t dtx = tile_x1 - tile_x0;
284 u32 *dst = &layer[start_row + (tile_x0 + tile_y * 32) * 8];
285 if (dtx < 1) {
286 size_t shift_left = start_col * 4;
287 size_t shift_right = (7 - end_col) * 4;
288 u32 mask = (0xFFFFFFFF >> shift_right) & (0xFFFFFFFF << shift_left);
289 u32 row = (0x11111111 * clr) & mask;
290 *dst = (*dst & ~mask) | row;
291 } else {
292 size_t shift_left = start_col * 4;
293 size_t shift_right = (7 - end_col) * 4;
294 u32 mask = 0xFFFFFFFF;
295 u32 row = 0x11111111 * clr;
296 *dst = (*dst & ~(mask << shift_left)) | (row << shift_left);
297 dst += 8;
298 for (size_t i = 1; i < dtx; i++) {
299 dirtyflag |= (1 << (tile_x0 + i));
300 *dst = row;
301 dst += 8;
302 }
303 *dst = (*dst & ~(mask >> shift_right)) | (row >> shift_right);
304 }
305
306 dirty_tiles[tile_y] |= dirtyflag;
307}
308
183IWRAM_CODE 309IWRAM_CODE
184void 310void
185ppu_1bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 color, u8 flipx, u8 flipy) { 311screen_fill(u32 *layer, u16 x0, u16 y0, u16 x1, u16 y1, u8 clr) {
312 MAYBE_SWAP(x0, x1);
313 MAYBE_SWAP(y0, y1);
314
315 // Special condition. If the screen is to be completely filled, use the DMA
316 // instead.
317 u16 max_width = SCREEN_WIDTH - 1;
318 u16 max_height = SCREEN_HEIGHT - 1;
319 if (x0 == 0 && x1 >= max_width && y0 == 0 && y1 >= max_height) {
320 clear_screen(layer, clr);
321 return;
322 }
323
324 // Drawline implementation.
325 for (size_t y = y0; y <= y1; y++) {
326 draw_hline(layer, x0, x1, y, clr);
327 }
328}
329
330#if NEW_PPU == 0
331IWRAM_CODE
332void
333ppu_1bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 clr, u8 flip_x, u8 flip_y) {
186 u8 sprline; 334 u8 sprline;
187 u16 v; 335 u16 v;
188 u32 dirtyflag = (1 << (x >> 3)) | (1 << ((x + 7) >> 3)); 336 u32 dirtyflag = (1 << (x >> 3)) | (1 << ((x + 7) >> 3));
@@ -190,21 +338,21 @@ ppu_1bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 color, u8 flipx, u8 flipy) {
190 u32 layerpos = ((y & 7) + (((x >> 3) + (y >> 3) * 32) * 8)); 338 u32 layerpos = ((y & 7) + (((x >> 3) + (y >> 3) * 32) * 8));
191 u32 *layerptr = &layer[layerpos]; 339 u32 *layerptr = &layer[layerpos];
192 u32 shift = (x & 7) << 2; 340 u32 shift = (x & 7) << 2;
193 u32 *lut_expand = flipx ? lut_2bpp : lut2bpp_flipx; 341 u32 *lut_expand = flip_x ? dec_byte_flip_x : dec_byte;
194 342
195 if (flipy) flipy = 7; 343 if (flip_y) flip_y = 7;
196 344
197 if (x >= SCREEN_WIDTH || y >= SCREEN_HEIGHT) return; 345 BOUNDCHECK_SCREEN(x, y);
198 346
199 if (blending[4][color]) { 347 if (blending[4][clr]) {
200 u64 mask = ~((u64)0xFFFFFFFF << shift); 348 u64 mask = ~((u64)0xFFFFFFFF << shift);
201 349
202 for (v = 0; v < 8; v++, layerptr++) { 350 for (v = 0; v < 8; v++, layerptr++) {
203 if ((y + v) >= SCREEN_HEIGHT) break; 351 if ((y + v) >= SCREEN_HEIGHT) break;
204 352
205 sprline = sprite[v ^ flipy]; 353 sprline = sprite[v ^ flip_y];
206 u64 data = (u64)(lut_expand[sprline] * (color & 3)) << shift; 354 u64 data = (u64)(lut_expand[sprline] * (clr & 3)) << shift;
207 data |= (u64)(lut_expand[sprline ^ 0xFF] * (color >> 2)) << shift; 355 data |= (u64)(lut_expand[sprline ^ 0xFF] * (clr >> 2)) << shift;
208 356
209 layerptr[0] = (layerptr[0] & mask) | data; 357 layerptr[0] = (layerptr[0] & mask) | data;
210 layerptr[8] = (layerptr[8] & (mask >> 32)) | (data >> 32); 358 layerptr[8] = (layerptr[8] & (mask >> 32)) | (data >> 32);
@@ -215,9 +363,9 @@ ppu_1bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 color, u8 flipx, u8 flipy) {
215 for (v = 0; v < 8; v++, layerptr++) { 363 for (v = 0; v < 8; v++, layerptr++) {
216 if ((y + v) >= SCREEN_HEIGHT) break; 364 if ((y + v) >= SCREEN_HEIGHT) break;
217 365
218 sprline = sprite[v ^ flipy]; 366 sprline = sprite[v ^ flip_y];
219 u64 mask = ~((u64)(lut_expand[sprline] * 0xF) << shift); 367 u64 mask = ~((u64)(lut_expand[sprline] * 0xF) << shift);
220 u64 data = (u64)(lut_expand[sprline] * (color & 3)) << shift; 368 u64 data = (u64)(lut_expand[sprline] * (clr & 3)) << shift;
221 369
222 layerptr[0] = (layerptr[0] & mask) | data; 370 layerptr[0] = (layerptr[0] & mask) | data;
223 layerptr[8] = (layerptr[8] & (mask >> 32)) | (data >> 32); 371 layerptr[8] = (layerptr[8] & (mask >> 32)) | (data >> 32);
@@ -230,10 +378,81 @@ ppu_1bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 color, u8 flipx, u8 flipy) {
230 dirty_tiles[(y + 7) >> 3] |= dirtyflag; 378 dirty_tiles[(y + 7) >> 3] |= dirtyflag;
231} 379}
232 380
381#else
233IWRAM_CODE 382IWRAM_CODE
383UNROLL_LOOPS
234void 384void
235ppu_2bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 color, 385ppu_1bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 clr, u8 flip_x, u8 flip_y) {
236 u8 flipx, u8 flipy) { 386 BOUNDCHECK_SCREEN(x, y);
387 size_t tile_x = x / 8;
388 size_t tile_y = y / 8;
389 size_t start_col = x % 8;
390 size_t start_row = y % 8;
391 size_t shift_left = start_col * 4;
392 size_t shift_right = (8 - start_col) * 4;
393 u32 dirtyflag = (1 << tile_x) | (1 << ((x + 7) >> 3));
394
395 u32 *dst = &layer[start_row + (tile_x + tile_y * 32) * 8];
396 u32 *lut = flip_x ? dec_byte_flip_x : dec_byte;
397 if (blending[4][clr]) {
398 u32 mask = 0xFFFFFFFF;
399 if (!flip_y) {
400 for(size_t v = 0; v < 8; v++, dst++) {
401 if ((y + v) >= SCREEN_HEIGHT) break;
402 u8 ch1 = sprite[v];
403 u32 color_1 = lut[ch1];
404 u32 color_2 = (color_1 ^ 0xFFFFFFFF) & 0x11111111;
405 u32 color = (color_1 * (clr & 3)) | (color_2 * (clr >> 2));
406 dst[0] = (dst[0] & ~(mask << shift_left)) | (color << shift_left);
407 dst[8] = (dst[8] & ~(mask >> shift_right)) | (color >> shift_right);
408 if ((start_row + v) == 7) dst += (32 - 1) * 8;
409 }
410 } else {
411 for(size_t v = 0; v < 8; v++, dst++) {
412 if ((y + v) >= SCREEN_HEIGHT) break;
413 u8 ch1 = sprite[(7 - v)];
414 u32 color_1 = lut[ch1];
415 u32 color_2 = (color_1 ^ 0xFFFFFFFF) & 0x11111111;
416 u32 color = (color_1 * (clr & 3)) | (color_2 * (clr >> 2));
417 dst[0] = (dst[0] & ~(mask << shift_left)) | (color << shift_left);
418 dst[8] = (dst[8] & ~(mask >> shift_right)) | (color >> shift_right);
419 if ((start_row + v) == 7) dst += (32 - 1) * 8;
420 }
421 }
422 } else {
423 if (!flip_y) {
424 for(size_t v = 0; v < 8; v++, dst++) {
425 if ((y + v) >= SCREEN_HEIGHT) break;
426 u8 ch1 = sprite[v];
427 u32 color= lut[ch1];
428 u32 mask = color * 0xF;
429 color *= clr & 3;
430 dst[0] = (dst[0] & ~(mask << shift_left)) | (color << shift_left);
431 dst[8] = (dst[8] & ~(mask >> shift_right)) | (color >> shift_right);
432 if ((start_row + v) == 7) dst += (32 - 1) * 8;
433 }
434 } else {
435 for(size_t v = 0; v < 8; v++, dst++) {
436 if ((y + v) >= SCREEN_HEIGHT) break;
437 u8 ch1 = sprite[(7 - v)];
438 u32 color= lut[ch1];
439 u32 mask = color * 0xF;
440 color *= clr & 3;
441 dst[0] = (dst[0] & ~(mask << shift_left)) | (color << shift_left);
442 dst[8] = (dst[8] & ~(mask >> shift_right)) | (color >> shift_right);
443 if ((start_row + v) == 7) dst += (32 - 1) * 8;
444 }
445 }
446 }
447 dirty_tiles[y >> 3] |= dirtyflag;
448 dirty_tiles[(y + 7) >> 3] |= dirtyflag;
449}
450#endif
451
452#if NEW_PPU == 0
453IWRAM_CODE
454void
455ppu_2bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 color, u8 flip_x, u8 flip_y) {
237 u8 sprline1, sprline2; 456 u8 sprline1, sprline2;
238 u8 xrightedge = x < ((32 - 1) * 8); 457 u8 xrightedge = x < ((32 - 1) * 8);
239 u16 v, h; 458 u16 v, h;
@@ -243,20 +462,19 @@ ppu_2bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 color,
243 u32 *layerptr = &layer[layerpos]; 462 u32 *layerptr = &layer[layerpos];
244 u32 shift = (x & 7) << 2; 463 u32 shift = (x & 7) << 2;
245 464
246 if (flipy) flipy = 7; 465 if (flip_y) flip_y = 7;
247 466
248 if (x >= SCREEN_WIDTH || y >= SCREEN_HEIGHT) return; 467 BOUNDCHECK_SCREEN(x, y);
249 468
250 if (color == 1) { 469 if (color == 1) {
251 u32 *lut_expand = flipx ? lut_2bpp : lut2bpp_flipx; 470 u32 *lut_expand = flip_x ? dec_byte_flip_x : dec_byte;
252 u64 mask = ~((u64)0xFFFFFFFF << shift); 471 u64 mask = ~((u64)0xFFFFFFFF << shift);
253 472
254 for (v = 0; v < 8; v++, layerptr++) { 473 for (v = 0; v < 8; v++, layerptr++) {
255 if ((y + v) >= (24 * 8)) break; 474 if ((y + v) >= (24 * 8)) break;
256 475
257 sprline1 = sprite[v ^ flipy]; 476 sprline1 = sprite[v ^ flip_y];
258 sprline2 = sprite[(v ^ flipy) | 8]; 477 sprline2 = sprite[(v ^ flip_y) | 8];
259
260 u32 data32 = (lut_expand[sprline1]) | (lut_expand[sprline2] << 1); 478 u32 data32 = (lut_expand[sprline1]) | (lut_expand[sprline2] << 1);
261 u64 data = ((u64) (data32 & 0x33333333)) << shift; 479 u64 data = ((u64) (data32 & 0x33333333)) << shift;
262 480
@@ -271,11 +489,11 @@ ppu_2bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 color,
271 for (v = 0; v < 8; v++, layerptr++) { 489 for (v = 0; v < 8; v++, layerptr++) {
272 if ((y + v) >= (24 * 8)) break; 490 if ((y + v) >= (24 * 8)) break;
273 491
274 u8 ch1 = sprite[v ^ flipy]; 492 u8 ch1 = sprite[v ^ flip_y];
275 u8 ch2 = sprite[(v ^ flipy) | 8]; 493 u8 ch2 = sprite[(v ^ flip_y) | 8];
276 u32 data32 = 0; 494 u32 data32 = 0;
277 495
278 if (!flipx) { 496 if (!flip_x) {
279 for (h = 0; h < 8; h++) { 497 for (h = 0; h < 8; h++) {
280 data32 <<= 4; 498 data32 <<= 4;
281 499
@@ -306,12 +524,12 @@ ppu_2bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 color,
306 for (v = 0; v < 8; v++, layerptr++) { 524 for (v = 0; v < 8; v++, layerptr++) {
307 if ((y + v) >= (24 * 8)) break; 525 if ((y + v) >= (24 * 8)) break;
308 526
309 u8 ch1 = sprite[v ^ flipy]; 527 u8 ch1 = sprite[v ^ flip_y];
310 u8 ch2 = sprite[(v ^ flipy) | 8]; 528 u8 ch2 = sprite[(v ^ flip_y) | 8];
311 u32 data32 = 0; 529 u32 data32 = 0;
312 u32 mask32 = 0; 530 u32 mask32 = 0;
313 531
314 if (!flipx) { 532 if (!flip_x) {
315 for (h = 0; h < 8; h++) { 533 for (h = 0; h < 8; h++) {
316 data32 <<= 4; mask32 <<= 4; 534 data32 <<= 4; mask32 <<= 4;
317 535
@@ -350,6 +568,143 @@ ppu_2bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 color,
350 dirty_tiles[y >> 3] |= dirtyflag; 568 dirty_tiles[y >> 3] |= dirtyflag;
351 dirty_tiles[(y + 7) >> 3] |= dirtyflag; 569 dirty_tiles[(y + 7) >> 3] |= dirtyflag;
352} 570}
571#else
572IWRAM_CODE
573UNROLL_LOOPS
574void
575ppu_2bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 clr, u8 flip_x, u8 flip_y) {
576 BOUNDCHECK_SCREEN(x, y);
577 size_t tile_x = x / 8;
578 size_t tile_y = y / 8;
579 size_t start_col = x % 8;
580 size_t start_row = y % 8;
581 size_t shift_left = start_col * 4;
582 size_t shift_right = (8 - start_col) * 4;
583 u32 dirtyflag = (1 << tile_x) | (1 << ((x + 7) >> 3));
584 u32 *dst = &layer[start_row + (tile_x + tile_y * 32) * 8];
585 u32 *lut = flip_x ? dec_byte_flip_x : dec_byte;
586 if (clr == 1) {
587 u32 mask = 0xFFFFFFFF;
588 if (!flip_y) {
589 for(size_t v = 0; v < 8; v++, dst++) {
590 if ((y + v) >= SCREEN_HEIGHT) break;
591 u8 ch1 = sprite[v];
592 u8 ch2 = sprite[v | 8];
593 u32 color = lut[ch1] | (lut[ch2] << 1);
594 dst[0] = (dst[0] & ~(mask << shift_left)) | (color << shift_left);
595 dst[8] = (dst[8] & ~(mask >> shift_right)) | (color >> shift_right);
596 if ((start_row + v) == 7) dst += (32 - 1) * 8;
597 }
598 } else {
599 for(size_t v = 0; v < 8; v++, dst++) {
600 if ((y + v) >= SCREEN_HEIGHT) break;
601 u8 ch1 = sprite[(7 - v)];
602 u8 ch2 = sprite[(7 - v) | 8];
603 u32 color = lut[ch1] | (lut[ch2] << 1);
604 dst[0] = (dst[0] & ~(mask << shift_left)) | (color << shift_left);
605 dst[8] = (dst[8] & ~(mask >> shift_right)) | (color >> shift_right);
606 if ((start_row + v) == 7) dst += (32 - 1) * 8;
607 }
608 }
609 } else if (blending[4][clr]) {
610 u32 mask = 0xFFFFFFFF;
611 u8 clr0 = blending[0][clr];
612 u8 clr1 = blending[1][clr];
613 u8 clr2 = blending[2][clr];
614 u8 clr3 = blending[3][clr];
615 if (!flip_y) {
616 for(size_t v = 0; v < 8; v++, dst++) {
617 if ((y + v) >= SCREEN_HEIGHT) break;
618 u8 ch1 = sprite[v];
619 u8 ch2 = sprite[v | 8];
620 u32 color = lut[ch1] | (lut[ch2] << 1);
621 u32 col1mask = (color & 0x11111111);
622 u32 col2mask = (color & 0x22222222) >> 1;
623 u32 col3mask = (col1mask & col2mask) * 0xF;
624 col1mask &= ~col3mask;
625 col2mask &= ~col3mask;
626 col3mask = (color & col3mask) & 0x11111111;
627 u32 col0mask = ~(col1mask | col2mask | col3mask) & 0x11111111;
628 color = (clr0 * col0mask) |
629 (clr1 * col1mask) |
630 (clr2 * col2mask) |
631 (clr3 * col3mask);
632 dst[0] = (dst[0] & ~(mask << shift_left)) | (color << shift_left);
633 dst[8] = (dst[8] & ~(mask >> shift_right)) | (color >> shift_right);
634 if ((start_row + v) == 7) dst += (32 - 1) * 8;
635 }
636 } else {
637 for(size_t v = 0; v < 8; v++, dst++) {
638 if ((y + v) >= SCREEN_HEIGHT) break;
639 u8 ch1 = sprite[(7 - v)];
640 u8 ch2 = sprite[(7 - v) | 8];
641 u32 color = lut[ch1] | (lut[ch2] << 1);
642 u32 col1mask = (color & 0x11111111);
643 u32 col2mask = (color & 0x22222222) >> 1;
644 u32 col3mask = (col1mask & col2mask) * 0xF;
645 col1mask &= ~col3mask;
646 col2mask &= ~col3mask;
647 col3mask = (color & col3mask) & 0x11111111;
648 u32 col0mask = ~(col1mask | col2mask | col3mask) & 0x11111111;
649 color = (clr0 * col0mask) |
650 (clr1 * col1mask) |
651 (clr2 * col2mask) |
652 (clr3 * col3mask);
653 dst[0] = (dst[0] & ~(mask << shift_left)) | (color << shift_left);
654 dst[8] = (dst[8] & ~(mask >> shift_right)) | (color >> shift_right);
655 if ((start_row + v) == 7) dst += (32 - 1) * 8;
656 }
657 }
658 } else {
659 u8 clr1 = blending[1][clr];
660 u8 clr2 = blending[2][clr];
661 u8 clr3 = blending[3][clr];
662 if (!flip_y) {
663 for(size_t v = 0; v < 8; v++, dst++) {
664 if ((y + v) >= SCREEN_HEIGHT) break;
665 u8 ch1 = sprite[v];
666 u8 ch2 = sprite[v | 8];
667 u32 color = lut[ch1] | (lut[ch2] << 1);
668 u32 col1mask = (color & 0x11111111);
669 u32 col2mask = (color & 0x22222222) >> 1;
670 u32 col3mask = (col1mask & col2mask) * 0xF;
671 col1mask &= ~col3mask;
672 col2mask &= ~col3mask;
673 col3mask = (color & col3mask) & 0x11111111;
674 u32 mask = (col1mask | col2mask | col3mask) * 0xF;
675 color = (clr1 * col1mask) |
676 (clr2 * col2mask) |
677 (clr3 * col3mask);
678 dst[0] = (dst[0] & ~(mask << shift_left)) | (color << shift_left);
679 dst[8] = (dst[8] & ~(mask >> shift_right)) | (color >> shift_right);
680 if ((start_row + v) == 7) dst += (32 - 1) * 8;
681 }
682 } else {
683 for(size_t v = 0; v < 8; v++, dst++) {
684 if ((y + v) >= SCREEN_HEIGHT) break;
685 u8 ch1 = sprite[(7 - v)];
686 u8 ch2 = sprite[(7 - v) | 8];
687 u32 color = lut[ch1] | (lut[ch2] << 1);
688 u32 col1mask = (color & 0x11111111);
689 u32 col2mask = (color & 0x22222222) >> 1;
690 u32 col3mask = (col1mask & col2mask) * 0xF;
691 col1mask &= ~col3mask;
692 col2mask &= ~col3mask;
693 col3mask = (color & col3mask) & 0x11111111;
694 u32 mask = (col1mask | col2mask | col3mask) * 0xF;
695 color = (clr1 * col1mask) |
696 (clr2 * col2mask) |
697 (clr3 * col3mask);
698 dst[0] = (dst[0] & ~(mask << shift_left)) | (color << shift_left);
699 dst[8] = (dst[8] & ~(mask >> shift_right)) | (color >> shift_right);
700 if ((start_row + v) == 7) dst += (32 - 1) * 8;
701 }
702 }
703 }
704 dirty_tiles[y >> 3] |= dirtyflag;
705 dirty_tiles[(y + 7) >> 3] |= dirtyflag;
706}
707#endif
353 708
354IWRAM_CODE 709IWRAM_CODE
355void 710void
@@ -365,23 +720,32 @@ putfontchar(u32 *layer, u16 tile_x, u16 tile_y, u8 ch, u8 color) {
365 720
366IWRAM_CODE 721IWRAM_CODE
367void 722void
368flipbuf(Ppu *p) { 723flipbuf() {
369 Tile *mem_fg = FG_FRONT; 724 u32 *fg_back = FG_BACK;
370 Tile *mem_bg = BG_FRONT; 725 u32 *bg_back = BG_BACK;
726 u32 *bg_front = BG_FRONT;
727 u32 *fg_front = FG_FRONT;
371 for (size_t j = 0; j < 20; ++j) { 728 for (size_t j = 0; j < 20; ++j) {
372 if (dirty_tiles[j] == 0) { 729 if (dirty_tiles[j] == 0) {
373 continue; 730 continue;
374 } 731 }
375 732#if FLIPBUF_DMA == 1
733 u32 offset = j * 32 * 8;
734 dma_copy(fg_front + offset, fg_back + offset, 32 * 8 * 4, 3);
735 dma_copy(bg_front + offset, bg_back + offset, 32 * 8 * 4, 3);
736#else
376 size_t k = 1; 737 size_t k = 1;
377 for (size_t i = 0; i < 30; ++i, k <<= 1) { 738 for (size_t i = 0; i < 30; ++i, k <<= 1) {
378 if (dirty_tiles[j] & k) { 739 if (dirty_tiles[j] & k) {
379 Tile *tile_fg = p->fg; 740 Tile *mem_fg = FG_FRONT;
380 Tile *tile_bg = p->bg; 741 Tile *mem_bg = BG_FRONT;
742 Tile *tile_fg = FG_BACK;
743 Tile *tile_bg = BG_BACK;
381 mem_fg[i + j * 32] = tile_fg[i + j * 32]; 744 mem_fg[i + j * 32] = tile_fg[i + j * 32];
382 mem_bg[i + j * 32] = tile_bg[i + j * 32]; 745 mem_bg[i + j * 32] = tile_bg[i + j * 32];
383 } 746 }
384 } 747 }
748#endif
385 dirty_tiles[j] = 0; 749 dirty_tiles[j] = 0;
386 } 750 }
387} 751}
@@ -404,15 +768,25 @@ KeyboardChar keyboard[] = {
404 {0, 0, '0'}, {0, 0, '1'}, {0, 0, '2'}, {0, 0, '3'}, {0, 0, '4'}, {0, 0, '5'}, {0, 0, '6'}, {0, 0, '7'}, {0, 0, '8'}, {0, 0, '9'}, {0, 0, '~'}, {0, 0, 0x18}, 768 {0, 0, '0'}, {0, 0, '1'}, {0, 0, '2'}, {0, 0, '3'}, {0, 0, '4'}, {0, 0, '5'}, {0, 0, '6'}, {0, 0, '7'}, {0, 0, '8'}, {0, 0, '9'}, {0, 0, '~'}, {0, 0, 0x18},
405 {0, 0, 'a'}, {0, 0, 'b'}, {0, 0, 'c'}, {0, 0, 'd'}, {0, 0, 'e'}, {0, 0, 'f'}, {0, 0, 'g'}, {0, 0, 'h'}, {0, 0, 'i'}, {0, 0, 'j'}, {0, 0, '/'}, {0, 0, 0x19}, 769 {0, 0, 'a'}, {0, 0, 'b'}, {0, 0, 'c'}, {0, 0, 'd'}, {0, 0, 'e'}, {0, 0, 'f'}, {0, 0, 'g'}, {0, 0, 'h'}, {0, 0, 'i'}, {0, 0, 'j'}, {0, 0, '/'}, {0, 0, 0x19},
406 {0, 0, 'k'}, {0, 0, 'l'}, {0, 0, 'm'}, {0, 0, 'n'}, {0, 0, 'o'}, {0, 0, 'p'}, {0, 0, 'q'}, {0, 0, 'r'}, {0, 0, 's'}, {0, 0, 't'}, {0, 0, '\\'}, {0, 0, 0x1b}, 770 {0, 0, 'k'}, {0, 0, 'l'}, {0, 0, 'm'}, {0, 0, 'n'}, {0, 0, 'o'}, {0, 0, 'p'}, {0, 0, 'q'}, {0, 0, 'r'}, {0, 0, 's'}, {0, 0, 't'}, {0, 0, '\\'}, {0, 0, 0x1b},
407 {0, 0, 'u'}, {0, 0, 'v'}, {0, 0, 'w'}, {0, 0, 'x'}, {0, 0, 'y'}, {0, 0, 'z'}, {0, 0, ','}, {0, 0, '.'}, {0, 0, ';'}, {0, 0, ':'}, {0, 0, '_'}, {0, 0, 0x1a}, 771 {0, 0, 'u'}, {0, 0, 'v'}, {0, 0, 'w'}, {0, 0, 'x'}, {0, 0, 'y'}, {0, 0, 'z'}, {0, 0, ','}, {0, 0, '.'}, {0, 0, ';'}, {0, 0, ':'}, {0, 0, ' '}, {0, 0, 0x1a},
408}; 772};
409 773
774bool keyboard_on = false;
775
410void 776void
411toggle_keyboard(void) { 777toggle_keyboard(void) {
778 DISP_CTRL = DISP_MODE_0 | DISP_BG_0 | DISP_BG_1 | DISP_OBJ;
412 for (size_t i = 0; i < LEN(keyboard); ++i) { 779 for (size_t i = 0; i < LEN(keyboard); ++i) {
413 OBJ_ATTR_0(i) ^= OBJ_HIDDEN; 780 OBJ_ATTR_0(i) ^= OBJ_HIDDEN;
414 } 781 }
415 OBJ_ATTR_0(127) ^= OBJ_HIDDEN; 782 OBJ_ATTR_0(127) ^= OBJ_HIDDEN;
783 if (keyboard_on) {
784 keyboard_on = false;
785 DISP_CTRL = DISP_MODE_0 | DISP_BG_0 | DISP_BG_1;
786 } else {
787 keyboard_on = true;
788 DISP_CTRL = DISP_MODE_0 | DISP_BG_0 | DISP_BG_1 | DISP_OBJ;
789 }
416} 790}
417 791
418void 792void
@@ -424,16 +798,13 @@ update_cursor(u8 pos) {
424 | OBJ_X_COORD(keyboard[cursor_position].x); 798 | OBJ_X_COORD(keyboard[cursor_position].x);
425} 799}
426 800
427int 801void
428initppu(Ppu *p, u8 hor, u8 ver, u8 pad) { 802video_init() {
429 p->hor = hor; 803 // Clear VRAM.
430 p->ver = ver; 804 dma_fill((u32*)MEM_VRAM, 0, KB(96), 3);
431 p->pad = pad;
432 p->width = (8 * p->hor + p->pad * 2);
433 p->height = (8 * p->ver + p->pad * 2);
434 805
435 // Initialize display mode and bg palette. 806 // Initialize display mode and bg palette.
436 DISP_CTRL = DISP_MODE_0 | DISP_BG_0 | DISP_BG_1 | DISP_OBJ; 807 DISP_CTRL = DISP_MODE_0 | DISP_BG_0 | DISP_BG_1;
437 808
438 // Initialize backgrounds. 809 // Initialize backgrounds.
439 u8 cb_fg = 0; 810 u8 cb_fg = 0;
@@ -443,21 +814,6 @@ initppu(Ppu *p, u8 hor, u8 ver, u8 pad) {
443 BG_CTRL(0) = BG_CHARBLOCK(cb_fg) | BG_SCREENBLOCK(sb_fg) | BG_PRIORITY(1); 814 BG_CTRL(0) = BG_CHARBLOCK(cb_fg) | BG_SCREENBLOCK(sb_fg) | BG_PRIORITY(1);
444 BG_CTRL(1) = BG_CHARBLOCK(cb_bg) | BG_SCREENBLOCK(sb_bg) | BG_PRIORITY(2); 815 BG_CTRL(1) = BG_CHARBLOCK(cb_bg) | BG_SCREENBLOCK(sb_bg) | BG_PRIORITY(2);
445 816
446 // Clear front buffer.
447 p->fg = FG_FRONT;
448 p->bg = BG_FRONT;
449
450 // Use DMA to clear VRAM.
451 u32 fill = 0;
452 dma_fill(p->fg, fill, KB(20), 3);
453 dma_fill(p->bg, fill, KB(20), 3);
454
455 // Clear back buffer.
456 p->fg = FG_BACK;
457 p->bg = BG_BACK;
458 dma_fill(p->fg, fill, KB(20), 3);
459 dma_fill(p->bg, fill, KB(20), 3);
460
461 // Initialize default palette. 817 // Initialize default palette.
462 PAL_BUFFER_BG[0] = COLOR_BLACK; 818 PAL_BUFFER_BG[0] = COLOR_BLACK;
463 PAL_BUFFER_BG[1] = COLOR_WHITE; 819 PAL_BUFFER_BG[1] = COLOR_WHITE;
@@ -465,9 +821,9 @@ initppu(Ppu *p, u8 hor, u8 ver, u8 pad) {
465 PAL_BUFFER_BG[3] = COLOR_BLUE; 821 PAL_BUFFER_BG[3] = COLOR_BLUE;
466 for (size_t i = 0; i < 16; ++i) { 822 for (size_t i = 0; i < 16; ++i) {
467 PAL_BUFFER_SPRITES[i] = COLOR_BLACK; 823 PAL_BUFFER_SPRITES[i] = COLOR_BLACK;
468 PAL_BUFFER_SPRITES[1 * 16] = COLOR_WHITE; 824 PAL_BUFFER_SPRITES[i + 1 * 16] = COLOR_WHITE;
469 PAL_BUFFER_SPRITES[2 * 16] = COLOR_RED; 825 PAL_BUFFER_SPRITES[i + 2 * 16] = COLOR_RED;
470 PAL_BUFFER_SPRITES[3 * 16] = COLOR_BLUE; 826 PAL_BUFFER_SPRITES[i + 3 * 16] = COLOR_BLUE;
471 } 827 }
472 828
473 // Initialize background memory map. 829 // Initialize background memory map.
@@ -490,7 +846,7 @@ initppu(Ppu *p, u8 hor, u8 ver, u8 pad) {
490 keyboard[i].y = tile_y * 8; 846 keyboard[i].y = tile_y * 8;
491 OBJ_ATTR_0(i) = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(keyboard[i].y) | OBJ_HIDDEN; 847 OBJ_ATTR_0(i) = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(keyboard[i].y) | OBJ_HIDDEN;
492 OBJ_ATTR_1(i) = OBJ_SIZE_SMALL | OBJ_X_COORD(keyboard[i].x); 848 OBJ_ATTR_1(i) = OBJ_SIZE_SMALL | OBJ_X_COORD(keyboard[i].x);
493 OBJ_ATTR_2(i) = (SPRITE_START_IDX + keyboard[i].symbol) | OBJ_PAL_BANK(0); 849 OBJ_ATTR_2(i) = (SPRITE_START_IDX + keyboard[i].symbol) | OBJ_PAL_BANK(2);
494 tile_x++; 850 tile_x++;
495 if (tile_x - KEYBOARD_START_TILE_X >= KEYBOARD_ROW_SIZE) { 851 if (tile_x - KEYBOARD_START_TILE_X >= KEYBOARD_ROW_SIZE) {
496 tile_x = KEYBOARD_START_TILE_X; 852 tile_x = KEYBOARD_START_TILE_X;
@@ -500,6 +856,4 @@ initppu(Ppu *p, u8 hor, u8 ver, u8 pad) {
500 OBJ_ATTR_0(127) = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(keyboard[cursor_position].y) | OBJ_HIDDEN; 856 OBJ_ATTR_0(127) = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(keyboard[cursor_position].y) | OBJ_HIDDEN;
501 OBJ_ATTR_1(127) = OBJ_SIZE_SMALL | OBJ_X_COORD(keyboard[cursor_position].x); 857 OBJ_ATTR_1(127) = OBJ_SIZE_SMALL | OBJ_X_COORD(keyboard[cursor_position].x);
502 OBJ_ATTR_2(127) = (SPRITE_START_IDX + 0xdb) | OBJ_PAL_BANK(3); 858 OBJ_ATTR_2(127) = (SPRITE_START_IDX + 0xdb) | OBJ_PAL_BANK(3);
503
504 return 1;
505} 859}
diff --git a/src/ppu.h b/src/ppu.h
index b5eb250..bd9120c 100644
--- a/src/ppu.h
+++ b/src/ppu.h
@@ -17,12 +17,6 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
17WITH REGARD TO THIS SOFTWARE. 17WITH REGARD TO THIS SOFTWARE.
18*/ 18*/
19 19
20typedef struct Ppu {
21 u32 *bg, *fg;
22 u16 hor, ver, pad, width, height;
23} Ppu;
24
25int initppu(Ppu *p, u8 hor, u8 ver, u8 pad);
26void putcolors(u8 *addr); 20void putcolors(u8 *addr);
27void ppu_pixel(u32 *layer, u16 x, u16 y, u8 color); 21void ppu_pixel(u32 *layer, u16 x, u16 y, u8 color);
28void ppu_1bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 color, u8 flipx, u8 flipy); 22void ppu_1bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 color, u8 flipx, u8 flipy);
diff --git a/src/profiling.c b/src/profiling.c
new file mode 100644
index 0000000..2d230df
--- /dev/null
+++ b/src/profiling.c
@@ -0,0 +1,157 @@
1#ifndef PROF_ENABLE
2#define PROF_ENABLE 0
3#endif
4
5#if PROF_ENABLE > 0 && PROF_ENABLE < 3
6
7#ifndef PROF_N_FRAMES
8#define PROF_N_FRAMES 15
9#endif
10
11// Profile method 1: Average per N frames.
12#if PROF_ENABLE == 1
13#define TEXT_ENABLE 1
14#define PROF(F,VAR) \
15 do { \
16 u32 __tmp_prof = profile_measure();\
17 (F);\
18 (VAR) += profile_measure() - __tmp_prof;\
19 } while (0)
20
21// Profile method 2: Maximum in N frames.
22#elif PROF_ENABLE == 2
23#define TEXT_ENABLE 1
24#define PROF(F,VAR) \
25 do { \
26 u32 __tmp_prof = profile_measure();\
27 (F);\
28 (VAR) = MAX(profile_measure() - __tmp_prof, (VAR));\
29 } while (0)
30#endif
31
32#ifndef PROF_SHOW_X
33#define PROF_SHOW_X 0
34#endif
35#ifndef PROF_SHOW_Y
36#define PROF_SHOW_Y 0
37#endif
38
39#define PROF_SHOW() \
40 do { \
41 txt_position((PROF_SHOW_X), (PROF_SHOW_Y));\
42 txt_printf("INPUT %.8lu\n", avg_input_cycles);\
43 txt_printf("EVAL %.8lu\n", avg_eval_cycles);\
44 txt_printf("VIDEO\n");\
45 txt_printf(">PIX %.8lu\n", avg_ppu_pixel_cycles);\
46 txt_printf(">FILL %.8lu\n", avg_ppu_fill_cycles);\
47 txt_printf(">1BPP %.8lu\n", avg_ppu_icn_cycles);\
48 txt_printf(">2BPP %.8lu\n", avg_ppu_chr_cycles);\
49 txt_printf(">FLIP %.8lu\n", avg_flip_cycles);\
50 txt_printf("AUDIO %.8lu\n", avg_mix_cycles);\
51 txt_printf("TOTAL %.8lu\n", avg_frame_cycles);\
52 u32 frame_time =\
53 FP_DIV(\
54 FP_NUM(avg_frame_cycles + 1, 2),\
55 FP_NUM(2809, 2),\
56 2) * 166;\
57 u32 fps =\
58 FP_DIV(\
59 FP_NUM(280896 * 60, 2),\
60 FP_NUM(avg_frame_cycles + 1, 2),\
61 2);\
62 txt_printf("TIME %.8lu\n", frame_time >> 2);\
63 txt_printf("FPS %.8lu\n", (fps >> 2) + 1);\
64 screen_fill(BG_BACK, 0, 0, 8 * 16, 8 * 12, 2);\
65 } while (0)
66
67static u32 prof_frame_counter = 0;
68
69static u32 frame_cycles = 0;
70static u32 ppu_pixel_cycles = 0;
71static u32 ppu_fill_cycles = 0;
72static u32 ppu_chr_cycles = 0;
73static u32 ppu_icn_cycles = 0;
74static u32 flip_cycles = 0;
75static u32 eval_cycles = 0;
76static u32 input_cycles = 0;
77static u32 mix_cycles = 0;
78
79static u32 avg_ppu_pixel_cycles = 0;
80static u32 avg_ppu_fill_cycles = 0;
81static u32 avg_ppu_chr_cycles = 0;
82static u32 avg_ppu_icn_cycles = 0;
83static u32 avg_flip_cycles = 0;
84static u32 avg_eval_cycles = 0;
85static u32 avg_input_cycles = 0;
86static u32 avg_mix_cycles = 0;
87static u32 avg_frame_cycles = 0;
88
89#if PROF_ENABLE == 1
90#define FRAME_START()\
91 do { \
92 if (prof_frame_counter == PROF_N_FRAMES) {\
93 avg_ppu_pixel_cycles = ppu_pixel_cycles / prof_frame_counter;\
94 avg_ppu_fill_cycles = ppu_fill_cycles / prof_frame_counter;\
95 avg_ppu_chr_cycles = ppu_chr_cycles / prof_frame_counter;\
96 avg_ppu_icn_cycles = ppu_icn_cycles / prof_frame_counter;\
97 avg_flip_cycles = flip_cycles / prof_frame_counter;\
98 avg_eval_cycles = eval_cycles / prof_frame_counter;\
99 avg_input_cycles = input_cycles / prof_frame_counter;\
100 avg_mix_cycles = mix_cycles / prof_frame_counter;\
101 avg_frame_cycles = frame_cycles / prof_frame_counter;\
102 prof_frame_counter = 0;\
103 frame_cycles = 0;\
104 ppu_pixel_cycles = 0;\
105 ppu_fill_cycles = 0;\
106 ppu_chr_cycles = 0;\
107 ppu_icn_cycles = 0;\
108 flip_cycles = 0;\
109 eval_cycles = 0;\
110 input_cycles = 0;\
111 mix_cycles = 0;\
112 }\
113 profile_start();\
114 } while (0)
115#elif PROF_ENABLE == 2
116#define FRAME_START()\
117 do { \
118 if (prof_frame_counter == PROF_N_FRAMES) {\
119 avg_ppu_pixel_cycles = ppu_pixel_cycles;\
120 avg_ppu_fill_cycles = ppu_fill_cycles;\
121 avg_ppu_chr_cycles = ppu_chr_cycles;\
122 avg_ppu_icn_cycles = ppu_icn_cycles;\
123 avg_flip_cycles = flip_cycles;\
124 avg_eval_cycles = eval_cycles;\
125 avg_input_cycles = input_cycles;\
126 avg_mix_cycles = mix_cycles;\
127 avg_frame_cycles = frame_cycles / prof_frame_counter;\
128 prof_frame_counter = 0;\
129 frame_cycles = 0;\
130 ppu_pixel_cycles = 0;\
131 ppu_fill_cycles = 0;\
132 ppu_chr_cycles = 0;\
133 ppu_icn_cycles = 0;\
134 flip_cycles = 0;\
135 eval_cycles = 0;\
136 input_cycles = 0;\
137 mix_cycles = 0;\
138 }\
139 profile_start();\
140 } while (0)
141#endif
142
143#define FRAME_END() \
144 do { \
145 prof_frame_counter++;\
146 frame_cycles += profile_stop();\
147 } while (0)
148
149#else
150
151// No profiling.
152#define PROF(F,VAR) (F)
153#define PROF_SHOW()
154#define FRAME_START()
155#define FRAME_END()
156#endif
157
diff --git a/src/rom.c b/src/rom.c
new file mode 100644
index 0000000..01fd451
--- /dev/null
+++ b/src/rom.c
@@ -0,0 +1,5 @@
1extern u8 _binary_build_uxn_rom_start[];
2extern u8 _binary_build_uxn_rom_size[];
3
4u8 *uxn_rom;
5size_t uxn_rom_size;
diff --git a/src/uxn-core.c b/src/uxn-core.c
new file mode 100644
index 0000000..8a2c971
--- /dev/null
+++ b/src/uxn-core.c
@@ -0,0 +1,36 @@
1extern void uxn_eval_asm(u16 pc);
2
3// Stacks (On IWRAM).
4extern u8 wst[256];
5extern u8 rst[256];
6extern uintptr_t wst_ptr;
7extern uintptr_t rst_ptr;
8
9// DEO/DEI mapping functiosn and device data (On IWRAM).
10extern uintptr_t deo_map[16];
11extern uintptr_t dei_map[16];
12extern u8 device_data[256];
13
14// DEBUG: ONLY
15// extern u8 device_0[16];
16// extern u8 device_1[16];
17// extern u8 device_2[16];
18// extern u8 device_3[16];
19// extern u8 device_4[16];
20// extern u8 device_5[16];
21// extern u8 device_6[16];
22// extern u8 device_7[16];
23// extern u8 device_8[16];
24// extern u8 device_a[16];
25// extern u8 device_b[16];
26// extern u8 device_c[16];
27// extern u8 device_d[16];
28// extern u8 device_e[16];
29// extern u8 device_f[16];
30
31EWRAM_BSS
32u8 uxn_ram[KB(64)];
33
34#define PAGE_PROGRAM 0x0100
35#define POKE2(d, v) do { (d)[0] = (v) >> 8; (d)[1] = (v); } while(0)
36#define PEEK2(d) ((d)[0] << 8 | (d)[1])
diff --git a/src/uxn-core.s b/src/uxn-core.s
new file mode 100644
index 0000000..255bb99
--- /dev/null
+++ b/src/uxn-core.s
@@ -0,0 +1,2721 @@
1.file "uxn-core.s"
2.section .iwram, "ax", %progbits
3.extern uxn_ram
4.align
5
6@
7@ Core variables
8@
9
10.global wst
11wst: .space 256
12.global wst_ptr
13wst_ptr: .word wst
14
15.global rst
16rst: .space 256
17.global rst_ptr
18rst_ptr: .word rst
19
20@ UXN evaluation function.
21@
22@ r0: PC pointer (argument for this function is the offset from UXN RAM).
23@ r1: Stack pointer (wst).
24@ r2: Stack pointer (rst).
25@ r3-r6: Scratch registers.
26@ r7: Ram ptr.
27@
28.global uxn_eval_asm
29uxn_eval_asm:
30 @ Ensure PC is not null.
31 cmp r0, #0
32 bxeq lr
33
34 @ Initialization.
35 push {r4-r7}
36 ldr r1, wst_ptr
37 ldr r2, rst_ptr
38 ldr r7, =uxn_ram
39 add r0, r0, r7
40
41uxn_decode:
42 ldrb r3, [r0], #1 @ current OP value / table index
43
44 @ Decode OP based on table lookup.
45 adr r4, op_table @ decoding table
46 ldr r4, [r4, r3, lsl #2] @ op_table[idx * 4]
47 bx r4 @ op_table[idx * 4]()
48
49uxn_ret:
50 @ Update stack pointers and return.
51 adr r0, wst_ptr
52 str r1, [r0]
53 adr r0, rst_ptr
54 str r2, [r0]
55 pop {r4-r7}
56 bx lr
57
58@
59@ Macros.
60@
61
62.macro next a
63 ldrb \a, [r0], #1
64.endm
65
66.macro wpop8 a
67 ldrb \a, [r1, #-1]!
68.endm
69
70.macro wpop8s a
71 ldrsb \a, [r1, #-1]!
72.endm
73
74.macro wpop16 a, b
75 ldrb \a, [r1, #-1]!
76 ldrb \b, [r1, #-1]!
77 orr \a, \a, \b, lsl #8
78.endm
79
80.macro wpush8 a
81 strb \a, [r1], #1
82.endm
83
84.macro wpush16 a
85 strb \a, [r1, #1]
86 lsr \a, #8
87 strb \a, [r1], #2
88.endm
89
90.macro wpeek8 a, off
91 ldrb \a, [r1, \off]
92.endm
93
94.macro wpeek8s a, off
95 ldrsb \a, [r1, \off]
96.endm
97
98.macro wpeek16 a, b, offa, offb
99 ldrb \a, [r1, \offa]
100 ldrb \b, [r1, \offb]
101 orr \a, \a, \b, lsl #8
102.endm
103
104.macro rpop8 a
105 ldrb \a, [r2, #-1]!
106.endm
107
108.macro rpop8s a
109 ldrsb \a, [r2, #-1]!
110.endm
111
112.macro rpop16 a, b
113 ldrb \a, [r2, #-1]!
114 ldrb \b, [r2, #-1]!
115 orr \a, \a, \b, lsl #8
116.endm
117
118.macro rpush8 a
119 strb \a, [r2], #1
120.endm
121
122.macro rpush16 a
123 strb \a, [r2, #1]
124 lsr \a, #8
125 strb \a, [r2], #2
126.endm
127
128.macro rpeek8 a, off
129 ldrb \a, [r2, \off]
130.endm
131
132.macro rpeek8s a, off
133 ldrsb \a, [r2, \off]
134.endm
135
136.macro rpeek16 a, b, offa, offb
137 ldrb \a, [r2, \offa]
138 ldrb \b, [r2, \offb]
139 orr \a, \a, \b, lsl #8
140.endm
141
142.macro zsave8 a, off
143 strb \a, [r7, \off]
144.endm
145
146.macro zsave16 a, off
147 add \off, r7
148 strb \a, [\off, #1]
149 lsr \a, #8
150 strb \a, [\off]
151.endm
152
153.macro zload8 a, off
154 ldrb \a, [r7, \off]
155.endm
156
157.macro rload8 a, off
158 ldrb \a, [r0, \off]
159.endm
160
161.macro aload8 a, off
162 ldrb \a, [r7, \off]
163.endm
164
165.macro asave8 a, off
166 strb \a, [r7, \off]
167.endm
168
169.macro asave16 a, off
170 add \off, r7
171 strb \a, [\off, #1]
172 lsr \a, #8
173 strb \a, [\off]
174.endm
175
176.macro rsave8 a, off
177 strb \a, [r0, \off]
178.endm
179
180.macro rsave16 a, off
181 adds \off, r0
182 strb \a, [\off, #1]
183 lsr \a, #8
184 strb \a, [\off]
185.endm
186
187@
188@ OP table
189@
190
191op_table:
192 .word brk @ 0x00
193 .word inc @ 0x01
194 .word pop @ 0x02
195 .word nip @ 0x03
196 .word swp @ 0x04
197 .word rot @ 0x05
198 .word dup @ 0x06
199 .word ovr @ 0x07
200 .word equ @ 0x08
201 .word neq @ 0x09
202 .word gth @ 0x0a
203 .word lth @ 0x0b
204 .word jmp @ 0x0c
205 .word jcn @ 0x0d
206 .word jsr @ 0x0e
207 .word sth @ 0x0f
208 .word ldz @ 0x10
209 .word stz @ 0x11
210 .word ldr @ 0x12
211 .word str @ 0x13
212 .word lda @ 0x14
213 .word sta @ 0x15
214 .word dei @ 0x16
215 .word deo @ 0x17
216 .word add @ 0x18
217 .word sub @ 0x19
218 .word mul @ 0x1a
219 .word div @ 0x1b
220 .word and @ 0x1c
221 .word ora @ 0x1d
222 .word eor @ 0x1e
223 .word sft @ 0x1f
224 .word jci @ 0x20
225 .word inc2 @ 0x21
226 .word pop2 @ 0x22
227 .word nip2 @ 0x23
228 .word swp2 @ 0x24
229 .word rot2 @ 0x25
230 .word dup2 @ 0x26
231 .word ovr2 @ 0x27
232 .word equ2 @ 0x28
233 .word neq2 @ 0x29
234 .word gth2 @ 0x2a
235 .word lth2 @ 0x2b
236 .word jmp2 @ 0x2c
237 .word jcn2 @ 0x2d
238 .word jsr2 @ 0x2e
239 .word sth2 @ 0x2f
240 .word ldz2 @ 0x30
241 .word stz2 @ 0x31
242 .word ldr2 @ 0x32
243 .word str2 @ 0x33
244 .word lda2 @ 0x34
245 .word sta2 @ 0x35
246 .word dei2 @ 0x36
247 .word deo2 @ 0x37
248 .word add2 @ 0x38
249 .word sub2 @ 0x39
250 .word mul2 @ 0x3a
251 .word div2 @ 0x3b
252 .word and2 @ 0x3c
253 .word ora2 @ 0x3d
254 .word eor2 @ 0x3e
255 .word sft2 @ 0x3f
256 .word jmi @ 0x40
257 .word incr @ 0x41
258 .word popr @ 0x42
259 .word nipr @ 0x43
260 .word swpr @ 0x44
261 .word rotr @ 0x45
262 .word dupr @ 0x46
263 .word ovrr @ 0x47
264 .word equr @ 0x48
265 .word neqr @ 0x49
266 .word gthr @ 0x4a
267 .word lthr @ 0x4b
268 .word jmpr @ 0x4c
269 .word jcnr @ 0x4d
270 .word jsrr @ 0x4e
271 .word sthr @ 0x4f
272 .word ldzr @ 0x50
273 .word stzr @ 0x51
274 .word ldrr @ 0x52
275 .word strr @ 0x53
276 .word ldar @ 0x54
277 .word star @ 0x55
278 .word deir @ 0x56
279 .word deor @ 0x57
280 .word addr @ 0x58
281 .word subr @ 0x59
282 .word mulr @ 0x5a
283 .word divr @ 0x5b
284 .word andr @ 0x5c
285 .word orar @ 0x5d
286 .word eorr @ 0x5e
287 .word sftr @ 0x5f
288 .word jsi @ 0x60
289 .word inc2r @ 0x61
290 .word pop2r @ 0x62
291 .word nip2r @ 0x63
292 .word swp2r @ 0x64
293 .word rot2r @ 0x65
294 .word dup2r @ 0x66
295 .word ovr2r @ 0x67
296 .word equ2r @ 0x68
297 .word neq2r @ 0x69
298 .word gth2r @ 0x6a
299 .word lth2r @ 0x6b
300 .word jmp2r @ 0x6c
301 .word jcn2r @ 0x6d
302 .word jsr2r @ 0x6e
303 .word sth2r @ 0x6f
304 .word ldz2r @ 0x70
305 .word stz2r @ 0x71
306 .word ldr2r @ 0x72
307 .word str2r @ 0x73
308 .word lda2r @ 0x74
309 .word sta2r @ 0x75
310 .word dei2r @ 0x76
311 .word deo2r @ 0x77
312 .word add2r @ 0x78
313 .word sub2r @ 0x79
314 .word mul2r @ 0x7a
315 .word div2r @ 0x7b
316 .word and2r @ 0x7c
317 .word ora2r @ 0x7d
318 .word eor2r @ 0x7e
319 .word sft2r @ 0x7f
320 .word lit @ 0x80
321 .word inck @ 0x81
322 .word popk @ 0x82
323 .word nipk @ 0x83
324 .word swpk @ 0x84
325 .word rotk @ 0x85
326 .word dupk @ 0x86
327 .word ovrk @ 0x87
328 .word equk @ 0x88
329 .word neqk @ 0x89
330 .word gthk @ 0x8a
331 .word lthk @ 0x8b
332 .word jmpk @ 0x8c
333 .word jcnk @ 0x8d
334 .word jsrk @ 0x8e
335 .word sthk @ 0x8f
336 .word ldzk @ 0x90
337 .word stzk @ 0x91
338 .word ldrk @ 0x92
339 .word strk @ 0x93
340 .word ldak @ 0x94
341 .word stak @ 0x95
342 .word deik @ 0x96
343 .word deok @ 0x97
344 .word addk @ 0x98
345 .word subk @ 0x99
346 .word mulk @ 0x9a
347 .word divk @ 0x9b
348 .word andk @ 0x9c
349 .word orak @ 0x9d
350 .word eork @ 0x9e
351 .word sftk @ 0x9f
352 .word lit2 @ 0xa0
353 .word inc2k @ 0xa1
354 .word pop2k @ 0xa2
355 .word nip2k @ 0xa3
356 .word swp2k @ 0xa4
357 .word rot2k @ 0xa5
358 .word dup2k @ 0xa6
359 .word ovr2k @ 0xa7
360 .word equ2k @ 0xa8
361 .word neq2k @ 0xa9
362 .word gth2k @ 0xaa
363 .word lth2k @ 0xab
364 .word jmp2k @ 0xac
365 .word jcn2k @ 0xad
366 .word jsr2k @ 0xae
367 .word sth2k @ 0xaf
368 .word ldz2k @ 0xb0
369 .word stz2k @ 0xb1
370 .word ldr2k @ 0xb2
371 .word str2k @ 0xb3
372 .word lda2k @ 0xb4
373 .word sta2k @ 0xb5
374 .word dei2k @ 0xb6
375 .word deo2k @ 0xb7
376 .word add2k @ 0xb8
377 .word sub2k @ 0xb9
378 .word mul2k @ 0xba
379 .word div2k @ 0xbb
380 .word and2k @ 0xbc
381 .word ora2k @ 0xbd
382 .word eor2k @ 0xbe
383 .word sft2k @ 0xbf
384 .word litr @ 0xc0
385 .word inckr @ 0xc1
386 .word popkr @ 0xc2
387 .word nipkr @ 0xc3
388 .word swpkr @ 0xc4
389 .word rotkr @ 0xc5
390 .word dupkr @ 0xc6
391 .word ovrkr @ 0xc7
392 .word equkr @ 0xc8
393 .word neqkr @ 0xc9
394 .word gthkr @ 0xca
395 .word lthkr @ 0xcb
396 .word jmpkr @ 0xcc
397 .word jcnkr @ 0xcd
398 .word jsrkr @ 0xce
399 .word sthkr @ 0xcf
400 .word ldzkr @ 0xd0
401 .word stzkr @ 0xd1
402 .word ldrkr @ 0xd2
403 .word strkr @ 0xd3
404 .word ldakr @ 0xd4
405 .word stakr @ 0xd5
406 .word deikr @ 0xd6
407 .word deokr @ 0xd7
408 .word addkr @ 0xd8
409 .word subkr @ 0xd9
410 .word mulkr @ 0xda
411 .word divkr @ 0xdb
412 .word andkr @ 0xdc
413 .word orakr @ 0xdd
414 .word eorkr @ 0xde
415 .word sftkr @ 0xdf
416 .word lit2r @ 0xe0
417 .word inc2kr @ 0xe1
418 .word pop2kr @ 0xe2
419 .word nip2kr @ 0xe3
420 .word swp2kr @ 0xe4
421 .word rot2kr @ 0xe5
422 .word dup2kr @ 0xe6
423 .word ovr2kr @ 0xe7
424 .word equ2kr @ 0xe8
425 .word neq2kr @ 0xe9
426 .word gth2kr @ 0xea
427 .word lth2kr @ 0xeb
428 .word jmp2kr @ 0xec
429 .word jcn2kr @ 0xed
430 .word jsr2kr @ 0xee
431 .word sth2kr @ 0xef
432 .word ldz2kr @ 0xf0
433 .word stz2kr @ 0xf1
434 .word ldr2kr @ 0xf2
435 .word str2kr @ 0xf3
436 .word lda2kr @ 0xf4
437 .word sta2kr @ 0xf5
438 .word dei2kr @ 0xf6
439 .word deo2kr @ 0xf7
440 .word add2kr @ 0xf8
441 .word sub2kr @ 0xf9
442 .word mul2kr @ 0xfa
443 .word div2kr @ 0xfb
444 .word and2kr @ 0xfc
445 .word ora2kr @ 0xfd
446 .word eor2kr @ 0xfe
447 .word sft2kr @ 0xff
448
449@
450@ OP implementations.
451@
452
453dei:
454 wpop8 r3
455 mov r4, r3, lsr #4 @ idx
456 and r3, #0x0f @ port
457 ldr r6, =dei_map
458 ldr r6, [r6, r4, lsl #2]
459 stmfd sp!, {r0, r7, lr}
460 ldr r0, =wst_ptr
461 str r1, [r0]
462 ldr r0, =rst_ptr
463 str r2, [r0]
464 ldr r0, =device_data
465 lsl r4, #4
466 add r0, r4
467 mov r1, r3
468 mov lr, pc
469 bx r6
470 ldr r1, wst_ptr
471 ldr r2, rst_ptr
472 wpush8 r0
473 ldmfd sp!, {r0, r7, lr}
474 b uxn_decode
475
476dei2:
477 wpop8 r3
478 mov r4, r3, lsr #4 @ idx
479 and r3, #0x0f @ port
480 ldr r6, =dei_map
481 ldr r6, [r6, r4, lsl #2]
482 stmfd sp!, {r0, r7, lr}
483 ldr r0, =wst_ptr
484 str r1, [r0]
485 ldr r0, =rst_ptr
486 str r2, [r0]
487 ldr r0, =device_data
488 lsl r4, #4
489 add r0, r4
490 mov r1, r3
491 mov lr, pc
492 bx r6
493 ldr r1, wst_ptr
494 ldr r2, rst_ptr
495 wpush16 r0
496 ldmfd sp!, {r0, r7, lr}
497 b uxn_decode
498
499deo:
500 @ Get args (idx/port/value).
501 wpop8 r3
502 mov r4, r3, lsr #4 @ idx
503 and r3, #0x0f @ port
504 wpop8 r5 @ value
505
506 @ Find current devide.
507 ldr r6, =deo_map
508 ldr r6, [r6, r4, lsl #2]
509
510 @ Save registers that can be affected.
511 stmfd sp!, {r0, r7, lr}
512 ldr r0, =wst_ptr
513 str r1, [r0]
514 ldr r0, =rst_ptr
515 str r2, [r0]
516
517 @ Call the deo function.
518 ldr r0, =device_data
519 lsl r4, #4
520 add r0, r4
521 strb r5, [r0, r3]
522 mov r1, r3
523 mov lr, pc
524 bx r6
525
526 @ Restore saved variables.
527 ldmfd sp!, {r0, r7, lr}
528 ldr r1, wst_ptr
529 ldr r2, rst_ptr
530 b uxn_decode
531
532deo2:
533 @ Get args (idx/port/value).
534 wpop8 r3
535 mov r4, r3, lsr #4 @ idx
536 and r3, #0x0f @ port
537 wpop16 r5, r6 @ value
538
539 @ Find current devide.
540 ldr r6, =deo_map
541 ldr r6, [r6, r4, lsl #2]
542
543 @ Save registers that can be affected.
544 stmfd sp!, {r0, r7, lr}
545 ldr r0, =wst_ptr
546 str r1, [r0]
547 ldr r0, =rst_ptr
548 str r2, [r0]
549
550 @ Call the deo function.
551 ldr r0, =device_data
552 lsl r4, #4
553 add r0, r4
554 mov r1, r3
555 add r3, r0
556 strb r5, [r3, #1]
557 lsr r5, #8
558 strb r5, [r3]
559 mov lr, pc
560 bx r6
561
562 @ Restore saved variables.
563 ldmfd sp!, {r0, r7, lr}
564 ldr r1, wst_ptr
565 ldr r2, rst_ptr
566 b uxn_decode
567
568deir:
569 rpop8 r3
570 mov r4, r3, lsr #4 @ idx
571 and r3, #0x0f @ port
572 ldr r6, =dei_map
573 ldr r6, [r6, r4, lsl #2]
574 stmfd sp!, {r0, r7, lr}
575 ldr r0, =wst_ptr
576 str r1, [r0]
577 ldr r0, =rst_ptr
578 str r2, [r0]
579 ldr r0, =device_data
580 lsl r4, #4
581 add r0, r4
582 mov r1, r3
583 mov lr, pc
584 bx r6
585 ldr r1, wst_ptr
586 ldr r2, rst_ptr
587 rpush8 r0
588 ldmfd sp!, {r0, r7, lr}
589 b uxn_decode
590
591dei2r:
592 rpop8 r3
593 mov r4, r3, lsr #4 @ idx
594 and r3, #0x0f @ port
595 ldr r6, =dei_map
596 ldr r6, [r6, r4, lsl #2]
597 stmfd sp!, {r0, r7, lr}
598 ldr r0, =wst_ptr
599 str r1, [r0]
600 ldr r0, =rst_ptr
601 str r2, [r0]
602 ldr r0, =device_data
603 lsl r4, #4
604 add r0, r4
605 mov r1, r3
606 mov lr, pc
607 bx r6
608 ldr r1, wst_ptr
609 ldr r2, rst_ptr
610 rpush16 r0
611 ldmfd sp!, {r0, r7, lr}
612 b uxn_decode
613
614deor:
615 @ Get args (idx/port/value).
616 rpop8 r3
617 mov r4, r3, lsr #4 @ idx
618 and r3, #0x0f @ port
619 rpop8 r5 @ value
620
621 @ Find current devide.
622 ldr r6, =deo_map
623 ldr r6, [r6, r4, lsl #2]
624
625 @ Save registers that can be affected.
626 stmfd sp!, {r0, r7, lr}
627 ldr r0, =wst_ptr
628 str r1, [r0]
629 ldr r0, =rst_ptr
630 str r2, [r0]
631
632 @ Call the deo function.
633 ldr r0, =device_data
634 lsl r4, #4
635 add r0, r4
636 strb r5, [r0, r3]
637 mov r1, r3
638 mov lr, pc
639 bx r6
640
641 @ Restore saved variables.
642 ldmfd sp!, {r0, r7, lr}
643 ldr r1, wst_ptr
644 ldr r2, rst_ptr
645 b uxn_decode
646
647deo2r:
648 @ Get args (idx/port/value).
649 rpop8 r3
650 mov r4, r3, lsr #4 @ idx
651 and r3, #0x0f @ port
652 rpop16 r5, r6 @ value
653
654 @ Find current devide.
655 ldr r6, =deo_map
656 ldr r6, [r6, r4, lsl #2]
657
658 @ Save registers that can be affected.
659 stmfd sp!, {r0, r7, lr}
660 ldr r0, =wst_ptr
661 str r1, [r0]
662 ldr r0, =rst_ptr
663 str r2, [r0]
664
665 @ Call the deo function.
666 ldr r0, =device_data
667 lsl r4, #4
668 add r0, r4
669 mov r1, r3
670 add r3, r0
671 strb r5, [r3, #1]
672 lsr r5, #8
673 strb r5, [r3]
674 mov lr, pc
675 bx r6
676
677 @ Restore saved variables.
678 ldmfd sp!, {r0, r7, lr}
679 ldr r1, wst_ptr
680 ldr r2, rst_ptr
681 b uxn_decode
682
683deik:
684 wpeek8 r3, #-1
685 mov r4, r3, lsr #4 @ idx
686 and r3, #0x0f @ port
687 ldr r6, =dei_map
688 ldr r6, [r6, r4, lsl #2]
689 stmfd sp!, {r0, r7, lr}
690 ldr r0, =wst_ptr
691 str r1, [r0]
692 ldr r0, =rst_ptr
693 str r2, [r0]
694 ldr r0, =device_data
695 lsl r4, #4
696 add r0, r4
697 mov r1, r3
698 mov lr, pc
699 bx r6
700 ldr r1, wst_ptr
701 ldr r2, rst_ptr
702 wpush8 r0
703 ldmfd sp!, {r0, r7, lr}
704 b uxn_decode
705
706dei2k:
707 wpeek8 r3, #-1
708 mov r4, r3, lsr #4 @ idx
709 and r3, #0x0f @ port
710 ldr r6, =dei_map
711 ldr r6, [r6, r4, lsl #2]
712 stmfd sp!, {r0, r7, lr}
713 ldr r0, =wst_ptr
714 str r1, [r0]
715 ldr r0, =rst_ptr
716 str r2, [r0]
717 ldr r0, =device_data
718 lsl r4, #4
719 add r0, r4
720 mov r1, r3
721 mov lr, pc
722 bx r6
723 ldr r1, wst_ptr
724 ldr r2, rst_ptr
725 wpush16 r0
726 ldmfd sp!, {r0, r7, lr}
727 b uxn_decode
728
729deok:
730 wpeek8 r3, #-1
731 mov r4, r3, lsr #4 @ idx
732 and r3, #0x0f @ port
733 wpeek8 r5, #-2 @ value
734 ldr r6, =deo_map
735 ldr r6, [r6, r4, lsl #2]
736 stmfd sp!, {r0, r7, lr}
737 ldr r0, =wst_ptr
738 str r1, [r0]
739 ldr r0, =rst_ptr
740 str r2, [r0]
741 ldr r0, =device_data
742 lsl r4, #4
743 add r0, r4
744 strb r5, [r0, r3]
745 mov r1, r3
746 mov lr, pc
747 bx r6
748 ldmfd sp!, {r0, r7, lr}
749 ldr r1, wst_ptr
750 ldr r2, rst_ptr
751 b uxn_decode
752
753deo2k:
754 wpeek8 r3, #-1
755 mov r4, r3, lsr #4 @ idx
756 and r3, #0x0f @ port
757 wpeek16 r5, r6, #-2, #-3 @ value
758 ldr r6, =deo_map
759 ldr r6, [r6, r4, lsl #2]
760 stmfd sp!, {r0, r7, lr}
761 ldr r0, =wst_ptr
762 str r1, [r0]
763 ldr r0, =rst_ptr
764 str r2, [r0]
765 ldr r0, =device_data
766 lsl r4, #4
767 add r0, r4
768 mov r1, r3
769 add r3, r0
770 strb r5, [r3, #1]
771 lsr r5, #8
772 strb r5, [r3]
773 mov lr, pc
774 bx r6
775 ldmfd sp!, {r0, r7, lr}
776 ldr r1, wst_ptr
777 ldr r2, rst_ptr
778 b uxn_decode
779
780deikr:
781 rpeek8 r3, #-1
782 mov r4, r3, lsr #4 @ idx
783 and r3, #0x0f @ port
784 ldr r6, =dei_map
785 ldr r6, [r6, r4, lsl #2]
786 stmfd sp!, {r0, r7, lr}
787 ldr r0, =wst_ptr
788 str r1, [r0]
789 ldr r0, =rst_ptr
790 str r2, [r0]
791 ldr r0, =device_data
792 lsl r4, #4
793 add r0, r4
794 mov r1, r3
795 mov lr, pc
796 bx r6
797 ldr r1, wst_ptr
798 ldr r2, rst_ptr
799 rpush8 r0
800 ldmfd sp!, {r0, r7, lr}
801 b uxn_decode
802
803dei2kr:
804 rpeek8 r3, #-1
805 mov r4, r3, lsr #4 @ idx
806 and r3, #0x0f @ port
807 ldr r6, =dei_map
808 ldr r6, [r6, r4, lsl #2]
809 stmfd sp!, {r0, r7, lr}
810 ldr r0, =wst_ptr
811 str r1, [r0]
812 ldr r0, =rst_ptr
813 str r2, [r0]
814 ldr r0, =device_data
815 lsl r4, #4
816 add r0, r4
817 mov r1, r3
818 mov lr, pc
819 bx r6
820 ldr r1, wst_ptr
821 ldr r2, rst_ptr
822 rpush16 r0
823 ldmfd sp!, {r0, r7, lr}
824 b uxn_decode
825
826deokr:
827 rpeek8 r3, #-1
828 mov r4, r3, lsr #4 @ idx
829 and r3, #0x0f @ port
830 rpeek8 r5, #-2 @ value
831 ldr r6, =deo_map
832 ldr r6, [r6, r4, lsl #2]
833 stmfd sp!, {r0, r7, lr}
834 ldr r0, =wst_ptr
835 str r1, [r0]
836 ldr r0, =rst_ptr
837 str r2, [r0]
838 ldr r0, =device_data
839 lsl r4, #4
840 add r0, r4
841 strb r5, [r0, r3]
842 mov r1, r3
843 mov lr, pc
844 bx r6
845 ldmfd sp!, {r0, r7, lr}
846 ldr r1, wst_ptr
847 ldr r2, rst_ptr
848 b uxn_decode
849
850deo2kr:
851 rpeek8 r3, #-1
852 mov r4, r3, lsr #4 @ idx
853 and r3, #0x0f @ port
854 rpeek16 r5, r6, #-2, #-3 @ value
855 ldr r6, =deo_map
856 ldr r6, [r6, r4, lsl #2]
857 stmfd sp!, {r0, r7, lr}
858 ldr r0, =wst_ptr
859 str r1, [r0]
860 ldr r0, =rst_ptr
861 str r2, [r0]
862 ldr r0, =device_data
863 lsl r4, #4
864 add r0, r4
865 mov r1, r3
866 add r3, r0
867 strb r5, [r3, #1]
868 lsr r5, #8
869 strb r5, [r3]
870 mov lr, pc
871 bx r6
872 ldmfd sp!, {r0, r7, lr}
873 ldr r1, wst_ptr
874 ldr r2, rst_ptr
875 b uxn_decode
876
877.ltorg
878.align 2
879
880.global device_data
881device_data:
882 .global device_0
883 device_0: .space 16
884 .global device_1
885 device_1: .space 16
886 .global device_2
887 device_2: .space 16
888 .global device_3
889 device_3: .space 16
890 .global device_4
891 device_4: .space 16
892 .global device_5
893 device_5: .space 16
894 .global device_6
895 device_6: .space 16
896 .global device_7
897 device_7: .space 16
898 .global device_8
899 device_8: .space 16
900 .global device_9
901 device_9: .space 16
902 .global device_a
903 device_a: .space 16
904 .global device_b
905 device_b: .space 16
906 .global device_c
907 device_c: .space 16
908 .global device_d
909 device_d: .space 16
910 .global device_e
911 device_e: .space 16
912 .global device_f
913 device_f: .space 16
914
915.global dei_map
916dei_map:
917 .word uxn_ret
918 .word uxn_ret
919 .word uxn_ret
920 .word uxn_ret
921 .word uxn_ret
922 .word uxn_ret
923 .word uxn_ret
924 .word uxn_ret
925 .word uxn_ret
926 .word uxn_ret
927 .word uxn_ret
928 .word uxn_ret
929 .word uxn_ret
930 .word uxn_ret
931 .word uxn_ret
932 .word uxn_ret
933
934.global deo_map
935deo_map:
936 .word uxn_ret
937 .word uxn_ret
938 .word uxn_ret
939 .word uxn_ret
940 .word uxn_ret
941 .word uxn_ret
942 .word uxn_ret
943 .word uxn_ret
944 .word uxn_ret
945 .word uxn_ret
946 .word uxn_ret
947 .word uxn_ret
948 .word uxn_ret
949 .word uxn_ret
950 .word uxn_ret
951 .word uxn_ret
952
953brk:
954 b uxn_ret
955
956jci:
957 ldrb r5, [r0], #1
958 ldrb r3, [r0], #1
959 orr r3, r3, r5, lsl #8
960 lsl r3, r3, #16
961 asr r3, r3, #16
962 wpop8 r4
963 cmp r4, #0
964 addne r0, r3
965 b uxn_decode
966
967jmi:
968 ldrb r5, [r0], #1
969 ldrb r3, [r0], #1
970 orr r3, r3, r5, lsl #8
971 lsl r3, r3, #16
972 asr r3, r3, #16
973 add r0, r3
974 b uxn_decode
975
976jsi:
977 ldrb r5, [r0], #1
978 ldrb r3, [r0], #1
979 orr r3, r3, r5, lsl #8
980 lsl r3, r3, #16
981 asr r3, r3, #16
982 mov r4, r0
983 rpush16 r4
984 add r0, r3
985 b uxn_decode
986
987lit:
988 next r3
989 wpush8 r3
990 b uxn_decode
991
992lit2:
993 next r3
994 next r4
995 wpush8 r3
996 wpush8 r4
997 b uxn_decode
998
999litr:
1000 next r3
1001 rpush8 r3
1002 b uxn_decode
1003
1004lit2r:
1005 next r3
1006 next r4
1007 rpush8 r3
1008 rpush8 r4
1009 b uxn_decode
1010
1011.ltorg
1012.align 2
1013
1014inc:
1015 wpop8 r3
1016 add r3, #1
1017 wpush8 r3
1018 b uxn_decode
1019
1020inc2:
1021 wpop16 r3, r5
1022 add r3, r3, #1
1023 wpush16 r3
1024 b uxn_decode
1025
1026pop:
1027 sub r1, #1
1028 b uxn_decode
1029
1030pop2:
1031 sub r1, #2
1032 b uxn_decode
1033
1034nip:
1035 wpop8 r3
1036 strb r3, [r1, #-1]
1037 b uxn_decode
1038
1039nip2:
1040 wpop16 r3, r5
1041 strb r3, [r1, #-1]
1042 lsr r3, #8
1043 strb r3, [r1, #-2]
1044 b uxn_decode
1045
1046swp:
1047 wpop8 r3
1048 wpop8 r4
1049 wpush8 r3
1050 wpush8 r4
1051 b uxn_decode
1052
1053swp2:
1054 wpop16 r3, r5
1055 wpop16 r4, r5
1056 wpush16 r3
1057 wpush16 r4
1058 b uxn_decode
1059
1060rot:
1061 wpop8 r5
1062 wpop8 r4
1063 wpop8 r3
1064 wpush8 r4
1065 wpush8 r5
1066 wpush8 r3
1067 b uxn_decode
1068
1069rot2:
1070 wpop16 r5, r6
1071 wpop16 r4, r6
1072 wpop16 r3, r6
1073 wpush16 r4
1074 wpush16 r5
1075 wpush16 r3
1076 b uxn_decode
1077
1078dup:
1079 wpeek8 r3, #-1
1080 wpush8 r3
1081 b uxn_decode
1082
1083dup2:
1084 wpeek8 r3, #-2
1085 wpeek8 r4, #-1
1086 wpush8 r3
1087 wpush8 r4
1088 b uxn_decode
1089
1090ovr:
1091 wpeek8 r3, #-2
1092 wpush8 r3
1093 b uxn_decode
1094
1095ovr2:
1096 wpeek8 r3, #-4
1097 wpeek8 r4, #-3
1098 wpush8 r3
1099 wpush8 r4
1100 b uxn_decode
1101
1102equ:
1103 wpop8 r3
1104 wpop8 r4
1105 sub r3, r4, r3
1106 rsbs r4, r3, #0
1107 adc r4, r4, r3
1108 wpush8 r4
1109 b uxn_decode
1110
1111equ2:
1112 wpop16 r3, r5
1113 wpop16 r4, r5
1114 sub r3, r4, r3
1115 rsbs r4, r3, #0
1116 adc r4, r4, r3
1117 wpush8 r4
1118 b uxn_decode
1119
1120neq:
1121 wpop8 r3
1122 wpop8 r4
1123 subs r3, r4, r3
1124 movne r3, #1
1125 wpush8 r3
1126 b uxn_decode
1127
1128neq2:
1129 wpop16 r3, r5
1130 wpop16 r4, r5
1131 subs r3, r4, r3
1132 movne r3, #1
1133 wpush8 r3
1134 b uxn_decode
1135
1136gth:
1137 wpop8 r3
1138 wpop8 r4
1139 cmp r4, r3
1140 movls r3, #0
1141 movhi r3, #1
1142 wpush8 r3
1143 b uxn_decode
1144
1145gth2:
1146 wpop16 r3, r5
1147 wpop16 r4, r5
1148 cmp r4, r3
1149 movls r3, #0
1150 movhi r3, #1
1151 wpush8 r3
1152 b uxn_decode
1153
1154lth:
1155 wpop8 r3
1156 wpop8 r4
1157 cmp r4, r3
1158 movcs r3, #0
1159 movcc r3, #1
1160 wpush8 r3
1161 b uxn_decode
1162
1163lth2:
1164 wpop16 r3, r5
1165 wpop16 r4, r5
1166 cmp r4, r3
1167 movcs r3, #0
1168 movcc r3, #1
1169 wpush8 r3
1170 b uxn_decode
1171
1172jmp:
1173 wpop8s r3
1174 add r0, r3
1175 b uxn_decode
1176
1177jmp2:
1178 wpop16 r3, r5
1179 mov r0, r7
1180 add r0, r0, r3
1181 b uxn_decode
1182
1183jcn:
1184 wpop8s r3
1185 wpop8 r4
1186 cmp r4, #0
1187 addne r0, r3
1188 b uxn_decode
1189
1190jcn2:
1191 wpop16 r3, r5
1192 wpop8 r4
1193 cmp r4, #0
1194 movne r0, r7
1195 cmp r4, #0
1196 addne r0, r0, r3
1197 b uxn_decode
1198
1199jsr:
1200 mov r3, r0
1201 sub r3, r3, r7
1202 wpop8s r4
1203 rpush16 r3
1204 add r0, r4
1205 b uxn_decode
1206
1207jsr2:
1208 mov r3, r0
1209 sub r3, r3, r7
1210 wpop16 r4, r5
1211 rpush16 r3
1212 mov r0, r7
1213 add r0, r0, r4
1214 b uxn_decode
1215
1216sth:
1217 wpop8 r3
1218 rpush8 r3
1219 b uxn_decode
1220
1221sth2:
1222 wpop16 r3, r5
1223 rpush16 r3
1224 b uxn_decode
1225
1226ldz:
1227 wpop8 r3
1228 zload8 r4, r3
1229 wpush8 r4
1230 b uxn_decode
1231
1232ldz2:
1233 wpop8 r3
1234 zload8 r4, r3
1235 wpush8 r4
1236 add r3, #1
1237 zload8 r4, r3
1238 wpush8 r4
1239 b uxn_decode
1240
1241stz:
1242 wpop8 r3
1243 wpop8 r4
1244 zsave8 r4, r3
1245 b uxn_decode
1246
1247stz2:
1248 wpop8 r3
1249 wpop16 r4, r5
1250 zsave16 r4, r3
1251 b uxn_decode
1252
1253ldr:
1254 wpop8s r4
1255 rload8 r3, r4
1256 wpush8 r3
1257 b uxn_decode
1258
1259ldr2:
1260 wpop8s r4
1261 rload8 r3, r4
1262 wpush8 r3
1263 add r4, #1
1264 rload8 r3, r4
1265 wpush8 r3
1266 b uxn_decode
1267
1268str:
1269 wpop8s r4
1270 wpop8 r3
1271 rsave8 r3, r4
1272 b uxn_decode
1273
1274str2:
1275 wpop8s r4
1276 wpop16 r3, r5
1277 rsave16 r3, r4
1278 b uxn_decode
1279
1280lda:
1281 wpop16 r4, r5
1282 aload8 r3, r4
1283 wpush8 r3
1284 b uxn_decode
1285
1286lda2:
1287 wpop16 r4, r5
1288 aload8 r3, r4
1289 wpush8 r3
1290 add r4, #1
1291 aload8 r3, r4
1292 wpush8 r3
1293 b uxn_decode
1294
1295sta:
1296 wpop16 r4, r5
1297 wpop8 r3
1298 asave8 r3, r4
1299 b uxn_decode
1300
1301sta2:
1302 wpop16 r4, r5
1303 wpop16 r3, r5
1304 asave16 r3, r4
1305 b uxn_decode
1306
1307add:
1308 wpop8 r3
1309 wpop8 r4
1310 add r3, r3, r4
1311 wpush8 r3
1312 b uxn_decode
1313
1314add2:
1315 wpop16 r3, r5
1316 wpop16 r4, r5
1317 add r3, r3, r4
1318 wpush16 r3
1319 b uxn_decode
1320
1321sub:
1322 wpop8 r3
1323 wpop8 r4
1324 sub r4, r4, r3
1325 wpush8 r4
1326 b uxn_decode
1327
1328sub2:
1329 wpop16 r3, r5
1330 wpop16 r4, r5
1331 sub r3, r4, r3
1332 wpush16 r3
1333 b uxn_decode
1334
1335mul:
1336 wpop8 r3
1337 wpop8 r4
1338 mul r4, r3, r4
1339 wpush8 r4
1340 b uxn_decode
1341
1342mul2:
1343 wpop16 r3, r5
1344 wpop16 r4, r5
1345 mul r3, r4, r3
1346 wpush16 r3
1347 b uxn_decode
1348
1349div:
1350 wpop8 r3
1351 wpop8 r4
1352 push {r0, r1, r2, r7, lr}
1353 mov r1, r3
1354 mov r0, r4
1355 bl __aeabi_uidiv
1356 mov r3, r0
1357 pop {r0, r1, r2, r7, lr}
1358 wpush8 r3
1359 b uxn_decode
1360
1361div2:
1362 wpop16 r3, r5
1363 wpop16 r4, r5
1364 push {r0, r1, r2, r7, lr}
1365 mov r1, r3
1366 mov r0, r4
1367 bl __aeabi_uidiv
1368 mov r3, r0
1369 pop {r0, r1, r2, r7, lr}
1370 wpush16 r3
1371 b uxn_decode
1372
1373and:
1374 wpop8 r3
1375 wpop8 r4
1376 and r3, r3, r4
1377 wpush8 r3
1378 b uxn_decode
1379
1380and2:
1381 wpop16 r3, r5
1382 wpop16 r4, r5
1383 and r3, r3, r4
1384 wpush16 r3
1385 b uxn_decode
1386
1387ora:
1388 wpop8 r3
1389 wpop8 r4
1390 orr r3, r3, r4
1391 wpush8 r3
1392 b uxn_decode
1393
1394ora2:
1395 wpop16 r3, r5
1396 wpop16 r4, r5
1397 orr r3, r3, r4
1398 wpush16 r3
1399 b uxn_decode
1400
1401eor:
1402 wpop8 r3
1403 wpop8 r4
1404 eor r3, r3, r4
1405 wpush8 r3
1406 b uxn_decode
1407
1408eor2:
1409 wpop16 r3, r5
1410 wpop16 r4, r5
1411 eor r3, r3, r4
1412 wpush16 r3
1413 b uxn_decode
1414
1415sft:
1416 wpop8 r4
1417 wpop8 r3
1418 lsr r5, r4, #4
1419 and r4, #0x0f
1420 lsr r3, r3, r4
1421 lsl r3, r3, r5
1422 wpush8 r3
1423 b uxn_decode
1424
1425sft2:
1426 wpop8 r4
1427 wpop16 r3, r5
1428 lsr r5, r4, #4
1429 and r4, #0x0f
1430 lsr r3, r3, r4
1431 lsl r3, r3, r5
1432 wpush16 r3
1433 b uxn_decode
1434
1435.ltorg
1436.align 2
1437
1438incr:
1439 rpop8 r3
1440 add r3, #1
1441 rpush8 r3
1442 b uxn_decode
1443
1444inc2r:
1445 rpop16 r3, r5
1446 add r3, r3, #1
1447 rpush16 r3
1448 b uxn_decode
1449
1450popr:
1451 sub r2, #1
1452 b uxn_decode
1453
1454pop2r:
1455 sub r2, #2
1456 b uxn_decode
1457
1458nipr:
1459 rpop8 r3
1460 strb r3, [r2, #-1]
1461 b uxn_decode
1462
1463nip2r:
1464 rpop16 r3, r5
1465 strb r3, [r2, #-1]
1466 lsr r3, #8
1467 strb r3, [r2, #-2]
1468 b uxn_decode
1469
1470swpr:
1471 rpop8 r3
1472 rpop8 r4
1473 rpush8 r3
1474 rpush8 r4
1475 b uxn_decode
1476
1477swp2r:
1478 rpop16 r3, r5
1479 rpop16 r4, r5
1480 rpush16 r3
1481 rpush16 r4
1482 b uxn_decode
1483
1484rotr:
1485 rpop8 r5
1486 rpop8 r4
1487 rpop8 r3
1488 rpush8 r4
1489 rpush8 r5
1490 rpush8 r3
1491 b uxn_decode
1492
1493rot2r:
1494 rpop16 r5, r6
1495 rpop16 r4, r6
1496 rpop16 r3, r6
1497 rpush16 r4
1498 rpush16 r5
1499 rpush16 r3
1500 b uxn_decode
1501
1502dupr:
1503 rpeek8 r3, #-1
1504 rpush8 r3
1505 b uxn_decode
1506
1507dup2r:
1508 rpeek8 r3, #-2
1509 rpeek8 r4, #-1
1510 rpush8 r3
1511 rpush8 r4
1512 b uxn_decode
1513
1514ovrr:
1515 rpeek8 r3, #-2
1516 rpush8 r3
1517 b uxn_decode
1518
1519ovr2r:
1520 rpeek8 r3, #-4
1521 rpeek8 r4, #-3
1522 rpush8 r3
1523 rpush8 r4
1524 b uxn_decode
1525
1526equr:
1527 rpop8 r3
1528 rpop8 r4
1529 sub r3, r4, r3
1530 rsbs r4, r3, #0
1531 adc r4, r4, r3
1532 rpush8 r4
1533 b uxn_decode
1534
1535equ2r:
1536 rpop16 r3, r5
1537 rpop16 r4, r5
1538 sub r3, r4, r3
1539 rsbs r4, r3, #0
1540 adc r4, r4, r3
1541 rpush8 r4
1542 b uxn_decode
1543
1544neqr:
1545 rpop8 r3
1546 rpop8 r4
1547 subs r3, r4, r3
1548 movne r3, #1
1549 rpush8 r3
1550 b uxn_decode
1551
1552neq2r:
1553 rpop16 r3, r5
1554 rpop16 r4, r5
1555 subs r3, r4, r3
1556 movne r3, #1
1557 rpush8 r3
1558 b uxn_decode
1559
1560gthr:
1561 rpop8 r3
1562 rpop8 r4
1563 cmp r4, r3
1564 movls r3, #0
1565 movhi r3, #1
1566 rpush8 r3
1567 b uxn_decode
1568
1569gth2r:
1570 rpop16 r3, r5
1571 rpop16 r4, r5
1572 cmp r4, r3
1573 movls r3, #0
1574 movhi r3, #1
1575 rpush8 r3
1576 b uxn_decode
1577
1578lthr:
1579 rpop8 r3
1580 rpop8 r4
1581 cmp r4, r3
1582 movcs r3, #0
1583 movcc r3, #1
1584 rpush8 r3
1585 b uxn_decode
1586
1587lth2r:
1588 rpop16 r3, r5
1589 rpop16 r4, r5
1590 cmp r4, r3
1591 movcs r3, #0
1592 movcc r3, #1
1593 rpush8 r3
1594 b uxn_decode
1595
1596jmpr:
1597 rpop8s r3
1598 add r0, r3
1599 b uxn_decode
1600
1601jmp2r:
1602 rpop16 r3, r5
1603 mov r0, r7
1604 add r0, r0, r3
1605 b uxn_decode
1606
1607jcnr:
1608 rpop8s r3
1609 rpop8 r4
1610 cmp r4, #0
1611 addne r0, r3
1612 b uxn_decode
1613
1614jcn2r:
1615 rpop16 r3, r5
1616 rpop8 r4
1617 cmp r4, #0
1618 movne r0, r7
1619 cmp r4, #0
1620 addne r0, r0, r3
1621 b uxn_decode
1622
1623jsrr:
1624 mov r3, r0
1625 sub r3, r3, r7
1626 rpop8s r4
1627 rpush16 r3
1628 add r0, r4
1629 b uxn_decode
1630
1631jsr2r:
1632 mov r3, r0
1633 sub r3, r3, r7
1634 rpop16 r4, r5
1635 rpush16 r3
1636 mov r0, r7
1637 add r0, r0, r4
1638 b uxn_decode
1639
1640sthr:
1641 rpop8 r3
1642 wpush8 r3
1643 b uxn_decode
1644
1645sth2r:
1646 rpop16 r3, r5
1647 wpush16 r3
1648 b uxn_decode
1649
1650ldzr:
1651 rpop8 r3
1652 zload8 r4, r3
1653 rpush8 r4
1654 b uxn_decode
1655
1656ldz2r:
1657 rpop8 r3
1658 zload8 r4, r3
1659 rpush8 r4
1660 add r3, #1
1661 zload8 r4, r3
1662 rpush8 r4
1663 b uxn_decode
1664
1665stzr:
1666 rpop8 r3
1667 rpop8 r4
1668 zsave8 r4, r3
1669 b uxn_decode
1670
1671stz2r:
1672 rpop8 r3
1673 rpop16 r4, r5
1674 zsave16 r4, r3
1675 b uxn_decode
1676
1677ldrr:
1678 rpop8s r4
1679 rload8 r3, r4
1680 rpush8 r3
1681 b uxn_decode
1682
1683ldr2r:
1684 rpop8s r4
1685 rload8 r3, r4
1686 rpush8 r3
1687 add r4, #1
1688 rload8 r3, r4
1689 rpush8 r3
1690 b uxn_decode
1691
1692strr:
1693 rpop8s r4
1694 rpop8 r3
1695 rsave8 r3, r4
1696 b uxn_decode
1697
1698str2r:
1699 rpop8s r4
1700 rpop16 r3, r5
1701 rsave16 r3, r4
1702 b uxn_decode
1703
1704ldar:
1705 rpop16 r4, r5
1706 aload8 r3, r4
1707 rpush8 r3
1708 b uxn_decode
1709
1710lda2r:
1711 rpop16 r4, r5
1712 aload8 r3, r4
1713 rpush8 r3
1714 add r4, #1
1715 aload8 r3, r4
1716 rpush8 r3
1717 b uxn_decode
1718
1719star:
1720 rpop16 r4, r5
1721 rpop8 r3
1722 asave8 r3, r4
1723 b uxn_decode
1724
1725sta2r:
1726 rpop16 r4, r5
1727 rpop16 r3, r5
1728 asave16 r3, r4
1729 b uxn_decode
1730
1731addr:
1732 rpop8 r3
1733 rpop8 r4
1734 add r3, r3, r4
1735 rpush8 r3
1736 b uxn_decode
1737
1738add2r:
1739 rpop16 r3, r5
1740 rpop16 r4, r5
1741 add r3, r3, r4
1742 rpush16 r3
1743 b uxn_decode
1744
1745subr:
1746 rpop8 r3
1747 rpop8 r4
1748 sub r4, r4, r3
1749 rpush8 r4
1750 b uxn_decode
1751
1752sub2r:
1753 rpop16 r3, r5
1754 rpop16 r4, r5
1755 sub r3, r4, r3
1756 rpush16 r3
1757 b uxn_decode
1758
1759mulr:
1760 rpop8 r3
1761 rpop8 r4
1762 mul r4, r3, r4
1763 rpush8 r4
1764 b uxn_decode
1765
1766mul2r:
1767 rpop16 r3, r5
1768 rpop16 r4, r5
1769 mul r3, r4, r3
1770 rpush16 r3
1771 b uxn_decode
1772
1773divr:
1774 rpop8 r3
1775 rpop8 r4
1776 push {r0, r1, r2, r7, lr}
1777 mov r1, r3
1778 mov r0, r4
1779 bl __aeabi_uidiv
1780 mov r3, r0
1781 pop {r0, r1, r2, r7, lr}
1782 rpush8 r3
1783 b uxn_decode
1784
1785div2r:
1786 rpop16 r3, r5
1787 rpop16 r4, r5
1788 push {r0, r1, r2, r7, lr}
1789 mov r1, r3
1790 mov r0, r4
1791 bl __aeabi_uidiv
1792 mov r3, r0
1793 pop {r0, r1, r2, r7, lr}
1794 rpush16 r3
1795 b uxn_decode
1796
1797andr:
1798 rpop8 r3
1799 rpop8 r4
1800 and r3, r3, r4
1801 rpush8 r3
1802 b uxn_decode
1803
1804and2r:
1805 rpop16 r3, r5
1806 rpop16 r4, r5
1807 and r3, r3, r4
1808 rpush16 r3
1809 b uxn_decode
1810
1811orar:
1812 rpop8 r3
1813 rpop8 r4
1814 orr r3, r3, r4
1815 rpush8 r3
1816 b uxn_decode
1817
1818ora2r:
1819 rpop16 r3, r5
1820 rpop16 r4, r5
1821 orr r3, r3, r4
1822 rpush16 r3
1823 b uxn_decode
1824
1825eorr:
1826 rpop8 r3
1827 rpop8 r4
1828 eor r3, r3, r4
1829 rpush8 r3
1830 b uxn_decode
1831
1832eor2r:
1833 rpop16 r3, r5
1834 rpop16 r4, r5
1835 eor r3, r3, r4
1836 rpush16 r3
1837 b uxn_decode
1838
1839sftr:
1840 rpop8 r4
1841 rpop8 r3
1842 lsr r5, r4, #4
1843 and r4, #0x0f
1844 lsr r3, r3, r4
1845 lsl r3, r3, r5
1846 rpush8 r3
1847 b uxn_decode
1848
1849sft2r:
1850 rpop8 r4
1851 rpop16 r3, r5
1852 lsr r5, r4, #4
1853 and r4, #0x0f
1854 lsr r3, r3, r4
1855 lsl r3, r3, r5
1856 rpush16 r3
1857 b uxn_decode
1858
1859.ltorg
1860.align 2
1861
1862inck:
1863 wpeek8 r3, #-1
1864 add r3, #1
1865 wpush8 r3
1866 b uxn_decode
1867
1868inc2k:
1869 wpeek16 r3, r5, #-1, #-2
1870 add r3, r3, #1
1871 wpush16 r3
1872 b uxn_decode
1873
1874popk:
1875 b uxn_decode
1876
1877pop2k:
1878 b uxn_decode
1879
1880nipk:
1881 wpeek8 r3, #-1
1882 wpush8 r3
1883 b uxn_decode
1884
1885nip2k:
1886 wpeek16 r3, r5, #-1, #-2
1887 wpush16 r3
1888 b uxn_decode
1889
1890swpk:
1891 wpeek8 r3, #-1
1892 wpeek8 r4, #-2
1893 wpush8 r3
1894 wpush8 r4
1895 b uxn_decode
1896
1897swp2k:
1898 wpeek16 r3, r5, #-1, #-2
1899 wpeek16 r4, r5, #-3, #-4
1900 wpush16 r3
1901 wpush16 r4
1902 b uxn_decode
1903
1904rotk:
1905 wpeek8 r5, #-1
1906 wpeek8 r4, #-2
1907 wpeek8 r3, #-3
1908 wpush8 r4
1909 wpush8 r5
1910 wpush8 r3
1911 b uxn_decode
1912
1913rot2k:
1914 wpeek16 r5, r6, #-1, #-2
1915 wpeek16 r4, r6, #-3, #-4
1916 wpeek16 r3, r6, #-5, #-6
1917 wpush16 r4
1918 wpush16 r5
1919 wpush16 r3
1920 b uxn_decode
1921
1922dupk:
1923 wpeek8 r3, #-1
1924 wpush8 r3
1925 wpush8 r3
1926 b uxn_decode
1927
1928dup2k:
1929 wpeek8 r3, #-2
1930 wpeek8 r4, #-1
1931 wpush8 r3
1932 wpush8 r4
1933 wpush8 r3
1934 wpush8 r4
1935 b uxn_decode
1936
1937ovrk:
1938 wpeek8 r3, #-2
1939 wpeek8 r4, #-1
1940 wpush8 r3
1941 wpush8 r4
1942 wpush8 r3
1943 b uxn_decode
1944
1945ovr2k:
1946 wpeek8 r3, #-4
1947 wpeek8 r4, #-3
1948 wpeek8 r5, #-2
1949 wpeek8 r6, #-1
1950 wpush8 r3
1951 wpush8 r4
1952 wpush8 r5
1953 wpush8 r6
1954 wpush8 r3
1955 wpush8 r4
1956 b uxn_decode
1957
1958equk:
1959 wpeek8 r3, #-1
1960 wpeek8 r4, #-2
1961 sub r3, r4, r3
1962 rsbs r4, r3, #0
1963 adc r4, r4, r3
1964 wpush8 r4
1965 b uxn_decode
1966
1967equ2k:
1968 wpeek16 r3, r5, #-1, #-2
1969 wpeek16 r4, r5, #-3, #-4
1970 sub r3, r4, r3
1971 rsbs r4, r3, #0
1972 adc r4, r4, r3
1973 wpush8 r4
1974 b uxn_decode
1975
1976neqk:
1977 wpeek8 r3, #-1
1978 wpeek8 r4, #-2
1979 subs r3, r4, r3
1980 movne r3, #1
1981 wpush8 r3
1982 b uxn_decode
1983
1984neq2k:
1985 wpeek16 r3, r5, #-1, #-2
1986 wpeek16 r4, r5, #-3, #-4
1987 subs r3, r4, r3
1988 movne r3, #1
1989 wpush8 r3
1990 b uxn_decode
1991
1992gthk:
1993 wpeek8 r3, #-1
1994 wpeek8 r4, #-2
1995 cmp r4, r3
1996 movls r3, #0
1997 movhi r3, #1
1998 wpush8 r3
1999 b uxn_decode
2000
2001gth2k:
2002 wpeek16 r3, r5, #-1, #-2
2003 wpeek16 r4, r5, #-3, #-4
2004 cmp r4, r3
2005 movls r3, #0
2006 movhi r3, #1
2007 wpush8 r3
2008 b uxn_decode
2009
2010lthk:
2011 wpeek8 r3, #-1
2012 wpeek8 r4, #-2
2013 cmp r4, r3
2014 movcs r3, #0
2015 movcc r3, #1
2016 wpush8 r3
2017 b uxn_decode
2018
2019lth2k:
2020 wpeek16 r3, r5, #-1, #-2
2021 wpeek16 r4, r5, #-3, #-4
2022 cmp r4, r3
2023 movcs r3, #0
2024 movcc r3, #1
2025 wpush8 r3
2026 b uxn_decode
2027
2028jmpk:
2029 wpeek8s r3, #-1
2030 add r0, r3
2031 b uxn_decode
2032
2033jmp2k:
2034 wpeek16 r3, r5, #-1, #-2
2035 mov r0, r7
2036 add r0, r0, r3
2037 b uxn_decode
2038
2039jcnk:
2040 wpeek8s r3, #-1
2041 wpeek8 r4, #-2
2042 cmp r4, #0
2043 addne r0, r3
2044 b uxn_decode
2045
2046jcn2k:
2047 wpeek16 r3, r5, #-1, #-2
2048 wpeek8 r4, #-3
2049 cmp r4, #0
2050 movne r0, r7
2051 cmp r4, #0
2052 addne r0, r0, r3
2053 b uxn_decode
2054
2055jsrk:
2056 mov r3, r0
2057 sub r3, r3, r7
2058 wpeek8s r4, #-1
2059 rpush16 r3
2060 add r0, r4
2061 b uxn_decode
2062
2063jsr2k:
2064 mov r3, r0
2065 sub r3, r3, r7
2066 wpeek16 r4, r5, #-1, #-2
2067 rpush16 r3
2068 mov r0, r7
2069 add r0, r0, r4
2070 b uxn_decode
2071
2072sthk:
2073 wpeek8 r3, #-1
2074 rpush8 r3
2075 b uxn_decode
2076
2077sth2k:
2078 wpeek16 r3, r5, #-1, #-2
2079 rpush16 r3
2080 b uxn_decode
2081
2082ldzk:
2083 wpeek8 r3, #-1
2084 zload8 r4, r3
2085 wpush8 r4
2086 b uxn_decode
2087
2088ldz2k:
2089 wpeek8 r3, #-1
2090 zload8 r4, r3
2091 wpush8 r4
2092 add r3, #1
2093 zload8 r4, r3
2094 wpush8 r4
2095 b uxn_decode
2096
2097stzk:
2098 wpeek8 r3, #-1
2099 wpeek8 r4, #-2
2100 zsave8 r4, r3
2101 b uxn_decode
2102
2103stz2k:
2104 wpeek8 r3, #-1
2105 wpeek16 r4, r5, #-2, #-3
2106 zsave16 r4, r3
2107 b uxn_decode
2108
2109ldrk:
2110 wpeek8s r4, #-1
2111 rload8 r3, r4
2112 wpush8 r3
2113 b uxn_decode
2114
2115ldr2k:
2116 wpeek8s r4, #-1
2117 rload8 r3, r4
2118 wpush8 r3
2119 add r4, #1
2120 rload8 r3, r4
2121 wpush8 r3
2122 b uxn_decode
2123
2124strk:
2125 wpeek8s r4, #-1
2126 wpeek8 r3, #-2
2127 rsave8 r3, r4
2128 b uxn_decode
2129
2130str2k:
2131 wpeek8s r4, #-1
2132 wpeek16 r3, r5, #-2, #-3
2133 rsave16 r3, r4
2134 b uxn_decode
2135
2136ldak:
2137 wpeek16 r4, r5, #-1, #-2
2138 aload8 r3, r4
2139 wpush8 r3
2140 b uxn_decode
2141
2142lda2k:
2143 wpeek16 r4, r5, #-1, #-2
2144 aload8 r3, r4
2145 wpush8 r3
2146 add r4, #1
2147 aload8 r3, r4
2148 wpush8 r3
2149 b uxn_decode
2150
2151stak:
2152 wpeek16 r4, r5, #-1, #-2
2153 wpeek8 r3, #-3
2154 asave8 r3, r4
2155 b uxn_decode
2156
2157sta2k:
2158 wpeek16 r4, r5, #-1, #-2
2159 wpeek16 r3, r5, #-3, #-4
2160 asave16 r3, r4
2161 b uxn_decode
2162
2163addk:
2164 wpeek8 r3, #-1
2165 wpeek8 r4, #-2
2166 add r3, r3, r4
2167 wpush8 r3
2168 b uxn_decode
2169
2170add2k:
2171 wpeek16 r3, r5, #-1, #-2
2172 wpeek16 r4, r5, #-3, #-4
2173 add r3, r3, r4
2174 wpush16 r3
2175 b uxn_decode
2176
2177subk:
2178 wpeek8 r3, #-1
2179 wpeek8 r4, #-2
2180 sub r4, r4, r3
2181 wpush8 r4
2182 b uxn_decode
2183
2184sub2k:
2185 wpeek16 r3, r5, #-1, #-2
2186 wpeek16 r4, r5, #-3, #-4
2187 sub r3, r4, r3
2188 wpush16 r3
2189 b uxn_decode
2190
2191mulk:
2192 wpeek8 r3, #-1
2193 wpeek8 r4, #-2
2194 mul r4, r3, r4
2195 wpush8 r4
2196 b uxn_decode
2197
2198mul2k:
2199 wpeek16 r3, r5, #-1, #-2
2200 wpeek16 r4, r5, #-3, #-4
2201 mul r3, r4, r3
2202 wpush16 r3
2203 b uxn_decode
2204
2205divk:
2206 wpeek8 r3, #-1
2207 wpeek8 r4, #-2
2208 push {r0, r1, r2, r7, lr}
2209 mov r1, r3
2210 mov r0, r4
2211 bl __aeabi_uidiv
2212 mov r3, r0
2213 pop {r0, r1, r2, r7, lr}
2214 wpush8 r3
2215 b uxn_decode
2216
2217div2k:
2218 wpeek16 r3, r5, #-1, #-2
2219 wpeek16 r4, r5, #-3, #-4
2220 push {r0, r1, r2, r7, lr}
2221 mov r1, r3
2222 mov r0, r4
2223 bl __aeabi_uidiv
2224 mov r3, r0
2225 pop {r0, r1, r2, r7, lr}
2226 wpush16 r3
2227 b uxn_decode
2228
2229andk:
2230 wpeek8 r3, #-1
2231 wpeek8 r4, #-2
2232 and r3, r3, r4
2233 wpush8 r3
2234 b uxn_decode
2235
2236and2k:
2237 wpeek16 r3, r5, #-1, #-2
2238 wpeek16 r4, r5, #-3, #-4
2239 and r3, r3, r4
2240 wpush16 r3
2241 b uxn_decode
2242
2243orak:
2244 wpeek8 r3, #-1
2245 wpeek8 r4, #-2
2246 orr r3, r3, r4
2247 wpush8 r3
2248 b uxn_decode
2249
2250ora2k:
2251 wpeek16 r3, r5, #-1, #-2
2252 wpeek16 r4, r5, #-3, #-4
2253 orr r3, r3, r4
2254 wpush16 r3
2255 b uxn_decode
2256
2257eork:
2258 wpeek8 r3, #-1
2259 wpeek8 r4, #-2
2260 eor r3, r3, r4
2261 wpush8 r3
2262 b uxn_decode
2263
2264eor2k:
2265 wpeek16 r3, r5, #-1, #-2
2266 wpeek16 r4, r5, #-3, #-4
2267 eor r3, r3, r4
2268 wpush16 r3
2269 b uxn_decode
2270
2271sftk:
2272 wpeek8 r4, #-1
2273 wpeek8 r3, #-2
2274 lsr r5, r4, #4
2275 and r4, #0x0f
2276 lsr r3, r3, r4
2277 lsl r3, r3, r5
2278 wpush8 r3
2279 b uxn_decode
2280
2281sft2k:
2282 wpeek8 r4, #-1
2283 wpeek16 r3, r5, #-2, #-3
2284 lsr r5, r4, #4
2285 and r4, #0x0f
2286 lsr r3, r3, r4
2287 lsl r3, r3, r5
2288 wpush16 r3
2289 b uxn_decode
2290
2291.ltorg
2292.align 2
2293
2294inckr:
2295 rpeek8 r3, #-1
2296 add r3, #1
2297 rpush8 r3
2298 b uxn_decode
2299
2300inc2kr:
2301 rpeek16 r3, r5, #-1, #-2
2302 add r3, r3, #1
2303 rpush16 r3
2304 b uxn_decode
2305
2306popkr:
2307 b uxn_decode
2308
2309pop2kr:
2310 b uxn_decode
2311
2312nipkr:
2313 rpeek8 r3, #-1
2314 wpush8 r3
2315 b uxn_decode
2316
2317nip2kr:
2318 rpeek16 r3, r5, #-1, #-2
2319 rpush16 r3
2320 b uxn_decode
2321
2322swpkr:
2323 rpeek8 r3, #-1
2324 rpeek8 r4, #-2
2325 rpush8 r3
2326 rpush8 r4
2327 b uxn_decode
2328
2329swp2kr:
2330 rpeek16 r3, r5, #-1, #-2
2331 rpeek16 r4, r5, #-3, #-4
2332 rpush16 r3
2333 rpush16 r4
2334 b uxn_decode
2335
2336rotkr:
2337 rpeek8 r5, #-1
2338 rpeek8 r4, #-2
2339 rpeek8 r3, #-3
2340 rpush8 r4
2341 rpush8 r5
2342 rpush8 r3
2343 b uxn_decode
2344
2345rot2kr:
2346 rpeek16 r5, r6, #-1, #-2
2347 rpeek16 r4, r6, #-3, #-4
2348 rpeek16 r3, r6, #-5, #-6
2349 rpush16 r4
2350 rpush16 r5
2351 rpush16 r3
2352 b uxn_decode
2353
2354dupkr:
2355 rpeek8 r3, #-1
2356 rpush8 r3
2357 rpush8 r3
2358 b uxn_decode
2359
2360dup2kr:
2361 rpeek8 r3, #-2
2362 rpeek8 r4, #-1
2363 rpush8 r3
2364 rpush8 r4
2365 rpush8 r3
2366 rpush8 r4
2367 b uxn_decode
2368
2369ovrkr:
2370 rpeek8 r3, #-2
2371 rpeek8 r4, #-1
2372 rpush8 r3
2373 rpush8 r4
2374 rpush8 r3
2375 b uxn_decode
2376
2377ovr2kr:
2378 rpeek8 r3, #-4
2379 rpeek8 r4, #-3
2380 rpeek8 r5, #-2
2381 rpeek8 r6, #-1
2382 rpush8 r3
2383 rpush8 r4
2384 rpush8 r5
2385 rpush8 r6
2386 rpush8 r3
2387 rpush8 r4
2388 b uxn_decode
2389
2390equkr:
2391 rpeek8 r3, #-1
2392 rpeek8 r4, #-2
2393 sub r3, r4, r3
2394 rsbs r4, r3, #0
2395 adc r4, r4, r3
2396 rpush8 r4
2397 b uxn_decode
2398
2399equ2kr:
2400 rpeek16 r3, r5, #-1, #-2
2401 rpeek16 r4, r5, #-3, #-4
2402 sub r3, r4, r3
2403 rsbs r4, r3, #0
2404 adc r4, r4, r3
2405 rpush8 r4
2406 b uxn_decode
2407
2408neqkr:
2409 rpeek8 r3, #-1
2410 rpeek8 r4, #-2
2411 subs r3, r4, r3
2412 movne r3, #1
2413 rpush8 r3
2414 b uxn_decode
2415
2416neq2kr:
2417 rpeek16 r3, r5, #-1, #-2
2418 rpeek16 r4, r5, #-3, #-4
2419 subs r3, r4, r3
2420 movne r3, #1
2421 rpush8 r3
2422 b uxn_decode
2423
2424gthkr:
2425 rpeek8 r3, #-1
2426 rpeek8 r4, #-2
2427 cmp r4, r3
2428 movls r3, #0
2429 movhi r3, #1
2430 rpush8 r3
2431 b uxn_decode
2432
2433gth2kr:
2434 rpeek16 r3, r5, #-1, #-2
2435 rpeek16 r4, r5, #-3, #-4
2436 cmp r4, r3
2437 movls r3, #0
2438 movhi r3, #1
2439 rpush8 r3
2440 b uxn_decode
2441
2442lthkr:
2443 rpeek8 r3, #-1
2444 rpeek8 r4, #-2
2445 cmp r4, r3
2446 movcs r3, #0
2447 movcc r3, #1
2448 rpush8 r3
2449 b uxn_decode
2450
2451lth2kr:
2452 rpeek16 r3, r5, #-1, #-2
2453 rpeek16 r4, r5, #-3, #-4
2454 cmp r4, r3
2455 movcs r3, #0
2456 movcc r3, #1
2457 rpush8 r3
2458 b uxn_decode
2459
2460jmpkr:
2461 rpeek8s r3, #-1
2462 add r0, r3
2463 b uxn_decode
2464
2465jmp2kr:
2466 rpeek16 r3, r5, #-1, #-2
2467 mov r0, r7
2468 add r0, r0, r3
2469 b uxn_decode
2470
2471jcnkr:
2472 rpeek8s r3, #-1
2473 rpeek8 r4, #-2
2474 cmp r4, #0
2475 addne r0, r3
2476 b uxn_decode
2477
2478jcn2kr:
2479 rpeek16 r3, r5, #-1, #-2
2480 rpeek8 r4, #-3
2481 cmp r4, #0
2482 movne r0, r7
2483 cmp r4, #0
2484 addne r0, r0, r3
2485 b uxn_decode
2486
2487jsrkr:
2488 mov r3, r0
2489 sub r3, r3, r7
2490 rpeek8s r4, #-1
2491 rpush16 r3
2492 add r0, r4
2493 b uxn_decode
2494
2495jsr2kr:
2496 mov r3, r0
2497 sub r3, r3, r7
2498 rpeek16 r4, r5, #-1, #-2
2499 rpush16 r3
2500 mov r0, r7
2501 add r0, r0, r4
2502 b uxn_decode
2503
2504sthkr:
2505 rpeek8 r3, #-1
2506 wpush8 r3
2507 b uxn_decode
2508
2509sth2kr:
2510 rpeek16 r3, r5, #-1, #-2
2511 wpush16 r3
2512 b uxn_decode
2513
2514ldzkr:
2515 rpeek8 r3, #-1
2516 zload8 r4, r3
2517 rpush8 r4
2518 b uxn_decode
2519
2520ldz2kr:
2521 rpeek8 r3, #-1
2522 zload8 r4, r3
2523 rpush8 r4
2524 add r3, #1
2525 zload8 r4, r3
2526 rpush8 r4
2527 b uxn_decode
2528
2529stzkr:
2530 rpeek8 r3, #-1
2531 rpeek8 r4, #-2
2532 zsave8 r4, r3
2533 b uxn_decode
2534
2535stz2kr:
2536 rpeek8 r3, #-1
2537 rpeek16 r4, r5, #-2, #-3
2538 zsave16 r4, r3
2539 b uxn_decode
2540
2541ldrkr:
2542 rpeek8s r4, #-1
2543 rload8 r3, r4
2544 rpush8 r3
2545 b uxn_decode
2546
2547ldr2kr:
2548 rpeek8s r4, #-1
2549 rload8 r3, r4
2550 rpush8 r3
2551 add r4, #1
2552 rload8 r3, r4
2553 rpush8 r3
2554 b uxn_decode
2555
2556strkr:
2557 rpeek8s r4, #-1
2558 rpeek8 r3, #-2
2559 rsave8 r3, r4
2560 b uxn_decode
2561
2562str2kr:
2563 rpeek8s r4, #-1
2564 rpeek16 r3, r5, #-1, #-2
2565 rsave16 r3, r4
2566 b uxn_decode
2567
2568ldakr:
2569 rpeek16 r4, r5, #-1, #-2
2570 aload8 r3, r4
2571 rpush8 r3
2572 b uxn_decode
2573
2574lda2kr:
2575 rpeek16 r4, r5, #-1, #-2
2576 aload8 r3, r4
2577 rpush8 r3
2578 add r4, #1
2579 aload8 r3, r4
2580 rpush8 r3
2581 b uxn_decode
2582
2583stakr:
2584 rpeek16 r4, r5, #-1, #-2
2585 rpeek8 r3, #-3
2586 asave8 r3, r4
2587 b uxn_decode
2588
2589sta2kr:
2590 rpeek16 r4, r5, #-1, #-2
2591 rpeek16 r3, r5, #-3, #-4
2592 asave16 r3, r4
2593 b uxn_decode
2594
2595addkr:
2596 rpeek8 r3, #-1
2597 rpeek8 r4, #-2
2598 add r3, r3, r4
2599 rpush8 r3
2600 b uxn_decode
2601
2602add2kr:
2603 rpeek16 r3, r5, #-1, #-2
2604 rpeek16 r4, r5, #-3, #-4
2605 add r3, r3, r4
2606 rpush16 r3
2607 b uxn_decode
2608
2609subkr:
2610 rpeek8 r3, #-1
2611 rpeek8 r4, #-2
2612 sub r4, r4, r3
2613 rpush8 r4
2614 b uxn_decode
2615
2616sub2kr:
2617 rpeek16 r3, r5, #-1, #-2
2618 rpeek16 r4, r5, #-3, #-4
2619 sub r3, r4, r3
2620 rpush16 r3
2621 b uxn_decode
2622
2623mulkr:
2624 rpeek8 r3, #-1
2625 rpeek8 r4, #-2
2626 mul r4, r3, r4
2627 rpush8 r4
2628 b uxn_decode
2629
2630mul2kr:
2631 rpeek16 r3, r5, #-1, #-2
2632 rpeek16 r4, r5, #-3, #-4
2633 mul r3, r4, r3
2634 rpush16 r3
2635 b uxn_decode
2636
2637divkr:
2638 rpeek8 r3, #-1
2639 rpeek8 r4, #-2
2640 push {r0, r1, r2, r7, lr}
2641 mov r1, r3
2642 mov r0, r4
2643 bl __aeabi_uidiv
2644 mov r3, r0
2645 pop {r0, r1, r2, r7, lr}
2646 rpush8 r3
2647 b uxn_decode
2648
2649div2kr:
2650 rpeek16 r3, r5, #-1, #-2
2651 rpeek16 r4, r5, #-3, #-4
2652 push {r0, r1, r2, r7, lr}
2653 mov r1, r3
2654 mov r0, r4
2655 bl __aeabi_uidiv
2656 mov r3, r0
2657 pop {r0, r1, r2, r7, lr}
2658 rpush16 r3
2659 b uxn_decode
2660
2661andkr:
2662 rpeek8 r3, #-1
2663 rpeek8 r4, #-2
2664 and r3, r3, r4
2665 rpush8 r3
2666 b uxn_decode
2667
2668and2kr:
2669 rpeek16 r3, r5, #-1, #-2
2670 rpeek16 r4, r5, #-3, #-4
2671 and r3, r3, r4
2672 rpush16 r3
2673 b uxn_decode
2674
2675orakr:
2676 rpeek8 r3, #-1
2677 rpeek8 r4, #-2
2678 orr r3, r3, r4
2679 rpush8 r3
2680 b uxn_decode
2681
2682ora2kr:
2683 rpeek16 r3, r5, #-1, #-2
2684 rpeek16 r4, r5, #-3, #-4
2685 orr r3, r3, r4
2686 rpush16 r3
2687 b uxn_decode
2688
2689eorkr:
2690 rpeek8 r3, #-1
2691 rpeek8 r4, #-2
2692 eor r3, r3, r4
2693 rpush8 r3
2694 b uxn_decode
2695
2696eor2kr:
2697 rpeek16 r3, r5, #-1, #-2
2698 rpeek16 r4, r5, #-3, #-4
2699 eor r3, r3, r4
2700 rpush16 r3
2701 b uxn_decode
2702
2703sftkr:
2704 rpeek8 r4, #-1
2705 rpeek8 r3, #-2
2706 lsr r5, r4, #4
2707 and r4, #0x0f
2708 lsr r3, r3, r4
2709 lsl r3, r3, r5
2710 rpush8 r3
2711 b uxn_decode
2712
2713sft2kr:
2714 rpeek8 r4, #-1
2715 rpeek16 r3, r5, #-2, #-3
2716 lsr r5, r4, #4
2717 and r4, #0x0f
2718 lsr r3, r3, r4
2719 lsl r3, r3, r5
2720 rpush16 r3
2721 b uxn_decode
diff --git a/src/uxn.c b/src/uxn.c
deleted file mode 100644
index a8fe7ac..0000000
--- a/src/uxn.c
+++ /dev/null
@@ -1,4269 +0,0 @@
1#include <stdio.h>
2#include "uxn.h"
3
4#define NO_STACK_CHECKS
5
6/*
7Copyright (u) 2021 Devine Lu Linvega
8Copyright (u) 2021 Andrew Alderwick
9
10Permission to use, copy, modify, and distribute this software for any
11purpose with or without fee is hereby granted, provided that the above
12copyright notice and this permission notice appear in all copies.
13
14THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
15WITH REGARD TO THIS SOFTWARE.
16*/
17
18/*
19 ^
20/!\ THIS FILE IS AUTOMATICALLY GENERATED
21---
22
23Its contents can get overwritten with the processed contents of src/uxn.c.
24See etc/mkuxn-fast.moon for instructions.
25
26*/
27
28#define MODE_RETURN 0x40
29#define MODE_KEEP 0x80
30
31IWRAM_CODE
32int
33uxn_eval(Uxn *u, u16 vec)
34{
35 u8 instr;
36 if(!vec || u->dev[0].dat[0xf])
37 return 0;
38 u->ram.ptr = vec;
39 if(u->wst.ptr > 0xf8) u->wst.ptr = 0xf8;
40 while((instr = u->ram.dat[u->ram.ptr++])) {
41 switch(instr) {
42#pragma GCC diagnostic push
43#pragma GCC diagnostic ignored "-Wunused-value"
44#pragma GCC diagnostic ignored "-Wunused-variable"
45 case 0x00: /* LIT */
46 case 0x80: /* LITk */
47 __asm__("evaluxn_00_LIT:");
48 {
49 u->wst.dat[u->wst.ptr] = mempeek8(u->ram.dat, u->ram.ptr++);
50#ifndef NO_STACK_CHECKS
51 if(__builtin_expect(u->wst.ptr > 254, 0)) {
52 u->wst.error = 2;
53 goto error;
54 }
55#endif
56 u->wst.ptr += 1;
57 }
58 break;
59 case 0x01: /* INC */
60 __asm__("evaluxn_01_INC:");
61 {
62 u8 a = u->wst.dat[u->wst.ptr - 1];
63 u->wst.dat[u->wst.ptr - 1] = a + 1;
64#ifndef NO_STACK_CHECKS
65 if(__builtin_expect(u->wst.ptr < 1, 0)) {
66 u->wst.error = 1;
67 goto error;
68 }
69#endif
70 }
71 break;
72 case 0x02: /* POP */
73 __asm__("evaluxn_02_POP:");
74 {
75 u->wst.dat[u->wst.ptr - 1];
76#ifndef NO_STACK_CHECKS
77 if(__builtin_expect(u->wst.ptr < 1, 0)) {
78 u->wst.error = 1;
79 goto error;
80 }
81#endif
82 u->wst.ptr -= 1;
83 }
84 break;
85 case 0x06: /* DUP */
86 __asm__("evaluxn_03_DUP:");
87 {
88 u8 a = u->wst.dat[u->wst.ptr - 1];
89 u->wst.dat[u->wst.ptr] = a;
90#ifndef NO_STACK_CHECKS
91 if(__builtin_expect(u->wst.ptr < 1, 0)) {
92 u->wst.error = 1;
93 goto error;
94 }
95 if(__builtin_expect(u->wst.ptr > 254, 0)) {
96 u->wst.error = 2;
97 goto error;
98 }
99#endif
100 u->wst.ptr += 1;
101 }
102 break;
103 case 0x03: /* NIP */
104 __asm__("evaluxn_04_NIP:");
105 {
106 u8 a = u->wst.dat[u->wst.ptr - 1];
107 u->wst.dat[u->wst.ptr - 2];
108 u->wst.dat[u->wst.ptr - 2] = a;
109#ifndef NO_STACK_CHECKS
110 if(__builtin_expect(u->wst.ptr < 2, 0)) {
111 u->wst.error = 1;
112 goto error;
113 }
114#endif
115 u->wst.ptr -= 1;
116 }
117 break;
118 case 0x04: /* SWP */
119 __asm__("evaluxn_05_SWP:");
120 {
121 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
122 u->wst.dat[u->wst.ptr - 2] = a;
123 u->wst.dat[u->wst.ptr - 1] = b;
124#ifndef NO_STACK_CHECKS
125 if(__builtin_expect(u->wst.ptr < 2, 0)) {
126 u->wst.error = 1;
127 goto error;
128 }
129#endif
130 }
131 break;
132 case 0x07: /* OVR */
133 __asm__("evaluxn_06_OVR:");
134 {
135 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
136 u->wst.dat[u->wst.ptr] = b;
137#ifndef NO_STACK_CHECKS
138 if(__builtin_expect(u->wst.ptr < 2, 0)) {
139 u->wst.error = 1;
140 goto error;
141 }
142 if(__builtin_expect(u->wst.ptr > 254, 0)) {
143 u->wst.error = 2;
144 goto error;
145 }
146#endif
147 u->wst.ptr += 1;
148 }
149 break;
150 case 0x05: /* ROT */
151 __asm__("evaluxn_07_ROT:");
152 {
153 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2], c = u->wst.dat[u->wst.ptr - 3];
154 u->wst.dat[u->wst.ptr - 3] = b;
155 u->wst.dat[u->wst.ptr - 2] = a;
156 u->wst.dat[u->wst.ptr - 1] = c;
157#ifndef NO_STACK_CHECKS
158 if(__builtin_expect(u->wst.ptr < 3, 0)) {
159 u->wst.error = 1;
160 goto error;
161 }
162#endif
163 }
164 break;
165 case 0x08: /* EQU */
166 __asm__("evaluxn_08_EQU:");
167 {
168 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
169 u->wst.dat[u->wst.ptr - 2] = b == a;
170#ifndef NO_STACK_CHECKS
171 if(__builtin_expect(u->wst.ptr < 2, 0)) {
172 u->wst.error = 1;
173 goto error;
174 }
175#endif
176 u->wst.ptr -= 1;
177 }
178 break;
179 case 0x09: /* NEQ */
180 __asm__("evaluxn_09_NEQ:");
181 {
182 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
183 u->wst.dat[u->wst.ptr - 2] = b != a;
184#ifndef NO_STACK_CHECKS
185 if(__builtin_expect(u->wst.ptr < 2, 0)) {
186 u->wst.error = 1;
187 goto error;
188 }
189#endif
190 u->wst.ptr -= 1;
191 }
192 break;
193 case 0x0a: /* GTH */
194 __asm__("evaluxn_0a_GTH:");
195 {
196 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
197 u->wst.dat[u->wst.ptr - 2] = b > a;
198#ifndef NO_STACK_CHECKS
199 if(__builtin_expect(u->wst.ptr < 2, 0)) {
200 u->wst.error = 1;
201 goto error;
202 }
203#endif
204 u->wst.ptr -= 1;
205 }
206 break;
207 case 0x0b: /* LTH */
208 __asm__("evaluxn_0b_LTH:");
209 {
210 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
211 u->wst.dat[u->wst.ptr - 2] = b < a;
212#ifndef NO_STACK_CHECKS
213 if(__builtin_expect(u->wst.ptr < 2, 0)) {
214 u->wst.error = 1;
215 goto error;
216 }
217#endif
218 u->wst.ptr -= 1;
219 }
220 break;
221 case 0x0c: /* JMP */
222 __asm__("evaluxn_0c_JMP:");
223 {
224 u8 a = u->wst.dat[u->wst.ptr - 1];
225 u->ram.ptr += (s8)a;
226#ifndef NO_STACK_CHECKS
227 if(__builtin_expect(u->wst.ptr < 1, 0)) {
228 u->wst.error = 1;
229 goto error;
230 }
231#endif
232 u->wst.ptr -= 1;
233 }
234 break;
235 case 0x0d: /* JCN */
236 __asm__("evaluxn_0d_JCN:");
237 {
238 u8 a = u->wst.dat[u->wst.ptr - 1];
239 if(u->wst.dat[u->wst.ptr - 2]) u->ram.ptr += (s8)a;
240#ifndef NO_STACK_CHECKS
241 if(__builtin_expect(u->wst.ptr < 2, 0)) {
242 u->wst.error = 1;
243 goto error;
244 }
245#endif
246 u->wst.ptr -= 2;
247 }
248 break;
249 case 0x0e: /* JSR */
250 __asm__("evaluxn_0e_JSR:");
251 {
252 u8 a = u->wst.dat[u->wst.ptr - 1];
253 u->rst.dat[u->rst.ptr] = u->ram.ptr >> 8;
254 u->rst.dat[u->rst.ptr + 1] = u->ram.ptr & 0xff;
255 u->ram.ptr += (s8)a;
256#ifndef NO_STACK_CHECKS
257 if(__builtin_expect(u->wst.ptr < 1, 0)) {
258 u->wst.error = 1;
259 goto error;
260 }
261#endif
262 u->wst.ptr -= 1;
263#ifndef NO_STACK_CHECKS
264 if(__builtin_expect(u->rst.ptr > 253, 0)) {
265 u->rst.error = 2;
266 goto error;
267 }
268#endif
269 u->rst.ptr += 2;
270 }
271 break;
272 case 0x0f: /* STH */
273 __asm__("evaluxn_0f_STH:");
274 {
275 u8 a = u->wst.dat[u->wst.ptr - 1];
276 u->rst.dat[u->rst.ptr] = a;
277#ifndef NO_STACK_CHECKS
278 if(__builtin_expect(u->wst.ptr < 1, 0)) {
279 u->wst.error = 1;
280 goto error;
281 }
282#endif
283 u->wst.ptr -= 1;
284#ifndef NO_STACK_CHECKS
285 if(__builtin_expect(u->rst.ptr > 254, 0)) {
286 u->rst.error = 2;
287 goto error;
288 }
289#endif
290 u->rst.ptr += 1;
291 }
292 break;
293 case 0x10: /* LDZ */
294 __asm__("evaluxn_10_LDZ:");
295 {
296 u8 a = u->wst.dat[u->wst.ptr - 1];
297 u->wst.dat[u->wst.ptr - 1] = mempeek8(u->ram.dat, a);
298#ifndef NO_STACK_CHECKS
299 if(__builtin_expect(u->wst.ptr < 1, 0)) {
300 u->wst.error = 1;
301 goto error;
302 }
303#endif
304 }
305 break;
306 case 0x11: /* STZ */
307 __asm__("evaluxn_11_STZ:");
308 {
309 u8 a = u->wst.dat[u->wst.ptr - 1];
310 u8 b = u->wst.dat[u->wst.ptr - 2];
311 mempoke8(u->ram.dat, a, b);
312#ifndef NO_STACK_CHECKS
313 if(__builtin_expect(u->wst.ptr < 2, 0)) {
314 u->wst.error = 1;
315 goto error;
316 }
317#endif
318 u->wst.ptr -= 2;
319 }
320 break;
321 case 0x12: /* LDR */
322 __asm__("evaluxn_12_LDR:");
323 {
324 u8 a = u->wst.dat[u->wst.ptr - 1];
325 u->wst.dat[u->wst.ptr - 1] = mempeek8(u->ram.dat, u->ram.ptr + (s8)a);
326#ifndef NO_STACK_CHECKS
327 if(__builtin_expect(u->wst.ptr < 1, 0)) {
328 u->wst.error = 1;
329 goto error;
330 }
331#endif
332 }
333 break;
334 case 0x13: /* STR */
335 __asm__("evaluxn_13_STR:");
336 {
337 u8 a = u->wst.dat[u->wst.ptr - 1];
338 u8 b = u->wst.dat[u->wst.ptr - 2];
339 mempoke8(u->ram.dat, u->ram.ptr + (s8)a, b);
340#ifndef NO_STACK_CHECKS
341 if(__builtin_expect(u->wst.ptr < 2, 0)) {
342 u->wst.error = 1;
343 goto error;
344 }
345#endif
346 u->wst.ptr -= 2;
347 }
348 break;
349 case 0x14: /* LDA */
350 __asm__("evaluxn_14_LDA:");
351 {
352 u16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8));
353 u->wst.dat[u->wst.ptr - 2] = mempeek8(u->ram.dat, a);
354#ifndef NO_STACK_CHECKS
355 if(__builtin_expect(u->wst.ptr < 2, 0)) {
356 u->wst.error = 1;
357 goto error;
358 }
359#endif
360 u->wst.ptr -= 1;
361 }
362 break;
363 case 0x15: /* STA */
364 __asm__("evaluxn_15_STA:");
365 {
366 u16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8));
367 u8 b = u->wst.dat[u->wst.ptr - 3];
368 mempoke8(u->ram.dat, a, b);
369#ifndef NO_STACK_CHECKS
370 if(__builtin_expect(u->wst.ptr < 3, 0)) {
371 u->wst.error = 1;
372 goto error;
373 }
374#endif
375 u->wst.ptr -= 3;
376 }
377 break;
378 case 0x16: /* DEI */
379 __asm__("evaluxn_16_DEI:");
380 {
381 u8 a = u->wst.dat[u->wst.ptr - 1];
382 u->wst.dat[u->wst.ptr - 1] = devpeek8(&u->dev[a >> 4], a);
383#ifndef NO_STACK_CHECKS
384 if(__builtin_expect(u->wst.ptr < 1, 0)) {
385 u->wst.error = 1;
386 goto error;
387 }
388#endif
389 }
390 break;
391 case 0x17: /* DEO */
392 __asm__("evaluxn_17_DEO:");
393 {
394 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
395 devpoke8(&u->dev[a >> 4], a, b);
396#ifndef NO_STACK_CHECKS
397 if(__builtin_expect(u->wst.ptr < 2, 0)) {
398 u->wst.error = 1;
399 goto error;
400 }
401#endif
402 u->wst.ptr -= 2;
403 }
404 break;
405 case 0x18: /* ADD */
406 __asm__("evaluxn_18_ADD:");
407 {
408 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
409 u->wst.dat[u->wst.ptr - 2] = b + a;
410#ifndef NO_STACK_CHECKS
411 if(__builtin_expect(u->wst.ptr < 2, 0)) {
412 u->wst.error = 1;
413 goto error;
414 }
415#endif
416 u->wst.ptr -= 1;
417 }
418 break;
419 case 0x19: /* SUB */
420 __asm__("evaluxn_19_SUB:");
421 {
422 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
423 u->wst.dat[u->wst.ptr - 2] = b - a;
424#ifndef NO_STACK_CHECKS
425 if(__builtin_expect(u->wst.ptr < 2, 0)) {
426 u->wst.error = 1;
427 goto error;
428 }
429#endif
430 u->wst.ptr -= 1;
431 }
432 break;
433 case 0x1a: /* MUL */
434 __asm__("evaluxn_1a_MUL:");
435 {
436 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
437 u->wst.dat[u->wst.ptr - 2] = b * a;
438#ifndef NO_STACK_CHECKS
439 if(__builtin_expect(u->wst.ptr < 2, 0)) {
440 u->wst.error = 1;
441 goto error;
442 }
443#endif
444 u->wst.ptr -= 1;
445 }
446 break;
447 case 0x1b: /* DIV */
448 __asm__("evaluxn_1b_DIV:");
449 {
450 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
451 if(a == 0) {
452 u->wst.error = 3;
453#ifndef NO_STACK_CHECKS
454 goto error;
455#endif
456 a = 1;
457 }
458 u->wst.dat[u->wst.ptr - 2] = b / a;
459#ifndef NO_STACK_CHECKS
460 if(__builtin_expect(u->wst.ptr < 2, 0)) {
461 u->wst.error = 1;
462 goto error;
463 }
464#endif
465 u->wst.ptr -= 1;
466 }
467 break;
468 case 0x1c: /* AND */
469 __asm__("evaluxn_1c_AND:");
470 {
471 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
472 u->wst.dat[u->wst.ptr - 2] = b & a;
473#ifndef NO_STACK_CHECKS
474 if(__builtin_expect(u->wst.ptr < 2, 0)) {
475 u->wst.error = 1;
476 goto error;
477 }
478#endif
479 u->wst.ptr -= 1;
480 }
481 break;
482 case 0x1d: /* ORA */
483 __asm__("evaluxn_1d_ORA:");
484 {
485 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
486 u->wst.dat[u->wst.ptr - 2] = b | a;
487#ifndef NO_STACK_CHECKS
488 if(__builtin_expect(u->wst.ptr < 2, 0)) {
489 u->wst.error = 1;
490 goto error;
491 }
492#endif
493 u->wst.ptr -= 1;
494 }
495 break;
496 case 0x1e: /* EOR */
497 __asm__("evaluxn_1e_EOR:");
498 {
499 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
500 u->wst.dat[u->wst.ptr - 2] = b ^ a;
501#ifndef NO_STACK_CHECKS
502 if(__builtin_expect(u->wst.ptr < 2, 0)) {
503 u->wst.error = 1;
504 goto error;
505 }
506#endif
507 u->wst.ptr -= 1;
508 }
509 break;
510 case 0x1f: /* SFT */
511 __asm__("evaluxn_1f_SFT:");
512 {
513 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
514 u->wst.dat[u->wst.ptr - 2] = b >> (a & 0x07) << ((a & 0x70) >> 4);
515#ifndef NO_STACK_CHECKS
516 if(__builtin_expect(u->wst.ptr < 2, 0)) {
517 u->wst.error = 1;
518 goto error;
519 }
520#endif
521 u->wst.ptr -= 1;
522 }
523 break;
524 case 0x20: /* LIT2 */
525 case 0xa0: /* LIT2k */
526 __asm__("evaluxn_20_LIT2:");
527 {
528 u->wst.dat[u->wst.ptr] = mempeek8(u->ram.dat, u->ram.ptr++);
529 u->wst.dat[u->wst.ptr + 1] = mempeek8(u->ram.dat, u->ram.ptr++);
530#ifndef NO_STACK_CHECKS
531 if(__builtin_expect(u->wst.ptr > 253, 0)) {
532 u->wst.error = 2;
533 goto error;
534 }
535#endif
536 u->wst.ptr += 2;
537 }
538 break;
539 case 0x21: /* INC2 */
540 __asm__("evaluxn_21_INC2:");
541 {
542 u16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8));
543 u->wst.dat[u->wst.ptr - 2] = (a + 1) >> 8;
544 u->wst.dat[u->wst.ptr - 1] = (a + 1) & 0xff;
545#ifndef NO_STACK_CHECKS
546 if(__builtin_expect(u->wst.ptr < 2, 0)) {
547 u->wst.error = 1;
548 goto error;
549 }
550#endif
551 }
552 break;
553 case 0x22: /* POP2 */
554 __asm__("evaluxn_22_POP2:");
555 {
556 (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8));
557#ifndef NO_STACK_CHECKS
558 if(__builtin_expect(u->wst.ptr < 2, 0)) {
559 u->wst.error = 1;
560 goto error;
561 }
562#endif
563 u->wst.ptr -= 2;
564 }
565 break;
566 case 0x26: /* DUP2 */
567 __asm__("evaluxn_23_DUP2:");
568 {
569 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
570 u->wst.dat[u->wst.ptr] = b;
571 u->wst.dat[u->wst.ptr + 1] = a;
572#ifndef NO_STACK_CHECKS
573 if(__builtin_expect(u->wst.ptr < 2, 0)) {
574 u->wst.error = 1;
575 goto error;
576 }
577 if(__builtin_expect(u->wst.ptr > 253, 0)) {
578 u->wst.error = 2;
579 goto error;
580 }
581#endif
582 u->wst.ptr += 2;
583 }
584 break;
585 case 0x23: /* NIP2 */
586 __asm__("evaluxn_24_NIP2:");
587 {
588 u16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8));
589 (u->wst.dat[u->wst.ptr - 3] | (u->wst.dat[u->wst.ptr - 4] << 8));
590 u->wst.dat[u->wst.ptr - 4] = a >> 8;
591 u->wst.dat[u->wst.ptr - 3] = a & 0xff;
592#ifndef NO_STACK_CHECKS
593 if(__builtin_expect(u->wst.ptr < 4, 0)) {
594 u->wst.error = 1;
595 goto error;
596 }
597#endif
598 u->wst.ptr -= 2;
599 }
600 break;
601 case 0x24: /* SWP2 */
602 __asm__("evaluxn_25_SWP2:");
603 {
604 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2], c = u->wst.dat[u->wst.ptr - 3], d = u->wst.dat[u->wst.ptr - 4];
605 u->wst.dat[u->wst.ptr - 4] = b;
606 u->wst.dat[u->wst.ptr - 3] = a;
607 u->wst.dat[u->wst.ptr - 2] = d;
608 u->wst.dat[u->wst.ptr - 1] = c;
609#ifndef NO_STACK_CHECKS
610 if(__builtin_expect(u->wst.ptr < 4, 0)) {
611 u->wst.error = 1;
612 goto error;
613 }
614#endif
615 }
616 break;
617 case 0x27: /* OVR2 */
618 __asm__("evaluxn_26_OVR2:");
619 {
620 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2], c = u->wst.dat[u->wst.ptr - 3], d = u->wst.dat[u->wst.ptr - 4];
621 u->wst.dat[u->wst.ptr] = d;
622 u->wst.dat[u->wst.ptr + 1] = c;
623#ifndef NO_STACK_CHECKS
624 if(__builtin_expect(u->wst.ptr < 4, 0)) {
625 u->wst.error = 1;
626 goto error;
627 }
628 if(__builtin_expect(u->wst.ptr > 253, 0)) {
629 u->wst.error = 2;
630 goto error;
631 }
632#endif
633 u->wst.ptr += 2;
634 }
635 break;
636 case 0x25: /* ROT2 */
637 __asm__("evaluxn_27_ROT2:");
638 {
639 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2], c = u->wst.dat[u->wst.ptr - 3], d = u->wst.dat[u->wst.ptr - 4], e = u->wst.dat[u->wst.ptr - 5], f = u->wst.dat[u->wst.ptr - 6];
640 u->wst.dat[u->wst.ptr - 6] = d;
641 u->wst.dat[u->wst.ptr - 5] = c;
642 u->wst.dat[u->wst.ptr - 4] = b;
643 u->wst.dat[u->wst.ptr - 3] = a;
644 u->wst.dat[u->wst.ptr - 2] = f;
645 u->wst.dat[u->wst.ptr - 1] = e;
646#ifndef NO_STACK_CHECKS
647 if(__builtin_expect(u->wst.ptr < 6, 0)) {
648 u->wst.error = 1;
649 goto error;
650 }
651#endif
652 }
653 break;
654 case 0x28: /* EQU2 */
655 __asm__("evaluxn_28_EQU2:");
656 {
657 u16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)), b = (u->wst.dat[u->wst.ptr - 3] | (u->wst.dat[u->wst.ptr - 4] << 8));
658 u->wst.dat[u->wst.ptr - 4] = b == a;
659#ifndef NO_STACK_CHECKS
660 if(__builtin_expect(u->wst.ptr < 4, 0)) {
661 u->wst.error = 1;
662 goto error;
663 }
664#endif
665 u->wst.ptr -= 3;
666 }
667 break;
668 case 0x29: /* NEQ2 */
669 __asm__("evaluxn_29_NEQ2:");
670 {
671 u16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)), b = (u->wst.dat[u->wst.ptr - 3] | (u->wst.dat[u->wst.ptr - 4] << 8));
672 u->wst.dat[u->wst.ptr - 4] = b != a;
673#ifndef NO_STACK_CHECKS
674 if(__builtin_expect(u->wst.ptr < 4, 0)) {
675 u->wst.error = 1;
676 goto error;
677 }
678#endif
679 u->wst.ptr -= 3;
680 }
681 break;
682 case 0x2a: /* GTH2 */
683 __asm__("evaluxn_2a_GTH2:");
684 {
685 u16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)), b = (u->wst.dat[u->wst.ptr - 3] | (u->wst.dat[u->wst.ptr - 4] << 8));
686 u->wst.dat[u->wst.ptr - 4] = b > a;
687#ifndef NO_STACK_CHECKS
688 if(__builtin_expect(u->wst.ptr < 4, 0)) {
689 u->wst.error = 1;
690 goto error;
691 }
692#endif
693 u->wst.ptr -= 3;
694 }
695 break;
696 case 0x2b: /* LTH2 */
697 __asm__("evaluxn_2b_LTH2:");
698 {
699 u16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)), b = (u->wst.dat[u->wst.ptr - 3] | (u->wst.dat[u->wst.ptr - 4] << 8));
700 u->wst.dat[u->wst.ptr - 4] = b < a;
701#ifndef NO_STACK_CHECKS
702 if(__builtin_expect(u->wst.ptr < 4, 0)) {
703 u->wst.error = 1;
704 goto error;
705 }
706#endif
707 u->wst.ptr -= 3;
708 }
709 break;
710 case 0x2c: /* JMP2 */
711 __asm__("evaluxn_2c_JMP2:");
712 {
713 u->ram.ptr = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8));
714#ifndef NO_STACK_CHECKS
715 if(__builtin_expect(u->wst.ptr < 2, 0)) {
716 u->wst.error = 1;
717 goto error;
718 }
719#endif
720 u->wst.ptr -= 2;
721 }
722 break;
723 case 0x2d: /* JCN2 */
724 __asm__("evaluxn_2d_JCN2:");
725 {
726 u16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8));
727 if(u->wst.dat[u->wst.ptr - 3]) u->ram.ptr = a;
728#ifndef NO_STACK_CHECKS
729 if(__builtin_expect(u->wst.ptr < 3, 0)) {
730 u->wst.error = 1;
731 goto error;
732 }
733#endif
734 u->wst.ptr -= 3;
735 }
736 break;
737 case 0x2e: /* JSR2 */
738 __asm__("evaluxn_2e_JSR2:");
739 {
740 u->rst.dat[u->rst.ptr] = u->ram.ptr >> 8;
741 u->rst.dat[u->rst.ptr + 1] = u->ram.ptr & 0xff;
742 u->ram.ptr = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8));
743#ifndef NO_STACK_CHECKS
744 if(__builtin_expect(u->wst.ptr < 2, 0)) {
745 u->wst.error = 1;
746 goto error;
747 }
748#endif
749 u->wst.ptr -= 2;
750#ifndef NO_STACK_CHECKS
751 if(__builtin_expect(u->rst.ptr > 253, 0)) {
752 u->rst.error = 2;
753 goto error;
754 }
755#endif
756 u->rst.ptr += 2;
757 }
758 break;
759 case 0x2f: /* STH2 */
760 __asm__("evaluxn_2f_STH2:");
761 {
762 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
763 u->rst.dat[u->rst.ptr] = b;
764 u->rst.dat[u->rst.ptr + 1] = a;
765#ifndef NO_STACK_CHECKS
766 if(__builtin_expect(u->wst.ptr < 2, 0)) {
767 u->wst.error = 1;
768 goto error;
769 }
770#endif
771 u->wst.ptr -= 2;
772#ifndef NO_STACK_CHECKS
773 if(__builtin_expect(u->rst.ptr > 253, 0)) {
774 u->rst.error = 2;
775 goto error;
776 }
777#endif
778 u->rst.ptr += 2;
779 }
780 break;
781 case 0x30: /* LDZ2 */
782 __asm__("evaluxn_30_LDZ2:");
783 {
784 u8 a = u->wst.dat[u->wst.ptr - 1];
785 u->wst.dat[u->wst.ptr - 1] = mempeek8(u->ram.dat, a);
786 u->wst.dat[u->wst.ptr] = mempeek8(u->ram.dat, a + 1);
787#ifndef NO_STACK_CHECKS
788 if(__builtin_expect(u->wst.ptr < 1, 0)) {
789 u->wst.error = 1;
790 goto error;
791 }
792 if(__builtin_expect(u->wst.ptr > 254, 0)) {
793 u->wst.error = 2;
794 goto error;
795 }
796#endif
797 u->wst.ptr += 1;
798 }
799 break;
800 case 0x31: /* STZ2 */
801 __asm__("evaluxn_31_STZ2:");
802 {
803 u8 a = u->wst.dat[u->wst.ptr - 1];
804 u16 b = (u->wst.dat[u->wst.ptr - 2] | (u->wst.dat[u->wst.ptr - 3] << 8));
805 mempoke16(u->ram.dat, a, b);
806#ifndef NO_STACK_CHECKS
807 if(__builtin_expect(u->wst.ptr < 3, 0)) {
808 u->wst.error = 1;
809 goto error;
810 }
811#endif
812 u->wst.ptr -= 3;
813 }
814 break;
815 case 0x32: /* LDR2 */
816 __asm__("evaluxn_32_LDR2:");
817 {
818 u8 a = u->wst.dat[u->wst.ptr - 1];
819 u->wst.dat[u->wst.ptr - 1] = mempeek8(u->ram.dat, u->ram.ptr + (s8)a);
820 u->wst.dat[u->wst.ptr] = mempeek8(u->ram.dat, u->ram.ptr + (s8)a + 1);
821#ifndef NO_STACK_CHECKS
822 if(__builtin_expect(u->wst.ptr < 1, 0)) {
823 u->wst.error = 1;
824 goto error;
825 }
826 if(__builtin_expect(u->wst.ptr > 254, 0)) {
827 u->wst.error = 2;
828 goto error;
829 }
830#endif
831 u->wst.ptr += 1;
832 }
833 break;
834 case 0x33: /* STR2 */
835 __asm__("evaluxn_33_STR2:");
836 {
837 u8 a = u->wst.dat[u->wst.ptr - 1];
838 u16 b = (u->wst.dat[u->wst.ptr - 2] | (u->wst.dat[u->wst.ptr - 3] << 8));
839 mempoke16(u->ram.dat, u->ram.ptr + (s8)a, b);
840#ifndef NO_STACK_CHECKS
841 if(__builtin_expect(u->wst.ptr < 3, 0)) {
842 u->wst.error = 1;
843 goto error;
844 }
845#endif
846 u->wst.ptr -= 3;
847 }
848 break;
849 case 0x34: /* LDA2 */
850 __asm__("evaluxn_34_LDA2:");
851 {
852 u16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8));
853 u->wst.dat[u->wst.ptr - 2] = mempeek8(u->ram.dat, a);
854 u->wst.dat[u->wst.ptr - 1] = mempeek8(u->ram.dat, a + 1);
855#ifndef NO_STACK_CHECKS
856 if(__builtin_expect(u->wst.ptr < 2, 0)) {
857 u->wst.error = 1;
858 goto error;
859 }
860#endif
861 }
862 break;
863 case 0x35: /* STA2 */
864 __asm__("evaluxn_35_STA2:");
865 {
866 u16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8));
867 u16 b = (u->wst.dat[u->wst.ptr - 3] | (u->wst.dat[u->wst.ptr - 4] << 8));
868 mempoke16(u->ram.dat, a, b);
869#ifndef NO_STACK_CHECKS
870 if(__builtin_expect(u->wst.ptr < 4, 0)) {
871 u->wst.error = 1;
872 goto error;
873 }
874#endif
875 u->wst.ptr -= 4;
876 }
877 break;
878 case 0x36: /* DEI2 */
879 __asm__("evaluxn_36_DEI2:");
880 {
881 u8 a = u->wst.dat[u->wst.ptr - 1];
882 u->wst.dat[u->wst.ptr - 1] = devpeek8(&u->dev[a >> 4], a);
883 u->wst.dat[u->wst.ptr] = devpeek8(&u->dev[a >> 4], a + 1);
884#ifndef NO_STACK_CHECKS
885 if(__builtin_expect(u->wst.ptr < 1, 0)) {
886 u->wst.error = 1;
887 goto error;
888 }
889 if(__builtin_expect(u->wst.ptr > 254, 0)) {
890 u->wst.error = 2;
891 goto error;
892 }
893#endif
894 u->wst.ptr += 1;
895 }
896 break;
897 case 0x37: /* DEO2 */
898 __asm__("evaluxn_37_DEO2:");
899 {
900 u8 a = u->wst.dat[u->wst.ptr - 1];
901 u16 b = (u->wst.dat[u->wst.ptr - 2] | (u->wst.dat[u->wst.ptr - 3] << 8));
902 devpoke16(&u->dev[a >> 4], a, b);
903#ifndef NO_STACK_CHECKS
904 if(__builtin_expect(u->wst.ptr < 3, 0)) {
905 u->wst.error = 1;
906 goto error;
907 }
908#endif
909 u->wst.ptr -= 3;
910 }
911 break;
912 case 0x38: /* ADD2 */
913 __asm__("evaluxn_38_ADD2:");
914 {
915 u16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)), b = (u->wst.dat[u->wst.ptr - 3] | (u->wst.dat[u->wst.ptr - 4] << 8));
916 u->wst.dat[u->wst.ptr - 4] = (b + a) >> 8;
917 u->wst.dat[u->wst.ptr - 3] = (b + a) & 0xff;
918#ifndef NO_STACK_CHECKS
919 if(__builtin_expect(u->wst.ptr < 4, 0)) {
920 u->wst.error = 1;
921 goto error;
922 }
923#endif
924 u->wst.ptr -= 2;
925 }
926 break;
927 case 0x39: /* SUB2 */
928 __asm__("evaluxn_39_SUB2:");
929 {
930 u16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)), b = (u->wst.dat[u->wst.ptr - 3] | (u->wst.dat[u->wst.ptr - 4] << 8));
931 u->wst.dat[u->wst.ptr - 4] = (b - a) >> 8;
932 u->wst.dat[u->wst.ptr - 3] = (b - a) & 0xff;
933#ifndef NO_STACK_CHECKS
934 if(__builtin_expect(u->wst.ptr < 4, 0)) {
935 u->wst.error = 1;
936 goto error;
937 }
938#endif
939 u->wst.ptr -= 2;
940 }
941 break;
942 case 0x3a: /* MUL2 */
943 __asm__("evaluxn_3a_MUL2:");
944 {
945 u16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)), b = (u->wst.dat[u->wst.ptr - 3] | (u->wst.dat[u->wst.ptr - 4] << 8));
946 u->wst.dat[u->wst.ptr - 4] = (b * a) >> 8;
947 u->wst.dat[u->wst.ptr - 3] = (b * a) & 0xff;
948#ifndef NO_STACK_CHECKS
949 if(__builtin_expect(u->wst.ptr < 4, 0)) {
950 u->wst.error = 1;
951 goto error;
952 }
953#endif
954 u->wst.ptr -= 2;
955 }
956 break;
957 case 0x3b: /* DIV2 */
958 __asm__("evaluxn_3b_DIV2:");
959 {
960 u16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)), b = (u->wst.dat[u->wst.ptr - 3] | (u->wst.dat[u->wst.ptr - 4] << 8));
961 if(a == 0) {
962 u->wst.error = 3;
963#ifndef NO_STACK_CHECKS
964 goto error;
965#endif
966 a = 1;
967 }
968 u->wst.dat[u->wst.ptr - 4] = (b / a) >> 8;
969 u->wst.dat[u->wst.ptr - 3] = (b / a) & 0xff;
970#ifndef NO_STACK_CHECKS
971 if(__builtin_expect(u->wst.ptr < 4, 0)) {
972 u->wst.error = 1;
973 goto error;
974 }
975#endif
976 u->wst.ptr -= 2;
977 }
978 break;
979 case 0x3c: /* AND2 */
980 __asm__("evaluxn_3c_AND2:");
981 {
982 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2], c = u->wst.dat[u->wst.ptr - 3], d = u->wst.dat[u->wst.ptr - 4];
983 u->wst.dat[u->wst.ptr - 4] = d & b;
984 u->wst.dat[u->wst.ptr - 3] = c & a;
985#ifndef NO_STACK_CHECKS
986 if(__builtin_expect(u->wst.ptr < 4, 0)) {
987 u->wst.error = 1;
988 goto error;
989 }
990#endif
991 u->wst.ptr -= 2;
992 }
993 break;
994 case 0x3d: /* ORA2 */
995 __asm__("evaluxn_3d_ORA2:");
996 {
997 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2], c = u->wst.dat[u->wst.ptr - 3], d = u->wst.dat[u->wst.ptr - 4];
998 u->wst.dat[u->wst.ptr - 4] = d | b;
999 u->wst.dat[u->wst.ptr - 3] = c | a;
1000#ifndef NO_STACK_CHECKS
1001 if(__builtin_expect(u->wst.ptr < 4, 0)) {
1002 u->wst.error = 1;
1003 goto error;
1004 }
1005#endif
1006 u->wst.ptr -= 2;
1007 }
1008 break;
1009 case 0x3e: /* EOR2 */
1010 __asm__("evaluxn_3e_EOR2:");
1011 {
1012 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2], c = u->wst.dat[u->wst.ptr - 3], d = u->wst.dat[u->wst.ptr - 4];
1013 u->wst.dat[u->wst.ptr - 4] = d ^ b;
1014 u->wst.dat[u->wst.ptr - 3] = c ^ a;
1015#ifndef NO_STACK_CHECKS
1016 if(__builtin_expect(u->wst.ptr < 4, 0)) {
1017 u->wst.error = 1;
1018 goto error;
1019 }
1020#endif
1021 u->wst.ptr -= 2;
1022 }
1023 break;
1024 case 0x3f: /* SFT2 */
1025 __asm__("evaluxn_3f_SFT2:");
1026 {
1027 u8 a = u->wst.dat[u->wst.ptr - 1];
1028 u16 b = (u->wst.dat[u->wst.ptr - 2] | (u->wst.dat[u->wst.ptr - 3] << 8));
1029 u->wst.dat[u->wst.ptr - 3] = (b >> (a & 0x0f) << ((a & 0xf0) >> 4)) >> 8;
1030 u->wst.dat[u->wst.ptr - 2] = (b >> (a & 0x0f) << ((a & 0xf0) >> 4)) & 0xff;
1031#ifndef NO_STACK_CHECKS
1032 if(__builtin_expect(u->wst.ptr < 3, 0)) {
1033 u->wst.error = 1;
1034 goto error;
1035 }
1036#endif
1037 u->wst.ptr -= 1;
1038 }
1039 break;
1040 case 0x40: /* LITr */
1041 case 0xc0: /* LITkr */
1042 __asm__("evaluxn_40_LITr:");
1043 {
1044 u->rst.dat[u->rst.ptr] = mempeek8(u->ram.dat, u->ram.ptr++);
1045#ifndef NO_STACK_CHECKS
1046 if(__builtin_expect(u->rst.ptr > 254, 0)) {
1047 u->rst.error = 2;
1048 goto error;
1049 }
1050#endif
1051 u->rst.ptr += 1;
1052 }
1053 break;
1054 case 0x41: /* INCr */
1055 __asm__("evaluxn_41_INCr:");
1056 {
1057 u8 a = u->rst.dat[u->rst.ptr - 1];
1058 u->rst.dat[u->rst.ptr - 1] = a + 1;
1059#ifndef NO_STACK_CHECKS
1060 if(__builtin_expect(u->rst.ptr < 1, 0)) {
1061 u->rst.error = 1;
1062 goto error;
1063 }
1064#endif
1065 }
1066 break;
1067 case 0x42: /* POPr */
1068 __asm__("evaluxn_42_POPr:");
1069 {
1070 u->rst.dat[u->rst.ptr - 1];
1071#ifndef NO_STACK_CHECKS
1072 if(__builtin_expect(u->rst.ptr < 1, 0)) {
1073 u->rst.error = 1;
1074 goto error;
1075 }
1076#endif
1077 u->rst.ptr -= 1;
1078 }
1079 break;
1080 case 0x46: /* DUPr */
1081 __asm__("evaluxn_43_DUPr:");
1082 {
1083 u8 a = u->rst.dat[u->rst.ptr - 1];
1084 u->rst.dat[u->rst.ptr] = a;
1085#ifndef NO_STACK_CHECKS
1086 if(__builtin_expect(u->rst.ptr < 1, 0)) {
1087 u->rst.error = 1;
1088 goto error;
1089 }
1090 if(__builtin_expect(u->rst.ptr > 254, 0)) {
1091 u->rst.error = 2;
1092 goto error;
1093 }
1094#endif
1095 u->rst.ptr += 1;
1096 }
1097 break;
1098 case 0x43: /* NIPr */
1099 __asm__("evaluxn_44_NIPr:");
1100 {
1101 u8 a = u->rst.dat[u->rst.ptr - 1];
1102 u->rst.dat[u->rst.ptr - 2];
1103 u->rst.dat[u->rst.ptr - 2] = a;
1104#ifndef NO_STACK_CHECKS
1105 if(__builtin_expect(u->rst.ptr < 2, 0)) {
1106 u->rst.error = 1;
1107 goto error;
1108 }
1109#endif
1110 u->rst.ptr -= 1;
1111 }
1112 break;
1113 case 0x44: /* SWPr */
1114 __asm__("evaluxn_45_SWPr:");
1115 {
1116 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
1117 u->rst.dat[u->rst.ptr - 2] = a;
1118 u->rst.dat[u->rst.ptr - 1] = b;
1119#ifndef NO_STACK_CHECKS
1120 if(__builtin_expect(u->rst.ptr < 2, 0)) {
1121 u->rst.error = 1;
1122 goto error;
1123 }
1124#endif
1125 }
1126 break;
1127 case 0x47: /* OVRr */
1128 __asm__("evaluxn_46_OVRr:");
1129 {
1130 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
1131 u->rst.dat[u->rst.ptr] = b;
1132#ifndef NO_STACK_CHECKS
1133 if(__builtin_expect(u->rst.ptr < 2, 0)) {
1134 u->rst.error = 1;
1135 goto error;
1136 }
1137 if(__builtin_expect(u->rst.ptr > 254, 0)) {
1138 u->rst.error = 2;
1139 goto error;
1140 }
1141#endif
1142 u->rst.ptr += 1;
1143 }
1144 break;
1145 case 0x45: /* ROTr */
1146 __asm__("evaluxn_47_ROTr:");
1147 {
1148 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2], c = u->rst.dat[u->rst.ptr - 3];
1149 u->rst.dat[u->rst.ptr - 3] = b;
1150 u->rst.dat[u->rst.ptr - 2] = a;
1151 u->rst.dat[u->rst.ptr - 1] = c;
1152#ifndef NO_STACK_CHECKS
1153 if(__builtin_expect(u->rst.ptr < 3, 0)) {
1154 u->rst.error = 1;
1155 goto error;
1156 }
1157#endif
1158 }
1159 break;
1160 case 0x48: /* EQUr */
1161 __asm__("evaluxn_48_EQUr:");
1162 {
1163 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
1164 u->rst.dat[u->rst.ptr - 2] = b == a;
1165#ifndef NO_STACK_CHECKS
1166 if(__builtin_expect(u->rst.ptr < 2, 0)) {
1167 u->rst.error = 1;
1168 goto error;
1169 }
1170#endif
1171 u->rst.ptr -= 1;
1172 }
1173 break;
1174 case 0x49: /* NEQr */
1175 __asm__("evaluxn_49_NEQr:");
1176 {
1177 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
1178 u->rst.dat[u->rst.ptr - 2] = b != a;
1179#ifndef NO_STACK_CHECKS
1180 if(__builtin_expect(u->rst.ptr < 2, 0)) {
1181 u->rst.error = 1;
1182 goto error;
1183 }
1184#endif
1185 u->rst.ptr -= 1;
1186 }
1187 break;
1188 case 0x4a: /* GTHr */
1189 __asm__("evaluxn_4a_GTHr:");
1190 {
1191 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
1192 u->rst.dat[u->rst.ptr - 2] = b > a;
1193#ifndef NO_STACK_CHECKS
1194 if(__builtin_expect(u->rst.ptr < 2, 0)) {
1195 u->rst.error = 1;
1196 goto error;
1197 }
1198#endif
1199 u->rst.ptr -= 1;
1200 }
1201 break;
1202 case 0x4b: /* LTHr */
1203 __asm__("evaluxn_4b_LTHr:");
1204 {
1205 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
1206 u->rst.dat[u->rst.ptr - 2] = b < a;
1207#ifndef NO_STACK_CHECKS
1208 if(__builtin_expect(u->rst.ptr < 2, 0)) {
1209 u->rst.error = 1;
1210 goto error;
1211 }
1212#endif
1213 u->rst.ptr -= 1;
1214 }
1215 break;
1216 case 0x4c: /* JMPr */
1217 __asm__("evaluxn_4c_JMPr:");
1218 {
1219 u8 a = u->rst.dat[u->rst.ptr - 1];
1220 u->ram.ptr += (s8)a;
1221#ifndef NO_STACK_CHECKS
1222 if(__builtin_expect(u->rst.ptr < 1, 0)) {
1223 u->rst.error = 1;
1224 goto error;
1225 }
1226#endif
1227 u->rst.ptr -= 1;
1228 }
1229 break;
1230 case 0x4d: /* JCNr */
1231 __asm__("evaluxn_4d_JCNr:");
1232 {
1233 u8 a = u->rst.dat[u->rst.ptr - 1];
1234 if(u->rst.dat[u->rst.ptr - 2]) u->ram.ptr += (s8)a;
1235#ifndef NO_STACK_CHECKS
1236 if(__builtin_expect(u->rst.ptr < 2, 0)) {
1237 u->rst.error = 1;
1238 goto error;
1239 }
1240#endif
1241 u->rst.ptr -= 2;
1242 }
1243 break;
1244 case 0x4e: /* JSRr */
1245 __asm__("evaluxn_4e_JSRr:");
1246 {
1247 u8 a = u->rst.dat[u->rst.ptr - 1];
1248 u->wst.dat[u->wst.ptr] = u->ram.ptr >> 8;
1249 u->wst.dat[u->wst.ptr + 1] = u->ram.ptr & 0xff;
1250 u->ram.ptr += (s8)a;
1251#ifndef NO_STACK_CHECKS
1252 if(__builtin_expect(u->rst.ptr < 1, 0)) {
1253 u->rst.error = 1;
1254 goto error;
1255 }
1256#endif
1257 u->rst.ptr -= 1;
1258#ifndef NO_STACK_CHECKS
1259 if(__builtin_expect(u->wst.ptr > 253, 0)) {
1260 u->wst.error = 2;
1261 goto error;
1262 }
1263#endif
1264 u->wst.ptr += 2;
1265 }
1266 break;
1267 case 0x4f: /* STHr */
1268 __asm__("evaluxn_4f_STHr:");
1269 {
1270 u8 a = u->rst.dat[u->rst.ptr - 1];
1271 u->wst.dat[u->wst.ptr] = a;
1272#ifndef NO_STACK_CHECKS
1273 if(__builtin_expect(u->rst.ptr < 1, 0)) {
1274 u->rst.error = 1;
1275 goto error;
1276 }
1277#endif
1278 u->rst.ptr -= 1;
1279#ifndef NO_STACK_CHECKS
1280 if(__builtin_expect(u->wst.ptr > 254, 0)) {
1281 u->wst.error = 2;
1282 goto error;
1283 }
1284#endif
1285 u->wst.ptr += 1;
1286 }
1287 break;
1288 case 0x50: /* LDZr */
1289 __asm__("evaluxn_50_LDZr:");
1290 {
1291 u8 a = u->rst.dat[u->rst.ptr - 1];
1292 u->rst.dat[u->rst.ptr - 1] = mempeek8(u->ram.dat, a);
1293#ifndef NO_STACK_CHECKS
1294 if(__builtin_expect(u->rst.ptr < 1, 0)) {
1295 u->rst.error = 1;
1296 goto error;
1297 }
1298#endif
1299 }
1300 break;
1301 case 0x51: /* STZr */
1302 __asm__("evaluxn_51_STZr:");
1303 {
1304 u8 a = u->rst.dat[u->rst.ptr - 1];
1305 u8 b = u->rst.dat[u->rst.ptr - 2];
1306 mempoke8(u->ram.dat, a, b);
1307#ifndef NO_STACK_CHECKS
1308 if(__builtin_expect(u->rst.ptr < 2, 0)) {
1309 u->rst.error = 1;
1310 goto error;
1311 }
1312#endif
1313 u->rst.ptr -= 2;
1314 }
1315 break;
1316 case 0x52: /* LDRr */
1317 __asm__("evaluxn_52_LDRr:");
1318 {
1319 u8 a = u->rst.dat[u->rst.ptr - 1];
1320 u->rst.dat[u->rst.ptr - 1] = mempeek8(u->ram.dat, u->ram.ptr + (s8)a);
1321#ifndef NO_STACK_CHECKS
1322 if(__builtin_expect(u->rst.ptr < 1, 0)) {
1323 u->rst.error = 1;
1324 goto error;
1325 }
1326#endif
1327 }
1328 break;
1329 case 0x53: /* STRr */
1330 __asm__("evaluxn_53_STRr:");
1331 {
1332 u8 a = u->rst.dat[u->rst.ptr - 1];
1333 u8 b = u->rst.dat[u->rst.ptr - 2];
1334 mempoke8(u->ram.dat, u->ram.ptr + (s8)a, b);
1335#ifndef NO_STACK_CHECKS
1336 if(__builtin_expect(u->rst.ptr < 2, 0)) {
1337 u->rst.error = 1;
1338 goto error;
1339 }
1340#endif
1341 u->rst.ptr -= 2;
1342 }
1343 break;
1344 case 0x54: /* LDAr */
1345 __asm__("evaluxn_54_LDAr:");
1346 {
1347 u16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8));
1348 u->rst.dat[u->rst.ptr - 2] = mempeek8(u->ram.dat, a);
1349#ifndef NO_STACK_CHECKS
1350 if(__builtin_expect(u->rst.ptr < 2, 0)) {
1351 u->rst.error = 1;
1352 goto error;
1353 }
1354#endif
1355 u->rst.ptr -= 1;
1356 }
1357 break;
1358 case 0x55: /* STAr */
1359 __asm__("evaluxn_55_STAr:");
1360 {
1361 u16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8));
1362 u8 b = u->rst.dat[u->rst.ptr - 3];
1363 mempoke8(u->ram.dat, a, b);
1364#ifndef NO_STACK_CHECKS
1365 if(__builtin_expect(u->rst.ptr < 3, 0)) {
1366 u->rst.error = 1;
1367 goto error;
1368 }
1369#endif
1370 u->rst.ptr -= 3;
1371 }
1372 break;
1373 case 0x56: /* DEIr */
1374 __asm__("evaluxn_56_DEIr:");
1375 {
1376 u8 a = u->rst.dat[u->rst.ptr - 1];
1377 u->rst.dat[u->rst.ptr - 1] = devpeek8(&u->dev[a >> 4], a);
1378#ifndef NO_STACK_CHECKS
1379 if(__builtin_expect(u->rst.ptr < 1, 0)) {
1380 u->rst.error = 1;
1381 goto error;
1382 }
1383#endif
1384 }
1385 break;
1386 case 0x57: /* DEOr */
1387 __asm__("evaluxn_57_DEOr:");
1388 {
1389 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
1390 devpoke8(&u->dev[a >> 4], a, b);
1391#ifndef NO_STACK_CHECKS
1392 if(__builtin_expect(u->rst.ptr < 2, 0)) {
1393 u->rst.error = 1;
1394 goto error;
1395 }
1396#endif
1397 u->rst.ptr -= 2;
1398 }
1399 break;
1400 case 0x58: /* ADDr */
1401 __asm__("evaluxn_58_ADDr:");
1402 {
1403 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
1404 u->rst.dat[u->rst.ptr - 2] = b + a;
1405#ifndef NO_STACK_CHECKS
1406 if(__builtin_expect(u->rst.ptr < 2, 0)) {
1407 u->rst.error = 1;
1408 goto error;
1409 }
1410#endif
1411 u->rst.ptr -= 1;
1412 }
1413 break;
1414 case 0x59: /* SUBr */
1415 __asm__("evaluxn_59_SUBr:");
1416 {
1417 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
1418 u->rst.dat[u->rst.ptr - 2] = b - a;
1419#ifndef NO_STACK_CHECKS
1420 if(__builtin_expect(u->rst.ptr < 2, 0)) {
1421 u->rst.error = 1;
1422 goto error;
1423 }
1424#endif
1425 u->rst.ptr -= 1;
1426 }
1427 break;
1428 case 0x5a: /* MULr */
1429 __asm__("evaluxn_5a_MULr:");
1430 {
1431 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
1432 u->rst.dat[u->rst.ptr - 2] = b * a;
1433#ifndef NO_STACK_CHECKS
1434 if(__builtin_expect(u->rst.ptr < 2, 0)) {
1435 u->rst.error = 1;
1436 goto error;
1437 }
1438#endif
1439 u->rst.ptr -= 1;
1440 }
1441 break;
1442 case 0x5b: /* DIVr */
1443 __asm__("evaluxn_5b_DIVr:");
1444 {
1445 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
1446 if(a == 0) {
1447 u->rst.error = 3;
1448#ifndef NO_STACK_CHECKS
1449 goto error;
1450#endif
1451 a = 1;
1452 }
1453 u->rst.dat[u->rst.ptr - 2] = b / a;
1454#ifndef NO_STACK_CHECKS
1455 if(__builtin_expect(u->rst.ptr < 2, 0)) {
1456 u->rst.error = 1;
1457 goto error;
1458 }
1459#endif
1460 u->rst.ptr -= 1;
1461 }
1462 break;
1463 case 0x5c: /* ANDr */
1464 __asm__("evaluxn_5c_ANDr:");
1465 {
1466 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
1467 u->rst.dat[u->rst.ptr - 2] = b & a;
1468#ifndef NO_STACK_CHECKS
1469 if(__builtin_expect(u->rst.ptr < 2, 0)) {
1470 u->rst.error = 1;
1471 goto error;
1472 }
1473#endif
1474 u->rst.ptr -= 1;
1475 }
1476 break;
1477 case 0x5d: /* ORAr */
1478 __asm__("evaluxn_5d_ORAr:");
1479 {
1480 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
1481 u->rst.dat[u->rst.ptr - 2] = b | a;
1482#ifndef NO_STACK_CHECKS
1483 if(__builtin_expect(u->rst.ptr < 2, 0)) {
1484 u->rst.error = 1;
1485 goto error;
1486 }
1487#endif
1488 u->rst.ptr -= 1;
1489 }
1490 break;
1491 case 0x5e: /* EORr */
1492 __asm__("evaluxn_5e_EORr:");
1493 {
1494 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
1495 u->rst.dat[u->rst.ptr - 2] = b ^ a;
1496#ifndef NO_STACK_CHECKS
1497 if(__builtin_expect(u->rst.ptr < 2, 0)) {
1498 u->rst.error = 1;
1499 goto error;
1500 }
1501#endif
1502 u->rst.ptr -= 1;
1503 }
1504 break;
1505 case 0x5f: /* SFTr */
1506 __asm__("evaluxn_5f_SFTr:");
1507 {
1508 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
1509 u->rst.dat[u->rst.ptr - 2] = b >> (a & 0x07) << ((a & 0x70) >> 4);
1510#ifndef NO_STACK_CHECKS
1511 if(__builtin_expect(u->rst.ptr < 2, 0)) {
1512 u->rst.error = 1;
1513 goto error;
1514 }
1515#endif
1516 u->rst.ptr -= 1;
1517 }
1518 break;
1519 case 0x60: /* LIT2r */
1520 case 0xe0: /* LIT2kr */
1521 __asm__("evaluxn_60_LIT2r:");
1522 {
1523 u->rst.dat[u->rst.ptr] = mempeek8(u->ram.dat, u->ram.ptr++);
1524 u->rst.dat[u->rst.ptr + 1] = mempeek8(u->ram.dat, u->ram.ptr++);
1525#ifndef NO_STACK_CHECKS
1526 if(__builtin_expect(u->rst.ptr > 253, 0)) {
1527 u->rst.error = 2;
1528 goto error;
1529 }
1530#endif
1531 u->rst.ptr += 2;
1532 }
1533 break;
1534 case 0x61: /* INC2r */
1535 __asm__("evaluxn_61_INC2r:");
1536 {
1537 u16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8));
1538 u->rst.dat[u->rst.ptr - 2] = (a + 1) >> 8;
1539 u->rst.dat[u->rst.ptr - 1] = (a + 1) & 0xff;
1540#ifndef NO_STACK_CHECKS
1541 if(__builtin_expect(u->rst.ptr < 2, 0)) {
1542 u->rst.error = 1;
1543 goto error;
1544 }
1545#endif
1546 }
1547 break;
1548 case 0x62: /* POP2r */
1549 __asm__("evaluxn_62_POP2r:");
1550 {
1551 (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8));
1552#ifndef NO_STACK_CHECKS
1553 if(__builtin_expect(u->rst.ptr < 2, 0)) {
1554 u->rst.error = 1;
1555 goto error;
1556 }
1557#endif
1558 u->rst.ptr -= 2;
1559 }
1560 break;
1561 case 0x66: /* DUP2r */
1562 __asm__("evaluxn_63_DUP2r:");
1563 {
1564 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
1565 u->rst.dat[u->rst.ptr] = b;
1566 u->rst.dat[u->rst.ptr + 1] = a;
1567#ifndef NO_STACK_CHECKS
1568 if(__builtin_expect(u->rst.ptr < 2, 0)) {
1569 u->rst.error = 1;
1570 goto error;
1571 }
1572 if(__builtin_expect(u->rst.ptr > 253, 0)) {
1573 u->rst.error = 2;
1574 goto error;
1575 }
1576#endif
1577 u->rst.ptr += 2;
1578 }
1579 break;
1580 case 0x63: /* NIP2r */
1581 __asm__("evaluxn_64_NIP2r:");
1582 {
1583 u16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8));
1584 (u->rst.dat[u->rst.ptr - 3] | (u->rst.dat[u->rst.ptr - 4] << 8));
1585 u->rst.dat[u->rst.ptr - 4] = a >> 8;
1586 u->rst.dat[u->rst.ptr - 3] = a & 0xff;
1587#ifndef NO_STACK_CHECKS
1588 if(__builtin_expect(u->rst.ptr < 4, 0)) {
1589 u->rst.error = 1;
1590 goto error;
1591 }
1592#endif
1593 u->rst.ptr -= 2;
1594 }
1595 break;
1596 case 0x64: /* SWP2r */
1597 __asm__("evaluxn_65_SWP2r:");
1598 {
1599 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2], c = u->rst.dat[u->rst.ptr - 3], d = u->rst.dat[u->rst.ptr - 4];
1600 u->rst.dat[u->rst.ptr - 4] = b;
1601 u->rst.dat[u->rst.ptr - 3] = a;
1602 u->rst.dat[u->rst.ptr - 2] = d;
1603 u->rst.dat[u->rst.ptr - 1] = c;
1604#ifndef NO_STACK_CHECKS
1605 if(__builtin_expect(u->rst.ptr < 4, 0)) {
1606 u->rst.error = 1;
1607 goto error;
1608 }
1609#endif
1610 }
1611 break;
1612 case 0x67: /* OVR2r */
1613 __asm__("evaluxn_66_OVR2r:");
1614 {
1615 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2], c = u->rst.dat[u->rst.ptr - 3], d = u->rst.dat[u->rst.ptr - 4];
1616 u->rst.dat[u->rst.ptr] = d;
1617 u->rst.dat[u->rst.ptr + 1] = c;
1618#ifndef NO_STACK_CHECKS
1619 if(__builtin_expect(u->rst.ptr < 4, 0)) {
1620 u->rst.error = 1;
1621 goto error;
1622 }
1623 if(__builtin_expect(u->rst.ptr > 253, 0)) {
1624 u->rst.error = 2;
1625 goto error;
1626 }
1627#endif
1628 u->rst.ptr += 2;
1629 }
1630 break;
1631 case 0x65: /* ROT2r */
1632 __asm__("evaluxn_67_ROT2r:");
1633 {
1634 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2], c = u->rst.dat[u->rst.ptr - 3], d = u->rst.dat[u->rst.ptr - 4], e = u->rst.dat[u->rst.ptr - 5], f = u->rst.dat[u->rst.ptr - 6];
1635 u->rst.dat[u->rst.ptr - 6] = d;
1636 u->rst.dat[u->rst.ptr - 5] = c;
1637 u->rst.dat[u->rst.ptr - 4] = b;
1638 u->rst.dat[u->rst.ptr - 3] = a;
1639 u->rst.dat[u->rst.ptr - 2] = f;
1640 u->rst.dat[u->rst.ptr - 1] = e;
1641#ifndef NO_STACK_CHECKS
1642 if(__builtin_expect(u->rst.ptr < 6, 0)) {
1643 u->rst.error = 1;
1644 goto error;
1645 }
1646#endif
1647 }
1648 break;
1649 case 0x68: /* EQU2r */
1650 __asm__("evaluxn_68_EQU2r:");
1651 {
1652 u16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)), b = (u->rst.dat[u->rst.ptr - 3] | (u->rst.dat[u->rst.ptr - 4] << 8));
1653 u->rst.dat[u->rst.ptr - 4] = b == a;
1654#ifndef NO_STACK_CHECKS
1655 if(__builtin_expect(u->rst.ptr < 4, 0)) {
1656 u->rst.error = 1;
1657 goto error;
1658 }
1659#endif
1660 u->rst.ptr -= 3;
1661 }
1662 break;
1663 case 0x69: /* NEQ2r */
1664 __asm__("evaluxn_69_NEQ2r:");
1665 {
1666 u16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)), b = (u->rst.dat[u->rst.ptr - 3] | (u->rst.dat[u->rst.ptr - 4] << 8));
1667 u->rst.dat[u->rst.ptr - 4] = b != a;
1668#ifndef NO_STACK_CHECKS
1669 if(__builtin_expect(u->rst.ptr < 4, 0)) {
1670 u->rst.error = 1;
1671 goto error;
1672 }
1673#endif
1674 u->rst.ptr -= 3;
1675 }
1676 break;
1677 case 0x6a: /* GTH2r */
1678 __asm__("evaluxn_6a_GTH2r:");
1679 {
1680 u16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)), b = (u->rst.dat[u->rst.ptr - 3] | (u->rst.dat[u->rst.ptr - 4] << 8));
1681 u->rst.dat[u->rst.ptr - 4] = b > a;
1682#ifndef NO_STACK_CHECKS
1683 if(__builtin_expect(u->rst.ptr < 4, 0)) {
1684 u->rst.error = 1;
1685 goto error;
1686 }
1687#endif
1688 u->rst.ptr -= 3;
1689 }
1690 break;
1691 case 0x6b: /* LTH2r */
1692 __asm__("evaluxn_6b_LTH2r:");
1693 {
1694 u16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)), b = (u->rst.dat[u->rst.ptr - 3] | (u->rst.dat[u->rst.ptr - 4] << 8));
1695 u->rst.dat[u->rst.ptr - 4] = b < a;
1696#ifndef NO_STACK_CHECKS
1697 if(__builtin_expect(u->rst.ptr < 4, 0)) {
1698 u->rst.error = 1;
1699 goto error;
1700 }
1701#endif
1702 u->rst.ptr -= 3;
1703 }
1704 break;
1705 case 0x6c: /* JMP2r */
1706 __asm__("evaluxn_6c_JMP2r:");
1707 {
1708 u->ram.ptr = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8));
1709#ifndef NO_STACK_CHECKS
1710 if(__builtin_expect(u->rst.ptr < 2, 0)) {
1711 u->rst.error = 1;
1712 goto error;
1713 }
1714#endif
1715 u->rst.ptr -= 2;
1716 }
1717 break;
1718 case 0x6d: /* JCN2r */
1719 __asm__("evaluxn_6d_JCN2r:");
1720 {
1721 u16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8));
1722 if(u->rst.dat[u->rst.ptr - 3]) u->ram.ptr = a;
1723#ifndef NO_STACK_CHECKS
1724 if(__builtin_expect(u->rst.ptr < 3, 0)) {
1725 u->rst.error = 1;
1726 goto error;
1727 }
1728#endif
1729 u->rst.ptr -= 3;
1730 }
1731 break;
1732 case 0x6e: /* JSR2r */
1733 __asm__("evaluxn_6e_JSR2r:");
1734 {
1735 u->wst.dat[u->wst.ptr] = u->ram.ptr >> 8;
1736 u->wst.dat[u->wst.ptr + 1] = u->ram.ptr & 0xff;
1737 u->ram.ptr = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8));
1738#ifndef NO_STACK_CHECKS
1739 if(__builtin_expect(u->rst.ptr < 2, 0)) {
1740 u->rst.error = 1;
1741 goto error;
1742 }
1743#endif
1744 u->rst.ptr -= 2;
1745#ifndef NO_STACK_CHECKS
1746 if(__builtin_expect(u->wst.ptr > 253, 0)) {
1747 u->wst.error = 2;
1748 goto error;
1749 }
1750#endif
1751 u->wst.ptr += 2;
1752 }
1753 break;
1754 case 0x6f: /* STH2r */
1755 __asm__("evaluxn_6f_STH2r:");
1756 {
1757 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
1758 u->wst.dat[u->wst.ptr] = b;
1759 u->wst.dat[u->wst.ptr + 1] = a;
1760#ifndef NO_STACK_CHECKS
1761 if(__builtin_expect(u->rst.ptr < 2, 0)) {
1762 u->rst.error = 1;
1763 goto error;
1764 }
1765#endif
1766 u->rst.ptr -= 2;
1767#ifndef NO_STACK_CHECKS
1768 if(__builtin_expect(u->wst.ptr > 253, 0)) {
1769 u->wst.error = 2;
1770 goto error;
1771 }
1772#endif
1773 u->wst.ptr += 2;
1774 }
1775 break;
1776 case 0x70: /* LDZ2r */
1777 __asm__("evaluxn_70_LDZ2r:");
1778 {
1779 u8 a = u->rst.dat[u->rst.ptr - 1];
1780 u->rst.dat[u->rst.ptr - 1] = mempeek8(u->ram.dat, a);
1781 u->rst.dat[u->rst.ptr] = mempeek8(u->ram.dat, a + 1);
1782#ifndef NO_STACK_CHECKS
1783 if(__builtin_expect(u->rst.ptr < 1, 0)) {
1784 u->rst.error = 1;
1785 goto error;
1786 }
1787 if(__builtin_expect(u->rst.ptr > 254, 0)) {
1788 u->rst.error = 2;
1789 goto error;
1790 }
1791#endif
1792 u->rst.ptr += 1;
1793 }
1794 break;
1795 case 0x71: /* STZ2r */
1796 __asm__("evaluxn_71_STZ2r:");
1797 {
1798 u8 a = u->rst.dat[u->rst.ptr - 1];
1799 u16 b = (u->rst.dat[u->rst.ptr - 2] | (u->rst.dat[u->rst.ptr - 3] << 8));
1800 mempoke16(u->ram.dat, a, b);
1801#ifndef NO_STACK_CHECKS
1802 if(__builtin_expect(u->rst.ptr < 3, 0)) {
1803 u->rst.error = 1;
1804 goto error;
1805 }
1806#endif
1807 u->rst.ptr -= 3;
1808 }
1809 break;
1810 case 0x72: /* LDR2r */
1811 __asm__("evaluxn_72_LDR2r:");
1812 {
1813 u8 a = u->rst.dat[u->rst.ptr - 1];
1814 u->rst.dat[u->rst.ptr - 1] = mempeek8(u->ram.dat, u->ram.ptr + (s8)a);
1815 u->rst.dat[u->rst.ptr] = mempeek8(u->ram.dat, u->ram.ptr + (s8)a + 1);
1816#ifndef NO_STACK_CHECKS
1817 if(__builtin_expect(u->rst.ptr < 1, 0)) {
1818 u->rst.error = 1;
1819 goto error;
1820 }
1821 if(__builtin_expect(u->rst.ptr > 254, 0)) {
1822 u->rst.error = 2;
1823 goto error;
1824 }
1825#endif
1826 u->rst.ptr += 1;
1827 }
1828 break;
1829 case 0x73: /* STR2r */
1830 __asm__("evaluxn_73_STR2r:");
1831 {
1832 u8 a = u->rst.dat[u->rst.ptr - 1];
1833 u16 b = (u->rst.dat[u->rst.ptr - 2] | (u->rst.dat[u->rst.ptr - 3] << 8));
1834 mempoke16(u->ram.dat, u->ram.ptr + (s8)a, b);
1835#ifndef NO_STACK_CHECKS
1836 if(__builtin_expect(u->rst.ptr < 3, 0)) {
1837 u->rst.error = 1;
1838 goto error;
1839 }
1840#endif
1841 u->rst.ptr -= 3;
1842 }
1843 break;
1844 case 0x74: /* LDA2r */
1845 __asm__("evaluxn_74_LDA2r:");
1846 {
1847 u16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8));
1848 u->rst.dat[u->rst.ptr - 2] = mempeek8(u->ram.dat, a);
1849 u->rst.dat[u->rst.ptr - 1] = mempeek8(u->ram.dat, a + 1);
1850#ifndef NO_STACK_CHECKS
1851 if(__builtin_expect(u->rst.ptr < 2, 0)) {
1852 u->rst.error = 1;
1853 goto error;
1854 }
1855#endif
1856 }
1857 break;
1858 case 0x75: /* STA2r */
1859 __asm__("evaluxn_75_STA2r:");
1860 {
1861 u16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8));
1862 u16 b = (u->rst.dat[u->rst.ptr - 3] | (u->rst.dat[u->rst.ptr - 4] << 8));
1863 mempoke16(u->ram.dat, a, b);
1864#ifndef NO_STACK_CHECKS
1865 if(__builtin_expect(u->rst.ptr < 4, 0)) {
1866 u->rst.error = 1;
1867 goto error;
1868 }
1869#endif
1870 u->rst.ptr -= 4;
1871 }
1872 break;
1873 case 0x76: /* DEI2r */
1874 __asm__("evaluxn_76_DEI2r:");
1875 {
1876 u8 a = u->rst.dat[u->rst.ptr - 1];
1877 u->rst.dat[u->rst.ptr - 1] = devpeek8(&u->dev[a >> 4], a);
1878 u->rst.dat[u->rst.ptr] = devpeek8(&u->dev[a >> 4], a + 1);
1879#ifndef NO_STACK_CHECKS
1880 if(__builtin_expect(u->rst.ptr < 1, 0)) {
1881 u->rst.error = 1;
1882 goto error;
1883 }
1884 if(__builtin_expect(u->rst.ptr > 254, 0)) {
1885 u->rst.error = 2;
1886 goto error;
1887 }
1888#endif
1889 u->rst.ptr += 1;
1890 }
1891 break;
1892 case 0x77: /* DEO2r */
1893 __asm__("evaluxn_77_DEO2r:");
1894 {
1895 u8 a = u->rst.dat[u->rst.ptr - 1];
1896 u16 b = (u->rst.dat[u->rst.ptr - 2] | (u->rst.dat[u->rst.ptr - 3] << 8));
1897 devpoke16(&u->dev[a >> 4], a, b);
1898#ifndef NO_STACK_CHECKS
1899 if(__builtin_expect(u->rst.ptr < 3, 0)) {
1900 u->rst.error = 1;
1901 goto error;
1902 }
1903#endif
1904 u->rst.ptr -= 3;
1905 }
1906 break;
1907 case 0x78: /* ADD2r */
1908 __asm__("evaluxn_78_ADD2r:");
1909 {
1910 u16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)), b = (u->rst.dat[u->rst.ptr - 3] | (u->rst.dat[u->rst.ptr - 4] << 8));
1911 u->rst.dat[u->rst.ptr - 4] = (b + a) >> 8;
1912 u->rst.dat[u->rst.ptr - 3] = (b + a) & 0xff;
1913#ifndef NO_STACK_CHECKS
1914 if(__builtin_expect(u->rst.ptr < 4, 0)) {
1915 u->rst.error = 1;
1916 goto error;
1917 }
1918#endif
1919 u->rst.ptr -= 2;
1920 }
1921 break;
1922 case 0x79: /* SUB2r */
1923 __asm__("evaluxn_79_SUB2r:");
1924 {
1925 u16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)), b = (u->rst.dat[u->rst.ptr - 3] | (u->rst.dat[u->rst.ptr - 4] << 8));
1926 u->rst.dat[u->rst.ptr - 4] = (b - a) >> 8;
1927 u->rst.dat[u->rst.ptr - 3] = (b - a) & 0xff;
1928#ifndef NO_STACK_CHECKS
1929 if(__builtin_expect(u->rst.ptr < 4, 0)) {
1930 u->rst.error = 1;
1931 goto error;
1932 }
1933#endif
1934 u->rst.ptr -= 2;
1935 }
1936 break;
1937 case 0x7a: /* MUL2r */
1938 __asm__("evaluxn_7a_MUL2r:");
1939 {
1940 u16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)), b = (u->rst.dat[u->rst.ptr - 3] | (u->rst.dat[u->rst.ptr - 4] << 8));
1941 u->rst.dat[u->rst.ptr - 4] = (b * a) >> 8;
1942 u->rst.dat[u->rst.ptr - 3] = (b * a) & 0xff;
1943#ifndef NO_STACK_CHECKS
1944 if(__builtin_expect(u->rst.ptr < 4, 0)) {
1945 u->rst.error = 1;
1946 goto error;
1947 }
1948#endif
1949 u->rst.ptr -= 2;
1950 }
1951 break;
1952 case 0x7b: /* DIV2r */
1953 __asm__("evaluxn_7b_DIV2r:");
1954 {
1955 u16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)), b = (u->rst.dat[u->rst.ptr - 3] | (u->rst.dat[u->rst.ptr - 4] << 8));
1956 if(a == 0) {
1957 u->rst.error = 3;
1958#ifndef NO_STACK_CHECKS
1959 goto error;
1960#endif
1961 a = 1;
1962 }
1963 u->rst.dat[u->rst.ptr - 4] = (b / a) >> 8;
1964 u->rst.dat[u->rst.ptr - 3] = (b / a) & 0xff;
1965#ifndef NO_STACK_CHECKS
1966 if(__builtin_expect(u->rst.ptr < 4, 0)) {
1967 u->rst.error = 1;
1968 goto error;
1969 }
1970#endif
1971 u->rst.ptr -= 2;
1972 }
1973 break;
1974 case 0x7c: /* AND2r */
1975 __asm__("evaluxn_7c_AND2r:");
1976 {
1977 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2], c = u->rst.dat[u->rst.ptr - 3], d = u->rst.dat[u->rst.ptr - 4];
1978 u->rst.dat[u->rst.ptr - 4] = d & b;
1979 u->rst.dat[u->rst.ptr - 3] = c & a;
1980#ifndef NO_STACK_CHECKS
1981 if(__builtin_expect(u->rst.ptr < 4, 0)) {
1982 u->rst.error = 1;
1983 goto error;
1984 }
1985#endif
1986 u->rst.ptr -= 2;
1987 }
1988 break;
1989 case 0x7d: /* ORA2r */
1990 __asm__("evaluxn_7d_ORA2r:");
1991 {
1992 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2], c = u->rst.dat[u->rst.ptr - 3], d = u->rst.dat[u->rst.ptr - 4];
1993 u->rst.dat[u->rst.ptr - 4] = d | b;
1994 u->rst.dat[u->rst.ptr - 3] = c | a;
1995#ifndef NO_STACK_CHECKS
1996 if(__builtin_expect(u->rst.ptr < 4, 0)) {
1997 u->rst.error = 1;
1998 goto error;
1999 }
2000#endif
2001 u->rst.ptr -= 2;
2002 }
2003 break;
2004 case 0x7e: /* EOR2r */
2005 __asm__("evaluxn_7e_EOR2r:");
2006 {
2007 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2], c = u->rst.dat[u->rst.ptr - 3], d = u->rst.dat[u->rst.ptr - 4];
2008 u->rst.dat[u->rst.ptr - 4] = d ^ b;
2009 u->rst.dat[u->rst.ptr - 3] = c ^ a;
2010#ifndef NO_STACK_CHECKS
2011 if(__builtin_expect(u->rst.ptr < 4, 0)) {
2012 u->rst.error = 1;
2013 goto error;
2014 }
2015#endif
2016 u->rst.ptr -= 2;
2017 }
2018 break;
2019 case 0x7f: /* SFT2r */
2020 __asm__("evaluxn_7f_SFT2r:");
2021 {
2022 u8 a = u->rst.dat[u->rst.ptr - 1];
2023 u16 b = (u->rst.dat[u->rst.ptr - 2] | (u->rst.dat[u->rst.ptr - 3] << 8));
2024 u->rst.dat[u->rst.ptr - 3] = (b >> (a & 0x0f) << ((a & 0xf0) >> 4)) >> 8;
2025 u->rst.dat[u->rst.ptr - 2] = (b >> (a & 0x0f) << ((a & 0xf0) >> 4)) & 0xff;
2026#ifndef NO_STACK_CHECKS
2027 if(__builtin_expect(u->rst.ptr < 3, 0)) {
2028 u->rst.error = 1;
2029 goto error;
2030 }
2031#endif
2032 u->rst.ptr -= 1;
2033 }
2034 break;
2035 case 0x81: /* INCk */
2036 __asm__("evaluxn_81_INCk:");
2037 {
2038 u8 a = u->wst.dat[u->wst.ptr - 1];
2039 u->wst.dat[u->wst.ptr] = a + 1;
2040#ifndef NO_STACK_CHECKS
2041 if(__builtin_expect(u->wst.ptr < 1, 0)) {
2042 u->wst.error = 1;
2043 goto error;
2044 }
2045 if(__builtin_expect(u->wst.ptr > 254, 0)) {
2046 u->wst.error = 2;
2047 goto error;
2048 }
2049#endif
2050 u->wst.ptr += 1;
2051 }
2052 break;
2053 case 0x82: /* POPk */
2054 __asm__("evaluxn_82_POPk:");
2055 {
2056 u->wst.dat[u->wst.ptr - 1];
2057#ifndef NO_STACK_CHECKS
2058 if(__builtin_expect(u->wst.ptr < 1, 0)) {
2059 u->wst.error = 1;
2060 goto error;
2061 }
2062#endif
2063 }
2064 break;
2065 case 0x86: /* DUPk */
2066 __asm__("evaluxn_83_DUPk:");
2067 {
2068 u8 a = u->wst.dat[u->wst.ptr - 1];
2069 u->wst.dat[u->wst.ptr] = a;
2070 u->wst.dat[u->wst.ptr + 1] = a;
2071#ifndef NO_STACK_CHECKS
2072 if(__builtin_expect(u->wst.ptr < 1, 0)) {
2073 u->wst.error = 1;
2074 goto error;
2075 }
2076 if(__builtin_expect(u->wst.ptr > 253, 0)) {
2077 u->wst.error = 2;
2078 goto error;
2079 }
2080#endif
2081 u->wst.ptr += 2;
2082 }
2083 break;
2084 case 0x83: /* NIPk */
2085 __asm__("evaluxn_84_NIPk:");
2086 {
2087 u8 a = u->wst.dat[u->wst.ptr - 1];
2088 u->wst.dat[u->wst.ptr - 2];
2089 u->wst.dat[u->wst.ptr] = a;
2090#ifndef NO_STACK_CHECKS
2091 if(__builtin_expect(u->wst.ptr < 2, 0)) {
2092 u->wst.error = 1;
2093 goto error;
2094 }
2095 if(__builtin_expect(u->wst.ptr > 254, 0)) {
2096 u->wst.error = 2;
2097 goto error;
2098 }
2099#endif
2100 u->wst.ptr += 1;
2101 }
2102 break;
2103 case 0x84: /* SWPk */
2104 __asm__("evaluxn_85_SWPk:");
2105 {
2106 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
2107 u->wst.dat[u->wst.ptr] = a;
2108 u->wst.dat[u->wst.ptr + 1] = b;
2109#ifndef NO_STACK_CHECKS
2110 if(__builtin_expect(u->wst.ptr < 2, 0)) {
2111 u->wst.error = 1;
2112 goto error;
2113 }
2114 if(__builtin_expect(u->wst.ptr > 253, 0)) {
2115 u->wst.error = 2;
2116 goto error;
2117 }
2118#endif
2119 u->wst.ptr += 2;
2120 }
2121 break;
2122 case 0x87: /* OVRk */
2123 __asm__("evaluxn_86_OVRk:");
2124 {
2125 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
2126 u->wst.dat[u->wst.ptr] = b;
2127 u->wst.dat[u->wst.ptr + 1] = a;
2128 u->wst.dat[u->wst.ptr + 2] = b;
2129#ifndef NO_STACK_CHECKS
2130 if(__builtin_expect(u->wst.ptr < 2, 0)) {
2131 u->wst.error = 1;
2132 goto error;
2133 }
2134 if(__builtin_expect(u->wst.ptr > 252, 0)) {
2135 u->wst.error = 2;
2136 goto error;
2137 }
2138#endif
2139 u->wst.ptr += 3;
2140 }
2141 break;
2142 case 0x85: /* ROTk */
2143 __asm__("evaluxn_87_ROTk:");
2144 {
2145 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2], c = u->wst.dat[u->wst.ptr - 3];
2146 u->wst.dat[u->wst.ptr] = b;
2147 u->wst.dat[u->wst.ptr + 1] = a;
2148 u->wst.dat[u->wst.ptr + 2] = c;
2149#ifndef NO_STACK_CHECKS
2150 if(__builtin_expect(u->wst.ptr < 3, 0)) {
2151 u->wst.error = 1;
2152 goto error;
2153 }
2154 if(__builtin_expect(u->wst.ptr > 252, 0)) {
2155 u->wst.error = 2;
2156 goto error;
2157 }
2158#endif
2159 u->wst.ptr += 3;
2160 }
2161 break;
2162 case 0x88: /* EQUk */
2163 __asm__("evaluxn_88_EQUk:");
2164 {
2165 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
2166 u->wst.dat[u->wst.ptr] = b == a;
2167#ifndef NO_STACK_CHECKS
2168 if(__builtin_expect(u->wst.ptr < 2, 0)) {
2169 u->wst.error = 1;
2170 goto error;
2171 }
2172 if(__builtin_expect(u->wst.ptr > 254, 0)) {
2173 u->wst.error = 2;
2174 goto error;
2175 }
2176#endif
2177 u->wst.ptr += 1;
2178 }
2179 break;
2180 case 0x89: /* NEQk */
2181 __asm__("evaluxn_89_NEQk:");
2182 {
2183 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
2184 u->wst.dat[u->wst.ptr] = b != a;
2185#ifndef NO_STACK_CHECKS
2186 if(__builtin_expect(u->wst.ptr < 2, 0)) {
2187 u->wst.error = 1;
2188 goto error;
2189 }
2190 if(__builtin_expect(u->wst.ptr > 254, 0)) {
2191 u->wst.error = 2;
2192 goto error;
2193 }
2194#endif
2195 u->wst.ptr += 1;
2196 }
2197 break;
2198 case 0x8a: /* GTHk */
2199 __asm__("evaluxn_8a_GTHk:");
2200 {
2201 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
2202 u->wst.dat[u->wst.ptr] = b > a;
2203#ifndef NO_STACK_CHECKS
2204 if(__builtin_expect(u->wst.ptr < 2, 0)) {
2205 u->wst.error = 1;
2206 goto error;
2207 }
2208 if(__builtin_expect(u->wst.ptr > 254, 0)) {
2209 u->wst.error = 2;
2210 goto error;
2211 }
2212#endif
2213 u->wst.ptr += 1;
2214 }
2215 break;
2216 case 0x8b: /* LTHk */
2217 __asm__("evaluxn_8b_LTHk:");
2218 {
2219 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
2220 u->wst.dat[u->wst.ptr] = b < a;
2221#ifndef NO_STACK_CHECKS
2222 if(__builtin_expect(u->wst.ptr < 2, 0)) {
2223 u->wst.error = 1;
2224 goto error;
2225 }
2226 if(__builtin_expect(u->wst.ptr > 254, 0)) {
2227 u->wst.error = 2;
2228 goto error;
2229 }
2230#endif
2231 u->wst.ptr += 1;
2232 }
2233 break;
2234 case 0x8c: /* JMPk */
2235 __asm__("evaluxn_8c_JMPk:");
2236 {
2237 u8 a = u->wst.dat[u->wst.ptr - 1];
2238 u->ram.ptr += (s8)a;
2239#ifndef NO_STACK_CHECKS
2240 if(__builtin_expect(u->wst.ptr < 1, 0)) {
2241 u->wst.error = 1;
2242 goto error;
2243 }
2244#endif
2245 }
2246 break;
2247 case 0x8d: /* JCNk */
2248 __asm__("evaluxn_8d_JCNk:");
2249 {
2250 u8 a = u->wst.dat[u->wst.ptr - 1];
2251 if(u->wst.dat[u->wst.ptr - 2]) u->ram.ptr += (s8)a;
2252#ifndef NO_STACK_CHECKS
2253 if(__builtin_expect(u->wst.ptr < 2, 0)) {
2254 u->wst.error = 1;
2255 goto error;
2256 }
2257#endif
2258 }
2259 break;
2260 case 0x8e: /* JSRk */
2261 __asm__("evaluxn_8e_JSRk:");
2262 {
2263 u8 a = u->wst.dat[u->wst.ptr - 1];
2264 u->rst.dat[u->rst.ptr] = u->ram.ptr >> 8;
2265 u->rst.dat[u->rst.ptr + 1] = u->ram.ptr & 0xff;
2266 u->ram.ptr += (s8)a;
2267#ifndef NO_STACK_CHECKS
2268 if(__builtin_expect(u->wst.ptr < 1, 0)) {
2269 u->wst.error = 1;
2270 goto error;
2271 }
2272 if(__builtin_expect(u->rst.ptr > 253, 0)) {
2273 u->rst.error = 2;
2274 goto error;
2275 }
2276#endif
2277 u->rst.ptr += 2;
2278 }
2279 break;
2280 case 0x8f: /* STHk */
2281 __asm__("evaluxn_8f_STHk:");
2282 {
2283 u8 a = u->wst.dat[u->wst.ptr - 1];
2284 u->rst.dat[u->rst.ptr] = a;
2285#ifndef NO_STACK_CHECKS
2286 if(__builtin_expect(u->wst.ptr < 1, 0)) {
2287 u->wst.error = 1;
2288 goto error;
2289 }
2290 if(__builtin_expect(u->rst.ptr > 254, 0)) {
2291 u->rst.error = 2;
2292 goto error;
2293 }
2294#endif
2295 u->rst.ptr += 1;
2296 }
2297 break;
2298 case 0x90: /* LDZk */
2299 __asm__("evaluxn_90_LDZk:");
2300 {
2301 u8 a = u->wst.dat[u->wst.ptr - 1];
2302 u->wst.dat[u->wst.ptr] = mempeek8(u->ram.dat, a);
2303#ifndef NO_STACK_CHECKS
2304 if(__builtin_expect(u->wst.ptr < 1, 0)) {
2305 u->wst.error = 1;
2306 goto error;
2307 }
2308 if(__builtin_expect(u->wst.ptr > 254, 0)) {
2309 u->wst.error = 2;
2310 goto error;
2311 }
2312#endif
2313 u->wst.ptr += 1;
2314 }
2315 break;
2316 case 0x91: /* STZk */
2317 __asm__("evaluxn_91_STZk:");
2318 {
2319 u8 a = u->wst.dat[u->wst.ptr - 1];
2320 u8 b = u->wst.dat[u->wst.ptr - 2];
2321 mempoke8(u->ram.dat, a, b);
2322#ifndef NO_STACK_CHECKS
2323 if(__builtin_expect(u->wst.ptr < 2, 0)) {
2324 u->wst.error = 1;
2325 goto error;
2326 }
2327#endif
2328 }
2329 break;
2330 case 0x92: /* LDRk */
2331 __asm__("evaluxn_92_LDRk:");
2332 {
2333 u8 a = u->wst.dat[u->wst.ptr - 1];
2334 u->wst.dat[u->wst.ptr] = mempeek8(u->ram.dat, u->ram.ptr + (s8)a);
2335#ifndef NO_STACK_CHECKS
2336 if(__builtin_expect(u->wst.ptr < 1, 0)) {
2337 u->wst.error = 1;
2338 goto error;
2339 }
2340 if(__builtin_expect(u->wst.ptr > 254, 0)) {
2341 u->wst.error = 2;
2342 goto error;
2343 }
2344#endif
2345 u->wst.ptr += 1;
2346 }
2347 break;
2348 case 0x93: /* STRk */
2349 __asm__("evaluxn_93_STRk:");
2350 {
2351 u8 a = u->wst.dat[u->wst.ptr - 1];
2352 u8 b = u->wst.dat[u->wst.ptr - 2];
2353 mempoke8(u->ram.dat, u->ram.ptr + (s8)a, b);
2354#ifndef NO_STACK_CHECKS
2355 if(__builtin_expect(u->wst.ptr < 2, 0)) {
2356 u->wst.error = 1;
2357 goto error;
2358 }
2359#endif
2360 }
2361 break;
2362 case 0x94: /* LDAk */
2363 __asm__("evaluxn_94_LDAk:");
2364 {
2365 u16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8));
2366 u->wst.dat[u->wst.ptr] = mempeek8(u->ram.dat, a);
2367#ifndef NO_STACK_CHECKS
2368 if(__builtin_expect(u->wst.ptr < 2, 0)) {
2369 u->wst.error = 1;
2370 goto error;
2371 }
2372 if(__builtin_expect(u->wst.ptr > 254, 0)) {
2373 u->wst.error = 2;
2374 goto error;
2375 }
2376#endif
2377 u->wst.ptr += 1;
2378 }
2379 break;
2380 case 0x95: /* STAk */
2381 __asm__("evaluxn_95_STAk:");
2382 {
2383 u16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8));
2384 u8 b = u->wst.dat[u->wst.ptr - 3];
2385 mempoke8(u->ram.dat, a, b);
2386#ifndef NO_STACK_CHECKS
2387 if(__builtin_expect(u->wst.ptr < 3, 0)) {
2388 u->wst.error = 1;
2389 goto error;
2390 }
2391#endif
2392 }
2393 break;
2394 case 0x96: /* DEIk */
2395 __asm__("evaluxn_96_DEIk:");
2396 {
2397 u8 a = u->wst.dat[u->wst.ptr - 1];
2398 u->wst.dat[u->wst.ptr] = devpeek8(&u->dev[a >> 4], a);
2399#ifndef NO_STACK_CHECKS
2400 if(__builtin_expect(u->wst.ptr < 1, 0)) {
2401 u->wst.error = 1;
2402 goto error;
2403 }
2404 if(__builtin_expect(u->wst.ptr > 254, 0)) {
2405 u->wst.error = 2;
2406 goto error;
2407 }
2408#endif
2409 u->wst.ptr += 1;
2410 }
2411 break;
2412 case 0x97: /* DEOk */
2413 __asm__("evaluxn_97_DEOk:");
2414 {
2415 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
2416 devpoke8(&u->dev[a >> 4], a, b);
2417#ifndef NO_STACK_CHECKS
2418 if(__builtin_expect(u->wst.ptr < 2, 0)) {
2419 u->wst.error = 1;
2420 goto error;
2421 }
2422#endif
2423 }
2424 break;
2425 case 0x98: /* ADDk */
2426 __asm__("evaluxn_98_ADDk:");
2427 {
2428 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
2429 u->wst.dat[u->wst.ptr] = b + a;
2430#ifndef NO_STACK_CHECKS
2431 if(__builtin_expect(u->wst.ptr < 2, 0)) {
2432 u->wst.error = 1;
2433 goto error;
2434 }
2435 if(__builtin_expect(u->wst.ptr > 254, 0)) {
2436 u->wst.error = 2;
2437 goto error;
2438 }
2439#endif
2440 u->wst.ptr += 1;
2441 }
2442 break;
2443 case 0x99: /* SUBk */
2444 __asm__("evaluxn_99_SUBk:");
2445 {
2446 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
2447 u->wst.dat[u->wst.ptr] = b - a;
2448#ifndef NO_STACK_CHECKS
2449 if(__builtin_expect(u->wst.ptr < 2, 0)) {
2450 u->wst.error = 1;
2451 goto error;
2452 }
2453 if(__builtin_expect(u->wst.ptr > 254, 0)) {
2454 u->wst.error = 2;
2455 goto error;
2456 }
2457#endif
2458 u->wst.ptr += 1;
2459 }
2460 break;
2461 case 0x9a: /* MULk */
2462 __asm__("evaluxn_9a_MULk:");
2463 {
2464 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
2465 u->wst.dat[u->wst.ptr] = b * a;
2466#ifndef NO_STACK_CHECKS
2467 if(__builtin_expect(u->wst.ptr < 2, 0)) {
2468 u->wst.error = 1;
2469 goto error;
2470 }
2471 if(__builtin_expect(u->wst.ptr > 254, 0)) {
2472 u->wst.error = 2;
2473 goto error;
2474 }
2475#endif
2476 u->wst.ptr += 1;
2477 }
2478 break;
2479 case 0x9b: /* DIVk */
2480 __asm__("evaluxn_9b_DIVk:");
2481 {
2482 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
2483 if(a == 0) {
2484 u->wst.error = 3;
2485#ifndef NO_STACK_CHECKS
2486 goto error;
2487#endif
2488 a = 1;
2489 }
2490 u->wst.dat[u->wst.ptr] = b / a;
2491#ifndef NO_STACK_CHECKS
2492 if(__builtin_expect(u->wst.ptr < 2, 0)) {
2493 u->wst.error = 1;
2494 goto error;
2495 }
2496 if(__builtin_expect(u->wst.ptr > 254, 0)) {
2497 u->wst.error = 2;
2498 goto error;
2499 }
2500#endif
2501 u->wst.ptr += 1;
2502 }
2503 break;
2504 case 0x9c: /* ANDk */
2505 __asm__("evaluxn_9c_ANDk:");
2506 {
2507 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
2508 u->wst.dat[u->wst.ptr] = b & a;
2509#ifndef NO_STACK_CHECKS
2510 if(__builtin_expect(u->wst.ptr < 2, 0)) {
2511 u->wst.error = 1;
2512 goto error;
2513 }
2514 if(__builtin_expect(u->wst.ptr > 254, 0)) {
2515 u->wst.error = 2;
2516 goto error;
2517 }
2518#endif
2519 u->wst.ptr += 1;
2520 }
2521 break;
2522 case 0x9d: /* ORAk */
2523 __asm__("evaluxn_9d_ORAk:");
2524 {
2525 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
2526 u->wst.dat[u->wst.ptr] = b | a;
2527#ifndef NO_STACK_CHECKS
2528 if(__builtin_expect(u->wst.ptr < 2, 0)) {
2529 u->wst.error = 1;
2530 goto error;
2531 }
2532 if(__builtin_expect(u->wst.ptr > 254, 0)) {
2533 u->wst.error = 2;
2534 goto error;
2535 }
2536#endif
2537 u->wst.ptr += 1;
2538 }
2539 break;
2540 case 0x9e: /* EORk */
2541 __asm__("evaluxn_9e_EORk:");
2542 {
2543 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
2544 u->wst.dat[u->wst.ptr] = b ^ a;
2545#ifndef NO_STACK_CHECKS
2546 if(__builtin_expect(u->wst.ptr < 2, 0)) {
2547 u->wst.error = 1;
2548 goto error;
2549 }
2550 if(__builtin_expect(u->wst.ptr > 254, 0)) {
2551 u->wst.error = 2;
2552 goto error;
2553 }
2554#endif
2555 u->wst.ptr += 1;
2556 }
2557 break;
2558 case 0x9f: /* SFTk */
2559 __asm__("evaluxn_9f_SFTk:");
2560 {
2561 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
2562 u->wst.dat[u->wst.ptr] = b >> (a & 0x07) << ((a & 0x70) >> 4);
2563#ifndef NO_STACK_CHECKS
2564 if(__builtin_expect(u->wst.ptr < 2, 0)) {
2565 u->wst.error = 1;
2566 goto error;
2567 }
2568 if(__builtin_expect(u->wst.ptr > 254, 0)) {
2569 u->wst.error = 2;
2570 goto error;
2571 }
2572#endif
2573 u->wst.ptr += 1;
2574 }
2575 break;
2576 case 0xa1: /* INC2k */
2577 __asm__("evaluxn_a1_INC2k:");
2578 {
2579 u16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8));
2580 u->wst.dat[u->wst.ptr] = (a + 1) >> 8;
2581 u->wst.dat[u->wst.ptr + 1] = (a + 1) & 0xff;
2582#ifndef NO_STACK_CHECKS
2583 if(__builtin_expect(u->wst.ptr < 2, 0)) {
2584 u->wst.error = 1;
2585 goto error;
2586 }
2587 if(__builtin_expect(u->wst.ptr > 253, 0)) {
2588 u->wst.error = 2;
2589 goto error;
2590 }
2591#endif
2592 u->wst.ptr += 2;
2593 }
2594 break;
2595 case 0xa2: /* POP2k */
2596 __asm__("evaluxn_a2_POP2k:");
2597 {
2598 (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8));
2599#ifndef NO_STACK_CHECKS
2600 if(__builtin_expect(u->wst.ptr < 2, 0)) {
2601 u->wst.error = 1;
2602 goto error;
2603 }
2604#endif
2605 }
2606 break;
2607 case 0xa6: /* DUP2k */
2608 __asm__("evaluxn_a3_DUP2k:");
2609 {
2610 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
2611 u->wst.dat[u->wst.ptr] = b;
2612 u->wst.dat[u->wst.ptr + 1] = a;
2613 u->wst.dat[u->wst.ptr + 2] = b;
2614 u->wst.dat[u->wst.ptr + 3] = a;
2615#ifndef NO_STACK_CHECKS
2616 if(__builtin_expect(u->wst.ptr < 2, 0)) {
2617 u->wst.error = 1;
2618 goto error;
2619 }
2620 if(__builtin_expect(u->wst.ptr > 251, 0)) {
2621 u->wst.error = 2;
2622 goto error;
2623 }
2624#endif
2625 u->wst.ptr += 4;
2626 }
2627 break;
2628 case 0xa3: /* NIP2k */
2629 __asm__("evaluxn_a4_NIP2k:");
2630 {
2631 u16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8));
2632 (u->wst.dat[u->wst.ptr - 3] | (u->wst.dat[u->wst.ptr - 4] << 8));
2633 u->wst.dat[u->wst.ptr] = a >> 8;
2634 u->wst.dat[u->wst.ptr + 1] = a & 0xff;
2635#ifndef NO_STACK_CHECKS
2636 if(__builtin_expect(u->wst.ptr < 4, 0)) {
2637 u->wst.error = 1;
2638 goto error;
2639 }
2640 if(__builtin_expect(u->wst.ptr > 253, 0)) {
2641 u->wst.error = 2;
2642 goto error;
2643 }
2644#endif
2645 u->wst.ptr += 2;
2646 }
2647 break;
2648 case 0xa4: /* SWP2k */
2649 __asm__("evaluxn_a5_SWP2k:");
2650 {
2651 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2], c = u->wst.dat[u->wst.ptr - 3], d = u->wst.dat[u->wst.ptr - 4];
2652 u->wst.dat[u->wst.ptr] = b;
2653 u->wst.dat[u->wst.ptr + 1] = a;
2654 u->wst.dat[u->wst.ptr + 2] = d;
2655 u->wst.dat[u->wst.ptr + 3] = c;
2656#ifndef NO_STACK_CHECKS
2657 if(__builtin_expect(u->wst.ptr < 4, 0)) {
2658 u->wst.error = 1;
2659 goto error;
2660 }
2661 if(__builtin_expect(u->wst.ptr > 251, 0)) {
2662 u->wst.error = 2;
2663 goto error;
2664 }
2665#endif
2666 u->wst.ptr += 4;
2667 }
2668 break;
2669 case 0xa7: /* OVR2k */
2670 __asm__("evaluxn_a6_OVR2k:");
2671 {
2672 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2], c = u->wst.dat[u->wst.ptr - 3], d = u->wst.dat[u->wst.ptr - 4];
2673 u->wst.dat[u->wst.ptr] = d;
2674 u->wst.dat[u->wst.ptr + 1] = c;
2675 u->wst.dat[u->wst.ptr + 2] = b;
2676 u->wst.dat[u->wst.ptr + 3] = a;
2677 u->wst.dat[u->wst.ptr + 4] = d;
2678 u->wst.dat[u->wst.ptr + 5] = c;
2679#ifndef NO_STACK_CHECKS
2680 if(__builtin_expect(u->wst.ptr < 4, 0)) {
2681 u->wst.error = 1;
2682 goto error;
2683 }
2684 if(__builtin_expect(u->wst.ptr > 249, 0)) {
2685 u->wst.error = 2;
2686 goto error;
2687 }
2688#endif
2689 u->wst.ptr += 6;
2690 }
2691 break;
2692 case 0xa5: /* ROT2k */
2693 __asm__("evaluxn_a7_ROT2k:");
2694 {
2695 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2], c = u->wst.dat[u->wst.ptr - 3], d = u->wst.dat[u->wst.ptr - 4], e = u->wst.dat[u->wst.ptr - 5], f = u->wst.dat[u->wst.ptr - 6];
2696 u->wst.dat[u->wst.ptr] = d;
2697 u->wst.dat[u->wst.ptr + 1] = c;
2698 u->wst.dat[u->wst.ptr + 2] = b;
2699 u->wst.dat[u->wst.ptr + 3] = a;
2700 u->wst.dat[u->wst.ptr + 4] = f;
2701 u->wst.dat[u->wst.ptr + 5] = e;
2702#ifndef NO_STACK_CHECKS
2703 if(__builtin_expect(u->wst.ptr < 6, 0)) {
2704 u->wst.error = 1;
2705 goto error;
2706 }
2707 if(__builtin_expect(u->wst.ptr > 249, 0)) {
2708 u->wst.error = 2;
2709 goto error;
2710 }
2711#endif
2712 u->wst.ptr += 6;
2713 }
2714 break;
2715 case 0xa8: /* EQU2k */
2716 __asm__("evaluxn_a8_EQU2k:");
2717 {
2718 u16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)), b = (u->wst.dat[u->wst.ptr - 3] | (u->wst.dat[u->wst.ptr - 4] << 8));
2719 u->wst.dat[u->wst.ptr] = b == a;
2720#ifndef NO_STACK_CHECKS
2721 if(__builtin_expect(u->wst.ptr < 4, 0)) {
2722 u->wst.error = 1;
2723 goto error;
2724 }
2725 if(__builtin_expect(u->wst.ptr > 254, 0)) {
2726 u->wst.error = 2;
2727 goto error;
2728 }
2729#endif
2730 u->wst.ptr += 1;
2731 }
2732 break;
2733 case 0xa9: /* NEQ2k */
2734 __asm__("evaluxn_a9_NEQ2k:");
2735 {
2736 u16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)), b = (u->wst.dat[u->wst.ptr - 3] | (u->wst.dat[u->wst.ptr - 4] << 8));
2737 u->wst.dat[u->wst.ptr] = b != a;
2738#ifndef NO_STACK_CHECKS
2739 if(__builtin_expect(u->wst.ptr < 4, 0)) {
2740 u->wst.error = 1;
2741 goto error;
2742 }
2743 if(__builtin_expect(u->wst.ptr > 254, 0)) {
2744 u->wst.error = 2;
2745 goto error;
2746 }
2747#endif
2748 u->wst.ptr += 1;
2749 }
2750 break;
2751 case 0xaa: /* GTH2k */
2752 __asm__("evaluxn_aa_GTH2k:");
2753 {
2754 u16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)), b = (u->wst.dat[u->wst.ptr - 3] | (u->wst.dat[u->wst.ptr - 4] << 8));
2755 u->wst.dat[u->wst.ptr] = b > a;
2756#ifndef NO_STACK_CHECKS
2757 if(__builtin_expect(u->wst.ptr < 4, 0)) {
2758 u->wst.error = 1;
2759 goto error;
2760 }
2761 if(__builtin_expect(u->wst.ptr > 254, 0)) {
2762 u->wst.error = 2;
2763 goto error;
2764 }
2765#endif
2766 u->wst.ptr += 1;
2767 }
2768 break;
2769 case 0xab: /* LTH2k */
2770 __asm__("evaluxn_ab_LTH2k:");
2771 {
2772 u16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)), b = (u->wst.dat[u->wst.ptr - 3] | (u->wst.dat[u->wst.ptr - 4] << 8));
2773 u->wst.dat[u->wst.ptr] = b < a;
2774#ifndef NO_STACK_CHECKS
2775 if(__builtin_expect(u->wst.ptr < 4, 0)) {
2776 u->wst.error = 1;
2777 goto error;
2778 }
2779 if(__builtin_expect(u->wst.ptr > 254, 0)) {
2780 u->wst.error = 2;
2781 goto error;
2782 }
2783#endif
2784 u->wst.ptr += 1;
2785 }
2786 break;
2787 case 0xac: /* JMP2k */
2788 __asm__("evaluxn_ac_JMP2k:");
2789 {
2790 u->ram.ptr = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8));
2791#ifndef NO_STACK_CHECKS
2792 if(__builtin_expect(u->wst.ptr < 2, 0)) {
2793 u->wst.error = 1;
2794 goto error;
2795 }
2796#endif
2797 }
2798 break;
2799 case 0xad: /* JCN2k */
2800 __asm__("evaluxn_ad_JCN2k:");
2801 {
2802 u16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8));
2803 if(u->wst.dat[u->wst.ptr - 3]) u->ram.ptr = a;
2804#ifndef NO_STACK_CHECKS
2805 if(__builtin_expect(u->wst.ptr < 3, 0)) {
2806 u->wst.error = 1;
2807 goto error;
2808 }
2809#endif
2810 }
2811 break;
2812 case 0xae: /* JSR2k */
2813 __asm__("evaluxn_ae_JSR2k:");
2814 {
2815 u->rst.dat[u->rst.ptr] = u->ram.ptr >> 8;
2816 u->rst.dat[u->rst.ptr + 1] = u->ram.ptr & 0xff;
2817 u->ram.ptr = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8));
2818#ifndef NO_STACK_CHECKS
2819 if(__builtin_expect(u->wst.ptr < 2, 0)) {
2820 u->wst.error = 1;
2821 goto error;
2822 }
2823 if(__builtin_expect(u->rst.ptr > 253, 0)) {
2824 u->rst.error = 2;
2825 goto error;
2826 }
2827#endif
2828 u->rst.ptr += 2;
2829 }
2830 break;
2831 case 0xaf: /* STH2k */
2832 __asm__("evaluxn_af_STH2k:");
2833 {
2834 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
2835 u->rst.dat[u->rst.ptr] = b;
2836 u->rst.dat[u->rst.ptr + 1] = a;
2837#ifndef NO_STACK_CHECKS
2838 if(__builtin_expect(u->wst.ptr < 2, 0)) {
2839 u->wst.error = 1;
2840 goto error;
2841 }
2842 if(__builtin_expect(u->rst.ptr > 253, 0)) {
2843 u->rst.error = 2;
2844 goto error;
2845 }
2846#endif
2847 u->rst.ptr += 2;
2848 }
2849 break;
2850 case 0xb0: /* LDZ2k */
2851 __asm__("evaluxn_b0_LDZ2k:");
2852 {
2853 u8 a = u->wst.dat[u->wst.ptr - 1];
2854 u->wst.dat[u->wst.ptr] = mempeek8(u->ram.dat, a);
2855 u->wst.dat[u->wst.ptr + 1] = mempeek8(u->ram.dat, a + 1);
2856#ifndef NO_STACK_CHECKS
2857 if(__builtin_expect(u->wst.ptr < 1, 0)) {
2858 u->wst.error = 1;
2859 goto error;
2860 }
2861 if(__builtin_expect(u->wst.ptr > 253, 0)) {
2862 u->wst.error = 2;
2863 goto error;
2864 }
2865#endif
2866 u->wst.ptr += 2;
2867 }
2868 break;
2869 case 0xb1: /* STZ2k */
2870 __asm__("evaluxn_b1_STZ2k:");
2871 {
2872 u8 a = u->wst.dat[u->wst.ptr - 1];
2873 u16 b = (u->wst.dat[u->wst.ptr - 2] | (u->wst.dat[u->wst.ptr - 3] << 8));
2874 mempoke16(u->ram.dat, a, b);
2875#ifndef NO_STACK_CHECKS
2876 if(__builtin_expect(u->wst.ptr < 3, 0)) {
2877 u->wst.error = 1;
2878 goto error;
2879 }
2880#endif
2881 }
2882 break;
2883 case 0xb2: /* LDR2k */
2884 __asm__("evaluxn_b2_LDR2k:");
2885 {
2886 u8 a = u->wst.dat[u->wst.ptr - 1];
2887 u->wst.dat[u->wst.ptr] = mempeek8(u->ram.dat, u->ram.ptr + (s8)a);
2888 u->wst.dat[u->wst.ptr + 1] = mempeek8(u->ram.dat, u->ram.ptr + (s8)a + 1);
2889#ifndef NO_STACK_CHECKS
2890 if(__builtin_expect(u->wst.ptr < 1, 0)) {
2891 u->wst.error = 1;
2892 goto error;
2893 }
2894 if(__builtin_expect(u->wst.ptr > 253, 0)) {
2895 u->wst.error = 2;
2896 goto error;
2897 }
2898#endif
2899 u->wst.ptr += 2;
2900 }
2901 break;
2902 case 0xb3: /* STR2k */
2903 __asm__("evaluxn_b3_STR2k:");
2904 {
2905 u8 a = u->wst.dat[u->wst.ptr - 1];
2906 u16 b = (u->wst.dat[u->wst.ptr - 2] | (u->wst.dat[u->wst.ptr - 3] << 8));
2907 mempoke16(u->ram.dat, u->ram.ptr + (s8)a, b);
2908#ifndef NO_STACK_CHECKS
2909 if(__builtin_expect(u->wst.ptr < 3, 0)) {
2910 u->wst.error = 1;
2911 goto error;
2912 }
2913#endif
2914 }
2915 break;
2916 case 0xb4: /* LDA2k */
2917 __asm__("evaluxn_b4_LDA2k:");
2918 {
2919 u16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8));
2920 u->wst.dat[u->wst.ptr] = mempeek8(u->ram.dat, a);
2921 u->wst.dat[u->wst.ptr + 1] = mempeek8(u->ram.dat, a + 1);
2922#ifndef NO_STACK_CHECKS
2923 if(__builtin_expect(u->wst.ptr < 2, 0)) {
2924 u->wst.error = 1;
2925 goto error;
2926 }
2927 if(__builtin_expect(u->wst.ptr > 253, 0)) {
2928 u->wst.error = 2;
2929 goto error;
2930 }
2931#endif
2932 u->wst.ptr += 2;
2933 }
2934 break;
2935 case 0xb5: /* STA2k */
2936 __asm__("evaluxn_b5_STA2k:");
2937 {
2938 u16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8));
2939 u16 b = (u->wst.dat[u->wst.ptr - 3] | (u->wst.dat[u->wst.ptr - 4] << 8));
2940 mempoke16(u->ram.dat, a, b);
2941#ifndef NO_STACK_CHECKS
2942 if(__builtin_expect(u->wst.ptr < 4, 0)) {
2943 u->wst.error = 1;
2944 goto error;
2945 }
2946#endif
2947 }
2948 break;
2949 case 0xb6: /* DEI2k */
2950 __asm__("evaluxn_b6_DEI2k:");
2951 {
2952 u8 a = u->wst.dat[u->wst.ptr - 1];
2953 u->wst.dat[u->wst.ptr] = devpeek8(&u->dev[a >> 4], a);
2954 u->wst.dat[u->wst.ptr + 1] = devpeek8(&u->dev[a >> 4], a + 1);
2955#ifndef NO_STACK_CHECKS
2956 if(__builtin_expect(u->wst.ptr < 1, 0)) {
2957 u->wst.error = 1;
2958 goto error;
2959 }
2960 if(__builtin_expect(u->wst.ptr > 253, 0)) {
2961 u->wst.error = 2;
2962 goto error;
2963 }
2964#endif
2965 u->wst.ptr += 2;
2966 }
2967 break;
2968 case 0xb7: /* DEO2k */
2969 __asm__("evaluxn_b7_DEO2k:");
2970 {
2971 u8 a = u->wst.dat[u->wst.ptr - 1];
2972 u16 b = (u->wst.dat[u->wst.ptr - 2] | (u->wst.dat[u->wst.ptr - 3] << 8));
2973 devpoke16(&u->dev[a >> 4], a, b);
2974#ifndef NO_STACK_CHECKS
2975 if(__builtin_expect(u->wst.ptr < 3, 0)) {
2976 u->wst.error = 1;
2977 goto error;
2978 }
2979#endif
2980 }
2981 break;
2982 case 0xb8: /* ADD2k */
2983 __asm__("evaluxn_b8_ADD2k:");
2984 {
2985 u16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)), b = (u->wst.dat[u->wst.ptr - 3] | (u->wst.dat[u->wst.ptr - 4] << 8));
2986 u->wst.dat[u->wst.ptr] = (b + a) >> 8;
2987 u->wst.dat[u->wst.ptr + 1] = (b + a) & 0xff;
2988#ifndef NO_STACK_CHECKS
2989 if(__builtin_expect(u->wst.ptr < 4, 0)) {
2990 u->wst.error = 1;
2991 goto error;
2992 }
2993 if(__builtin_expect(u->wst.ptr > 253, 0)) {
2994 u->wst.error = 2;
2995 goto error;
2996 }
2997#endif
2998 u->wst.ptr += 2;
2999 }
3000 break;
3001 case 0xb9: /* SUB2k */
3002 __asm__("evaluxn_b9_SUB2k:");
3003 {
3004 u16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)), b = (u->wst.dat[u->wst.ptr - 3] | (u->wst.dat[u->wst.ptr - 4] << 8));
3005 u->wst.dat[u->wst.ptr] = (b - a) >> 8;
3006 u->wst.dat[u->wst.ptr + 1] = (b - a) & 0xff;
3007#ifndef NO_STACK_CHECKS
3008 if(__builtin_expect(u->wst.ptr < 4, 0)) {
3009 u->wst.error = 1;
3010 goto error;
3011 }
3012 if(__builtin_expect(u->wst.ptr > 253, 0)) {
3013 u->wst.error = 2;
3014 goto error;
3015 }
3016#endif
3017 u->wst.ptr += 2;
3018 }
3019 break;
3020 case 0xba: /* MUL2k */
3021 __asm__("evaluxn_ba_MUL2k:");
3022 {
3023 u16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)), b = (u->wst.dat[u->wst.ptr - 3] | (u->wst.dat[u->wst.ptr - 4] << 8));
3024 u->wst.dat[u->wst.ptr] = (b * a) >> 8;
3025 u->wst.dat[u->wst.ptr + 1] = (b * a) & 0xff;
3026#ifndef NO_STACK_CHECKS
3027 if(__builtin_expect(u->wst.ptr < 4, 0)) {
3028 u->wst.error = 1;
3029 goto error;
3030 }
3031 if(__builtin_expect(u->wst.ptr > 253, 0)) {
3032 u->wst.error = 2;
3033 goto error;
3034 }
3035#endif
3036 u->wst.ptr += 2;
3037 }
3038 break;
3039 case 0xbb: /* DIV2k */
3040 __asm__("evaluxn_bb_DIV2k:");
3041 {
3042 u16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)), b = (u->wst.dat[u->wst.ptr - 3] | (u->wst.dat[u->wst.ptr - 4] << 8));
3043 if(a == 0) {
3044 u->wst.error = 3;
3045#ifndef NO_STACK_CHECKS
3046 goto error;
3047#endif
3048 a = 1;
3049 }
3050 u->wst.dat[u->wst.ptr] = (b / a) >> 8;
3051 u->wst.dat[u->wst.ptr + 1] = (b / a) & 0xff;
3052#ifndef NO_STACK_CHECKS
3053 if(__builtin_expect(u->wst.ptr < 4, 0)) {
3054 u->wst.error = 1;
3055 goto error;
3056 }
3057 if(__builtin_expect(u->wst.ptr > 253, 0)) {
3058 u->wst.error = 2;
3059 goto error;
3060 }
3061#endif
3062 u->wst.ptr += 2;
3063 }
3064 break;
3065 case 0xbc: /* AND2k */
3066 __asm__("evaluxn_bc_AND2k:");
3067 {
3068 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2], c = u->wst.dat[u->wst.ptr - 3], d = u->wst.dat[u->wst.ptr - 4];
3069 u->wst.dat[u->wst.ptr] = d & b;
3070 u->wst.dat[u->wst.ptr + 1] = c & a;
3071#ifndef NO_STACK_CHECKS
3072 if(__builtin_expect(u->wst.ptr < 4, 0)) {
3073 u->wst.error = 1;
3074 goto error;
3075 }
3076 if(__builtin_expect(u->wst.ptr > 253, 0)) {
3077 u->wst.error = 2;
3078 goto error;
3079 }
3080#endif
3081 u->wst.ptr += 2;
3082 }
3083 break;
3084 case 0xbd: /* ORA2k */
3085 __asm__("evaluxn_bd_ORA2k:");
3086 {
3087 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2], c = u->wst.dat[u->wst.ptr - 3], d = u->wst.dat[u->wst.ptr - 4];
3088 u->wst.dat[u->wst.ptr] = d | b;
3089 u->wst.dat[u->wst.ptr + 1] = c | a;
3090#ifndef NO_STACK_CHECKS
3091 if(__builtin_expect(u->wst.ptr < 4, 0)) {
3092 u->wst.error = 1;
3093 goto error;
3094 }
3095 if(__builtin_expect(u->wst.ptr > 253, 0)) {
3096 u->wst.error = 2;
3097 goto error;
3098 }
3099#endif
3100 u->wst.ptr += 2;
3101 }
3102 break;
3103 case 0xbe: /* EOR2k */
3104 __asm__("evaluxn_be_EOR2k:");
3105 {
3106 u8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2], c = u->wst.dat[u->wst.ptr - 3], d = u->wst.dat[u->wst.ptr - 4];
3107 u->wst.dat[u->wst.ptr] = d ^ b;
3108 u->wst.dat[u->wst.ptr + 1] = c ^ a;
3109#ifndef NO_STACK_CHECKS
3110 if(__builtin_expect(u->wst.ptr < 4, 0)) {
3111 u->wst.error = 1;
3112 goto error;
3113 }
3114 if(__builtin_expect(u->wst.ptr > 253, 0)) {
3115 u->wst.error = 2;
3116 goto error;
3117 }
3118#endif
3119 u->wst.ptr += 2;
3120 }
3121 break;
3122 case 0xbf: /* SFT2k */
3123 __asm__("evaluxn_bf_SFT2k:");
3124 {
3125 u8 a = u->wst.dat[u->wst.ptr - 1];
3126 u16 b = (u->wst.dat[u->wst.ptr - 2] | (u->wst.dat[u->wst.ptr - 3] << 8));
3127 u->wst.dat[u->wst.ptr] = (b >> (a & 0x0f) << ((a & 0xf0) >> 4)) >> 8;
3128 u->wst.dat[u->wst.ptr + 1] = (b >> (a & 0x0f) << ((a & 0xf0) >> 4)) & 0xff;
3129#ifndef NO_STACK_CHECKS
3130 if(__builtin_expect(u->wst.ptr < 3, 0)) {
3131 u->wst.error = 1;
3132 goto error;
3133 }
3134 if(__builtin_expect(u->wst.ptr > 253, 0)) {
3135 u->wst.error = 2;
3136 goto error;
3137 }
3138#endif
3139 u->wst.ptr += 2;
3140 }
3141 break;
3142 case 0xc1: /* INCkr */
3143 __asm__("evaluxn_c1_INCkr:");
3144 {
3145 u8 a = u->rst.dat[u->rst.ptr - 1];
3146 u->rst.dat[u->rst.ptr] = a + 1;
3147#ifndef NO_STACK_CHECKS
3148 if(__builtin_expect(u->rst.ptr < 1, 0)) {
3149 u->rst.error = 1;
3150 goto error;
3151 }
3152 if(__builtin_expect(u->rst.ptr > 254, 0)) {
3153 u->rst.error = 2;
3154 goto error;
3155 }
3156#endif
3157 u->rst.ptr += 1;
3158 }
3159 break;
3160 case 0xc2: /* POPkr */
3161 __asm__("evaluxn_c2_POPkr:");
3162 {
3163 u->rst.dat[u->rst.ptr - 1];
3164#ifndef NO_STACK_CHECKS
3165 if(__builtin_expect(u->rst.ptr < 1, 0)) {
3166 u->rst.error = 1;
3167 goto error;
3168 }
3169#endif
3170 }
3171 break;
3172 case 0xc6: /* DUPkr */
3173 __asm__("evaluxn_c3_DUPkr:");
3174 {
3175 u8 a = u->rst.dat[u->rst.ptr - 1];
3176 u->rst.dat[u->rst.ptr] = a;
3177 u->rst.dat[u->rst.ptr + 1] = a;
3178#ifndef NO_STACK_CHECKS
3179 if(__builtin_expect(u->rst.ptr < 1, 0)) {
3180 u->rst.error = 1;
3181 goto error;
3182 }
3183 if(__builtin_expect(u->rst.ptr > 253, 0)) {
3184 u->rst.error = 2;
3185 goto error;
3186 }
3187#endif
3188 u->rst.ptr += 2;
3189 }
3190 break;
3191 case 0xc3: /* NIPkr */
3192 __asm__("evaluxn_c4_NIPkr:");
3193 {
3194 u8 a = u->rst.dat[u->rst.ptr - 1];
3195 u->rst.dat[u->rst.ptr - 2];
3196 u->rst.dat[u->rst.ptr] = a;
3197#ifndef NO_STACK_CHECKS
3198 if(__builtin_expect(u->rst.ptr < 2, 0)) {
3199 u->rst.error = 1;
3200 goto error;
3201 }
3202 if(__builtin_expect(u->rst.ptr > 254, 0)) {
3203 u->rst.error = 2;
3204 goto error;
3205 }
3206#endif
3207 u->rst.ptr += 1;
3208 }
3209 break;
3210 case 0xc4: /* SWPkr */
3211 __asm__("evaluxn_c5_SWPkr:");
3212 {
3213 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
3214 u->rst.dat[u->rst.ptr] = a;
3215 u->rst.dat[u->rst.ptr + 1] = b;
3216#ifndef NO_STACK_CHECKS
3217 if(__builtin_expect(u->rst.ptr < 2, 0)) {
3218 u->rst.error = 1;
3219 goto error;
3220 }
3221 if(__builtin_expect(u->rst.ptr > 253, 0)) {
3222 u->rst.error = 2;
3223 goto error;
3224 }
3225#endif
3226 u->rst.ptr += 2;
3227 }
3228 break;
3229 case 0xc7: /* OVRkr */
3230 __asm__("evaluxn_c6_OVRkr:");
3231 {
3232 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
3233 u->rst.dat[u->rst.ptr] = b;
3234 u->rst.dat[u->rst.ptr + 1] = a;
3235 u->rst.dat[u->rst.ptr + 2] = b;
3236#ifndef NO_STACK_CHECKS
3237 if(__builtin_expect(u->rst.ptr < 2, 0)) {
3238 u->rst.error = 1;
3239 goto error;
3240 }
3241 if(__builtin_expect(u->rst.ptr > 252, 0)) {
3242 u->rst.error = 2;
3243 goto error;
3244 }
3245#endif
3246 u->rst.ptr += 3;
3247 }
3248 break;
3249 case 0xc5: /* ROTkr */
3250 __asm__("evaluxn_c7_ROTkr:");
3251 {
3252 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2], c = u->rst.dat[u->rst.ptr - 3];
3253 u->rst.dat[u->rst.ptr] = b;
3254 u->rst.dat[u->rst.ptr + 1] = a;
3255 u->rst.dat[u->rst.ptr + 2] = c;
3256#ifndef NO_STACK_CHECKS
3257 if(__builtin_expect(u->rst.ptr < 3, 0)) {
3258 u->rst.error = 1;
3259 goto error;
3260 }
3261 if(__builtin_expect(u->rst.ptr > 252, 0)) {
3262 u->rst.error = 2;
3263 goto error;
3264 }
3265#endif
3266 u->rst.ptr += 3;
3267 }
3268 break;
3269 case 0xc8: /* EQUkr */
3270 __asm__("evaluxn_c8_EQUkr:");
3271 {
3272 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
3273 u->rst.dat[u->rst.ptr] = b == a;
3274#ifndef NO_STACK_CHECKS
3275 if(__builtin_expect(u->rst.ptr < 2, 0)) {
3276 u->rst.error = 1;
3277 goto error;
3278 }
3279 if(__builtin_expect(u->rst.ptr > 254, 0)) {
3280 u->rst.error = 2;
3281 goto error;
3282 }
3283#endif
3284 u->rst.ptr += 1;
3285 }
3286 break;
3287 case 0xc9: /* NEQkr */
3288 __asm__("evaluxn_c9_NEQkr:");
3289 {
3290 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
3291 u->rst.dat[u->rst.ptr] = b != a;
3292#ifndef NO_STACK_CHECKS
3293 if(__builtin_expect(u->rst.ptr < 2, 0)) {
3294 u->rst.error = 1;
3295 goto error;
3296 }
3297 if(__builtin_expect(u->rst.ptr > 254, 0)) {
3298 u->rst.error = 2;
3299 goto error;
3300 }
3301#endif
3302 u->rst.ptr += 1;
3303 }
3304 break;
3305 case 0xca: /* GTHkr */
3306 __asm__("evaluxn_ca_GTHkr:");
3307 {
3308 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
3309 u->rst.dat[u->rst.ptr] = b > a;
3310#ifndef NO_STACK_CHECKS
3311 if(__builtin_expect(u->rst.ptr < 2, 0)) {
3312 u->rst.error = 1;
3313 goto error;
3314 }
3315 if(__builtin_expect(u->rst.ptr > 254, 0)) {
3316 u->rst.error = 2;
3317 goto error;
3318 }
3319#endif
3320 u->rst.ptr += 1;
3321 }
3322 break;
3323 case 0xcb: /* LTHkr */
3324 __asm__("evaluxn_cb_LTHkr:");
3325 {
3326 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
3327 u->rst.dat[u->rst.ptr] = b < a;
3328#ifndef NO_STACK_CHECKS
3329 if(__builtin_expect(u->rst.ptr < 2, 0)) {
3330 u->rst.error = 1;
3331 goto error;
3332 }
3333 if(__builtin_expect(u->rst.ptr > 254, 0)) {
3334 u->rst.error = 2;
3335 goto error;
3336 }
3337#endif
3338 u->rst.ptr += 1;
3339 }
3340 break;
3341 case 0xcc: /* JMPkr */
3342 __asm__("evaluxn_cc_JMPkr:");
3343 {
3344 u8 a = u->rst.dat[u->rst.ptr - 1];
3345 u->ram.ptr += (s8)a;
3346#ifndef NO_STACK_CHECKS
3347 if(__builtin_expect(u->rst.ptr < 1, 0)) {
3348 u->rst.error = 1;
3349 goto error;
3350 }
3351#endif
3352 }
3353 break;
3354 case 0xcd: /* JCNkr */
3355 __asm__("evaluxn_cd_JCNkr:");
3356 {
3357 u8 a = u->rst.dat[u->rst.ptr - 1];
3358 if(u->rst.dat[u->rst.ptr - 2]) u->ram.ptr += (s8)a;
3359#ifndef NO_STACK_CHECKS
3360 if(__builtin_expect(u->rst.ptr < 2, 0)) {
3361 u->rst.error = 1;
3362 goto error;
3363 }
3364#endif
3365 }
3366 break;
3367 case 0xce: /* JSRkr */
3368 __asm__("evaluxn_ce_JSRkr:");
3369 {
3370 u8 a = u->rst.dat[u->rst.ptr - 1];
3371 u->wst.dat[u->wst.ptr] = u->ram.ptr >> 8;
3372 u->wst.dat[u->wst.ptr + 1] = u->ram.ptr & 0xff;
3373 u->ram.ptr += (s8)a;
3374#ifndef NO_STACK_CHECKS
3375 if(__builtin_expect(u->rst.ptr < 1, 0)) {
3376 u->rst.error = 1;
3377 goto error;
3378 }
3379 if(__builtin_expect(u->wst.ptr > 253, 0)) {
3380 u->wst.error = 2;
3381 goto error;
3382 }
3383#endif
3384 u->wst.ptr += 2;
3385 }
3386 break;
3387 case 0xcf: /* STHkr */
3388 __asm__("evaluxn_cf_STHkr:");
3389 {
3390 u8 a = u->rst.dat[u->rst.ptr - 1];
3391 u->wst.dat[u->wst.ptr] = a;
3392#ifndef NO_STACK_CHECKS
3393 if(__builtin_expect(u->rst.ptr < 1, 0)) {
3394 u->rst.error = 1;
3395 goto error;
3396 }
3397 if(__builtin_expect(u->wst.ptr > 254, 0)) {
3398 u->wst.error = 2;
3399 goto error;
3400 }
3401#endif
3402 u->wst.ptr += 1;
3403 }
3404 break;
3405 case 0xd0: /* LDZkr */
3406 __asm__("evaluxn_d0_LDZkr:");
3407 {
3408 u8 a = u->rst.dat[u->rst.ptr - 1];
3409 u->rst.dat[u->rst.ptr] = mempeek8(u->ram.dat, a);
3410#ifndef NO_STACK_CHECKS
3411 if(__builtin_expect(u->rst.ptr < 1, 0)) {
3412 u->rst.error = 1;
3413 goto error;
3414 }
3415 if(__builtin_expect(u->rst.ptr > 254, 0)) {
3416 u->rst.error = 2;
3417 goto error;
3418 }
3419#endif
3420 u->rst.ptr += 1;
3421 }
3422 break;
3423 case 0xd1: /* STZkr */
3424 __asm__("evaluxn_d1_STZkr:");
3425 {
3426 u8 a = u->rst.dat[u->rst.ptr - 1];
3427 u8 b = u->rst.dat[u->rst.ptr - 2];
3428 mempoke8(u->ram.dat, a, b);
3429#ifndef NO_STACK_CHECKS
3430 if(__builtin_expect(u->rst.ptr < 2, 0)) {
3431 u->rst.error = 1;
3432 goto error;
3433 }
3434#endif
3435 }
3436 break;
3437 case 0xd2: /* LDRkr */
3438 __asm__("evaluxn_d2_LDRkr:");
3439 {
3440 u8 a = u->rst.dat[u->rst.ptr - 1];
3441 u->rst.dat[u->rst.ptr] = mempeek8(u->ram.dat, u->ram.ptr + (s8)a);
3442#ifndef NO_STACK_CHECKS
3443 if(__builtin_expect(u->rst.ptr < 1, 0)) {
3444 u->rst.error = 1;
3445 goto error;
3446 }
3447 if(__builtin_expect(u->rst.ptr > 254, 0)) {
3448 u->rst.error = 2;
3449 goto error;
3450 }
3451#endif
3452 u->rst.ptr += 1;
3453 }
3454 break;
3455 case 0xd3: /* STRkr */
3456 __asm__("evaluxn_d3_STRkr:");
3457 {
3458 u8 a = u->rst.dat[u->rst.ptr - 1];
3459 u8 b = u->rst.dat[u->rst.ptr - 2];
3460 mempoke8(u->ram.dat, u->ram.ptr + (s8)a, b);
3461#ifndef NO_STACK_CHECKS
3462 if(__builtin_expect(u->rst.ptr < 2, 0)) {
3463 u->rst.error = 1;
3464 goto error;
3465 }
3466#endif
3467 }
3468 break;
3469 case 0xd4: /* LDAkr */
3470 __asm__("evaluxn_d4_LDAkr:");
3471 {
3472 u16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8));
3473 u->rst.dat[u->rst.ptr] = mempeek8(u->ram.dat, a);
3474#ifndef NO_STACK_CHECKS
3475 if(__builtin_expect(u->rst.ptr < 2, 0)) {
3476 u->rst.error = 1;
3477 goto error;
3478 }
3479 if(__builtin_expect(u->rst.ptr > 254, 0)) {
3480 u->rst.error = 2;
3481 goto error;
3482 }
3483#endif
3484 u->rst.ptr += 1;
3485 }
3486 break;
3487 case 0xd5: /* STAkr */
3488 __asm__("evaluxn_d5_STAkr:");
3489 {
3490 u16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8));
3491 u8 b = u->rst.dat[u->rst.ptr - 3];
3492 mempoke8(u->ram.dat, a, b);
3493#ifndef NO_STACK_CHECKS
3494 if(__builtin_expect(u->rst.ptr < 3, 0)) {
3495 u->rst.error = 1;
3496 goto error;
3497 }
3498#endif
3499 }
3500 break;
3501 case 0xd6: /* DEIkr */
3502 __asm__("evaluxn_d6_DEIkr:");
3503 {
3504 u8 a = u->rst.dat[u->rst.ptr - 1];
3505 u->rst.dat[u->rst.ptr] = devpeek8(&u->dev[a >> 4], a);
3506#ifndef NO_STACK_CHECKS
3507 if(__builtin_expect(u->rst.ptr < 1, 0)) {
3508 u->rst.error = 1;
3509 goto error;
3510 }
3511 if(__builtin_expect(u->rst.ptr > 254, 0)) {
3512 u->rst.error = 2;
3513 goto error;
3514 }
3515#endif
3516 u->rst.ptr += 1;
3517 }
3518 break;
3519 case 0xd7: /* DEOkr */
3520 __asm__("evaluxn_d7_DEOkr:");
3521 {
3522 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
3523 devpoke8(&u->dev[a >> 4], a, b);
3524#ifndef NO_STACK_CHECKS
3525 if(__builtin_expect(u->rst.ptr < 2, 0)) {
3526 u->rst.error = 1;
3527 goto error;
3528 }
3529#endif
3530 }
3531 break;
3532 case 0xd8: /* ADDkr */
3533 __asm__("evaluxn_d8_ADDkr:");
3534 {
3535 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
3536 u->rst.dat[u->rst.ptr] = b + a;
3537#ifndef NO_STACK_CHECKS
3538 if(__builtin_expect(u->rst.ptr < 2, 0)) {
3539 u->rst.error = 1;
3540 goto error;
3541 }
3542 if(__builtin_expect(u->rst.ptr > 254, 0)) {
3543 u->rst.error = 2;
3544 goto error;
3545 }
3546#endif
3547 u->rst.ptr += 1;
3548 }
3549 break;
3550 case 0xd9: /* SUBkr */
3551 __asm__("evaluxn_d9_SUBkr:");
3552 {
3553 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
3554 u->rst.dat[u->rst.ptr] = b - a;
3555#ifndef NO_STACK_CHECKS
3556 if(__builtin_expect(u->rst.ptr < 2, 0)) {
3557 u->rst.error = 1;
3558 goto error;
3559 }
3560 if(__builtin_expect(u->rst.ptr > 254, 0)) {
3561 u->rst.error = 2;
3562 goto error;
3563 }
3564#endif
3565 u->rst.ptr += 1;
3566 }
3567 break;
3568 case 0xda: /* MULkr */
3569 __asm__("evaluxn_da_MULkr:");
3570 {
3571 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
3572 u->rst.dat[u->rst.ptr] = b * a;
3573#ifndef NO_STACK_CHECKS
3574 if(__builtin_expect(u->rst.ptr < 2, 0)) {
3575 u->rst.error = 1;
3576 goto error;
3577 }
3578 if(__builtin_expect(u->rst.ptr > 254, 0)) {
3579 u->rst.error = 2;
3580 goto error;
3581 }
3582#endif
3583 u->rst.ptr += 1;
3584 }
3585 break;
3586 case 0xdb: /* DIVkr */
3587 __asm__("evaluxn_db_DIVkr:");
3588 {
3589 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
3590 if(a == 0) {
3591 u->rst.error = 3;
3592#ifndef NO_STACK_CHECKS
3593 goto error;
3594#endif
3595 a = 1;
3596 }
3597 u->rst.dat[u->rst.ptr] = b / a;
3598#ifndef NO_STACK_CHECKS
3599 if(__builtin_expect(u->rst.ptr < 2, 0)) {
3600 u->rst.error = 1;
3601 goto error;
3602 }
3603 if(__builtin_expect(u->rst.ptr > 254, 0)) {
3604 u->rst.error = 2;
3605 goto error;
3606 }
3607#endif
3608 u->rst.ptr += 1;
3609 }
3610 break;
3611 case 0xdc: /* ANDkr */
3612 __asm__("evaluxn_dc_ANDkr:");
3613 {
3614 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
3615 u->rst.dat[u->rst.ptr] = b & a;
3616#ifndef NO_STACK_CHECKS
3617 if(__builtin_expect(u->rst.ptr < 2, 0)) {
3618 u->rst.error = 1;
3619 goto error;
3620 }
3621 if(__builtin_expect(u->rst.ptr > 254, 0)) {
3622 u->rst.error = 2;
3623 goto error;
3624 }
3625#endif
3626 u->rst.ptr += 1;
3627 }
3628 break;
3629 case 0xdd: /* ORAkr */
3630 __asm__("evaluxn_dd_ORAkr:");
3631 {
3632 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
3633 u->rst.dat[u->rst.ptr] = b | a;
3634#ifndef NO_STACK_CHECKS
3635 if(__builtin_expect(u->rst.ptr < 2, 0)) {
3636 u->rst.error = 1;
3637 goto error;
3638 }
3639 if(__builtin_expect(u->rst.ptr > 254, 0)) {
3640 u->rst.error = 2;
3641 goto error;
3642 }
3643#endif
3644 u->rst.ptr += 1;
3645 }
3646 break;
3647 case 0xde: /* EORkr */
3648 __asm__("evaluxn_de_EORkr:");
3649 {
3650 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
3651 u->rst.dat[u->rst.ptr] = b ^ a;
3652#ifndef NO_STACK_CHECKS
3653 if(__builtin_expect(u->rst.ptr < 2, 0)) {
3654 u->rst.error = 1;
3655 goto error;
3656 }
3657 if(__builtin_expect(u->rst.ptr > 254, 0)) {
3658 u->rst.error = 2;
3659 goto error;
3660 }
3661#endif
3662 u->rst.ptr += 1;
3663 }
3664 break;
3665 case 0xdf: /* SFTkr */
3666 __asm__("evaluxn_df_SFTkr:");
3667 {
3668 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
3669 u->rst.dat[u->rst.ptr] = b >> (a & 0x07) << ((a & 0x70) >> 4);
3670#ifndef NO_STACK_CHECKS
3671 if(__builtin_expect(u->rst.ptr < 2, 0)) {
3672 u->rst.error = 1;
3673 goto error;
3674 }
3675 if(__builtin_expect(u->rst.ptr > 254, 0)) {
3676 u->rst.error = 2;
3677 goto error;
3678 }
3679#endif
3680 u->rst.ptr += 1;
3681 }
3682 break;
3683 case 0xe1: /* INC2kr */
3684 __asm__("evaluxn_e1_INC2kr:");
3685 {
3686 u16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8));
3687 u->rst.dat[u->rst.ptr] = (a + 1) >> 8;
3688 u->rst.dat[u->rst.ptr + 1] = (a + 1) & 0xff;
3689#ifndef NO_STACK_CHECKS
3690 if(__builtin_expect(u->rst.ptr < 2, 0)) {
3691 u->rst.error = 1;
3692 goto error;
3693 }
3694 if(__builtin_expect(u->rst.ptr > 253, 0)) {
3695 u->rst.error = 2;
3696 goto error;
3697 }
3698#endif
3699 u->rst.ptr += 2;
3700 }
3701 break;
3702 case 0xe2: /* POP2kr */
3703 __asm__("evaluxn_e2_POP2kr:");
3704 {
3705 (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8));
3706#ifndef NO_STACK_CHECKS
3707 if(__builtin_expect(u->rst.ptr < 2, 0)) {
3708 u->rst.error = 1;
3709 goto error;
3710 }
3711#endif
3712 }
3713 break;
3714 case 0xe6: /* DUP2kr */
3715 __asm__("evaluxn_e3_DUP2kr:");
3716 {
3717 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
3718 u->rst.dat[u->rst.ptr] = b;
3719 u->rst.dat[u->rst.ptr + 1] = a;
3720 u->rst.dat[u->rst.ptr + 2] = b;
3721 u->rst.dat[u->rst.ptr + 3] = a;
3722#ifndef NO_STACK_CHECKS
3723 if(__builtin_expect(u->rst.ptr < 2, 0)) {
3724 u->rst.error = 1;
3725 goto error;
3726 }
3727 if(__builtin_expect(u->rst.ptr > 251, 0)) {
3728 u->rst.error = 2;
3729 goto error;
3730 }
3731#endif
3732 u->rst.ptr += 4;
3733 }
3734 break;
3735 case 0xe3: /* NIP2kr */
3736 __asm__("evaluxn_e4_NIP2kr:");
3737 {
3738 u16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8));
3739 (u->rst.dat[u->rst.ptr - 3] | (u->rst.dat[u->rst.ptr - 4] << 8));
3740 u->rst.dat[u->rst.ptr] = a >> 8;
3741 u->rst.dat[u->rst.ptr + 1] = a & 0xff;
3742#ifndef NO_STACK_CHECKS
3743 if(__builtin_expect(u->rst.ptr < 4, 0)) {
3744 u->rst.error = 1;
3745 goto error;
3746 }
3747 if(__builtin_expect(u->rst.ptr > 253, 0)) {
3748 u->rst.error = 2;
3749 goto error;
3750 }
3751#endif
3752 u->rst.ptr += 2;
3753 }
3754 break;
3755 case 0xe4: /* SWP2kr */
3756 __asm__("evaluxn_e5_SWP2kr:");
3757 {
3758 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2], c = u->rst.dat[u->rst.ptr - 3], d = u->rst.dat[u->rst.ptr - 4];
3759 u->rst.dat[u->rst.ptr] = b;
3760 u->rst.dat[u->rst.ptr + 1] = a;
3761 u->rst.dat[u->rst.ptr + 2] = d;
3762 u->rst.dat[u->rst.ptr + 3] = c;
3763#ifndef NO_STACK_CHECKS
3764 if(__builtin_expect(u->rst.ptr < 4, 0)) {
3765 u->rst.error = 1;
3766 goto error;
3767 }
3768 if(__builtin_expect(u->rst.ptr > 251, 0)) {
3769 u->rst.error = 2;
3770 goto error;
3771 }
3772#endif
3773 u->rst.ptr += 4;
3774 }
3775 break;
3776 case 0xe7: /* OVR2kr */
3777 __asm__("evaluxn_e6_OVR2kr:");
3778 {
3779 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2], c = u->rst.dat[u->rst.ptr - 3], d = u->rst.dat[u->rst.ptr - 4];
3780 u->rst.dat[u->rst.ptr] = d;
3781 u->rst.dat[u->rst.ptr + 1] = c;
3782 u->rst.dat[u->rst.ptr + 2] = b;
3783 u->rst.dat[u->rst.ptr + 3] = a;
3784 u->rst.dat[u->rst.ptr + 4] = d;
3785 u->rst.dat[u->rst.ptr + 5] = c;
3786#ifndef NO_STACK_CHECKS
3787 if(__builtin_expect(u->rst.ptr < 4, 0)) {
3788 u->rst.error = 1;
3789 goto error;
3790 }
3791 if(__builtin_expect(u->rst.ptr > 249, 0)) {
3792 u->rst.error = 2;
3793 goto error;
3794 }
3795#endif
3796 u->rst.ptr += 6;
3797 }
3798 break;
3799 case 0xe5: /* ROT2kr */
3800 __asm__("evaluxn_e7_ROT2kr:");
3801 {
3802 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2], c = u->rst.dat[u->rst.ptr - 3], d = u->rst.dat[u->rst.ptr - 4], e = u->rst.dat[u->rst.ptr - 5], f = u->rst.dat[u->rst.ptr - 6];
3803 u->rst.dat[u->rst.ptr] = d;
3804 u->rst.dat[u->rst.ptr + 1] = c;
3805 u->rst.dat[u->rst.ptr + 2] = b;
3806 u->rst.dat[u->rst.ptr + 3] = a;
3807 u->rst.dat[u->rst.ptr + 4] = f;
3808 u->rst.dat[u->rst.ptr + 5] = e;
3809#ifndef NO_STACK_CHECKS
3810 if(__builtin_expect(u->rst.ptr < 6, 0)) {
3811 u->rst.error = 1;
3812 goto error;
3813 }
3814 if(__builtin_expect(u->rst.ptr > 249, 0)) {
3815 u->rst.error = 2;
3816 goto error;
3817 }
3818#endif
3819 u->rst.ptr += 6;
3820 }
3821 break;
3822 case 0xe8: /* EQU2kr */
3823 __asm__("evaluxn_e8_EQU2kr:");
3824 {
3825 u16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)), b = (u->rst.dat[u->rst.ptr - 3] | (u->rst.dat[u->rst.ptr - 4] << 8));
3826 u->rst.dat[u->rst.ptr] = b == a;
3827#ifndef NO_STACK_CHECKS
3828 if(__builtin_expect(u->rst.ptr < 4, 0)) {
3829 u->rst.error = 1;
3830 goto error;
3831 }
3832 if(__builtin_expect(u->rst.ptr > 254, 0)) {
3833 u->rst.error = 2;
3834 goto error;
3835 }
3836#endif
3837 u->rst.ptr += 1;
3838 }
3839 break;
3840 case 0xe9: /* NEQ2kr */
3841 __asm__("evaluxn_e9_NEQ2kr:");
3842 {
3843 u16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)), b = (u->rst.dat[u->rst.ptr - 3] | (u->rst.dat[u->rst.ptr - 4] << 8));
3844 u->rst.dat[u->rst.ptr] = b != a;
3845#ifndef NO_STACK_CHECKS
3846 if(__builtin_expect(u->rst.ptr < 4, 0)) {
3847 u->rst.error = 1;
3848 goto error;
3849 }
3850 if(__builtin_expect(u->rst.ptr > 254, 0)) {
3851 u->rst.error = 2;
3852 goto error;
3853 }
3854#endif
3855 u->rst.ptr += 1;
3856 }
3857 break;
3858 case 0xea: /* GTH2kr */
3859 __asm__("evaluxn_ea_GTH2kr:");
3860 {
3861 u16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)), b = (u->rst.dat[u->rst.ptr - 3] | (u->rst.dat[u->rst.ptr - 4] << 8));
3862 u->rst.dat[u->rst.ptr] = b > a;
3863#ifndef NO_STACK_CHECKS
3864 if(__builtin_expect(u->rst.ptr < 4, 0)) {
3865 u->rst.error = 1;
3866 goto error;
3867 }
3868 if(__builtin_expect(u->rst.ptr > 254, 0)) {
3869 u->rst.error = 2;
3870 goto error;
3871 }
3872#endif
3873 u->rst.ptr += 1;
3874 }
3875 break;
3876 case 0xeb: /* LTH2kr */
3877 __asm__("evaluxn_eb_LTH2kr:");
3878 {
3879 u16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)), b = (u->rst.dat[u->rst.ptr - 3] | (u->rst.dat[u->rst.ptr - 4] << 8));
3880 u->rst.dat[u->rst.ptr] = b < a;
3881#ifndef NO_STACK_CHECKS
3882 if(__builtin_expect(u->rst.ptr < 4, 0)) {
3883 u->rst.error = 1;
3884 goto error;
3885 }
3886 if(__builtin_expect(u->rst.ptr > 254, 0)) {
3887 u->rst.error = 2;
3888 goto error;
3889 }
3890#endif
3891 u->rst.ptr += 1;
3892 }
3893 break;
3894 case 0xec: /* JMP2kr */
3895 __asm__("evaluxn_ec_JMP2kr:");
3896 {
3897 u->ram.ptr = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8));
3898#ifndef NO_STACK_CHECKS
3899 if(__builtin_expect(u->rst.ptr < 2, 0)) {
3900 u->rst.error = 1;
3901 goto error;
3902 }
3903#endif
3904 }
3905 break;
3906 case 0xed: /* JCN2kr */
3907 __asm__("evaluxn_ed_JCN2kr:");
3908 {
3909 u16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8));
3910 if(u->rst.dat[u->rst.ptr - 3]) u->ram.ptr = a;
3911#ifndef NO_STACK_CHECKS
3912 if(__builtin_expect(u->rst.ptr < 3, 0)) {
3913 u->rst.error = 1;
3914 goto error;
3915 }
3916#endif
3917 }
3918 break;
3919 case 0xee: /* JSR2kr */
3920 __asm__("evaluxn_ee_JSR2kr:");
3921 {
3922 u->wst.dat[u->wst.ptr] = u->ram.ptr >> 8;
3923 u->wst.dat[u->wst.ptr + 1] = u->ram.ptr & 0xff;
3924 u->ram.ptr = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8));
3925#ifndef NO_STACK_CHECKS
3926 if(__builtin_expect(u->rst.ptr < 2, 0)) {
3927 u->rst.error = 1;
3928 goto error;
3929 }
3930 if(__builtin_expect(u->wst.ptr > 253, 0)) {
3931 u->wst.error = 2;
3932 goto error;
3933 }
3934#endif
3935 u->wst.ptr += 2;
3936 }
3937 break;
3938 case 0xef: /* STH2kr */
3939 __asm__("evaluxn_ef_STH2kr:");
3940 {
3941 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
3942 u->wst.dat[u->wst.ptr] = b;
3943 u->wst.dat[u->wst.ptr + 1] = a;
3944#ifndef NO_STACK_CHECKS
3945 if(__builtin_expect(u->rst.ptr < 2, 0)) {
3946 u->rst.error = 1;
3947 goto error;
3948 }
3949 if(__builtin_expect(u->wst.ptr > 253, 0)) {
3950 u->wst.error = 2;
3951 goto error;
3952 }
3953#endif
3954 u->wst.ptr += 2;
3955 }
3956 break;
3957 case 0xf0: /* LDZ2kr */
3958 __asm__("evaluxn_f0_LDZ2kr:");
3959 {
3960 u8 a = u->rst.dat[u->rst.ptr - 1];
3961 u->rst.dat[u->rst.ptr] = mempeek8(u->ram.dat, a);
3962 u->rst.dat[u->rst.ptr + 1] = mempeek8(u->ram.dat, a + 1);
3963#ifndef NO_STACK_CHECKS
3964 if(__builtin_expect(u->rst.ptr < 1, 0)) {
3965 u->rst.error = 1;
3966 goto error;
3967 }
3968 if(__builtin_expect(u->rst.ptr > 253, 0)) {
3969 u->rst.error = 2;
3970 goto error;
3971 }
3972#endif
3973 u->rst.ptr += 2;
3974 }
3975 break;
3976 case 0xf1: /* STZ2kr */
3977 __asm__("evaluxn_f1_STZ2kr:");
3978 {
3979 u8 a = u->rst.dat[u->rst.ptr - 1];
3980 u16 b = (u->rst.dat[u->rst.ptr - 2] | (u->rst.dat[u->rst.ptr - 3] << 8));
3981 mempoke16(u->ram.dat, a, b);
3982#ifndef NO_STACK_CHECKS
3983 if(__builtin_expect(u->rst.ptr < 3, 0)) {
3984 u->rst.error = 1;
3985 goto error;
3986 }
3987#endif
3988 }
3989 break;
3990 case 0xf2: /* LDR2kr */
3991 __asm__("evaluxn_f2_LDR2kr:");
3992 {
3993 u8 a = u->rst.dat[u->rst.ptr - 1];
3994 u->rst.dat[u->rst.ptr] = mempeek8(u->ram.dat, u->ram.ptr + (s8)a);
3995 u->rst.dat[u->rst.ptr + 1] = mempeek8(u->ram.dat, u->ram.ptr + (s8)a + 1);
3996#ifndef NO_STACK_CHECKS
3997 if(__builtin_expect(u->rst.ptr < 1, 0)) {
3998 u->rst.error = 1;
3999 goto error;
4000 }
4001 if(__builtin_expect(u->rst.ptr > 253, 0)) {
4002 u->rst.error = 2;
4003 goto error;
4004 }
4005#endif
4006 u->rst.ptr += 2;
4007 }
4008 break;
4009 case 0xf3: /* STR2kr */
4010 __asm__("evaluxn_f3_STR2kr:");
4011 {
4012 u8 a = u->rst.dat[u->rst.ptr - 1];
4013 u16 b = (u->rst.dat[u->rst.ptr - 2] | (u->rst.dat[u->rst.ptr - 3] << 8));
4014 mempoke16(u->ram.dat, u->ram.ptr + (s8)a, b);
4015#ifndef NO_STACK_CHECKS
4016 if(__builtin_expect(u->rst.ptr < 3, 0)) {
4017 u->rst.error = 1;
4018 goto error;
4019 }
4020#endif
4021 }
4022 break;
4023 case 0xf4: /* LDA2kr */
4024 __asm__("evaluxn_f4_LDA2kr:");
4025 {
4026 u16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8));
4027 u->rst.dat[u->rst.ptr] = mempeek8(u->ram.dat, a);
4028 u->rst.dat[u->rst.ptr + 1] = mempeek8(u->ram.dat, a + 1);
4029#ifndef NO_STACK_CHECKS
4030 if(__builtin_expect(u->rst.ptr < 2, 0)) {
4031 u->rst.error = 1;
4032 goto error;
4033 }
4034 if(__builtin_expect(u->rst.ptr > 253, 0)) {
4035 u->rst.error = 2;
4036 goto error;
4037 }
4038#endif
4039 u->rst.ptr += 2;
4040 }
4041 break;
4042 case 0xf5: /* STA2kr */
4043 __asm__("evaluxn_f5_STA2kr:");
4044 {
4045 u16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8));
4046 u16 b = (u->rst.dat[u->rst.ptr - 3] | (u->rst.dat[u->rst.ptr - 4] << 8));
4047 mempoke16(u->ram.dat, a, b);
4048#ifndef NO_STACK_CHECKS
4049 if(__builtin_expect(u->rst.ptr < 4, 0)) {
4050 u->rst.error = 1;
4051 goto error;
4052 }
4053#endif
4054 }
4055 break;
4056 case 0xf6: /* DEI2kr */
4057 __asm__("evaluxn_f6_DEI2kr:");
4058 {
4059 u8 a = u->rst.dat[u->rst.ptr - 1];
4060 u->rst.dat[u->rst.ptr] = devpeek8(&u->dev[a >> 4], a);
4061 u->rst.dat[u->rst.ptr + 1] = devpeek8(&u->dev[a >> 4], a + 1);
4062#ifndef NO_STACK_CHECKS
4063 if(__builtin_expect(u->rst.ptr < 1, 0)) {
4064 u->rst.error = 1;
4065 goto error;
4066 }
4067 if(__builtin_expect(u->rst.ptr > 253, 0)) {
4068 u->rst.error = 2;
4069 goto error;
4070 }
4071#endif
4072 u->rst.ptr += 2;
4073 }
4074 break;
4075 case 0xf7: /* DEO2kr */
4076 __asm__("evaluxn_f7_DEO2kr:");
4077 {
4078 u8 a = u->rst.dat[u->rst.ptr - 1];
4079 u16 b = (u->rst.dat[u->rst.ptr - 2] | (u->rst.dat[u->rst.ptr - 3] << 8));
4080 devpoke16(&u->dev[a >> 4], a, b);
4081#ifndef NO_STACK_CHECKS
4082 if(__builtin_expect(u->rst.ptr < 3, 0)) {
4083 u->rst.error = 1;
4084 goto error;
4085 }
4086#endif
4087 }
4088 break;
4089 case 0xf8: /* ADD2kr */
4090 __asm__("evaluxn_f8_ADD2kr:");
4091 {
4092 u16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)), b = (u->rst.dat[u->rst.ptr - 3] | (u->rst.dat[u->rst.ptr - 4] << 8));
4093 u->rst.dat[u->rst.ptr] = (b + a) >> 8;
4094 u->rst.dat[u->rst.ptr + 1] = (b + a) & 0xff;
4095#ifndef NO_STACK_CHECKS
4096 if(__builtin_expect(u->rst.ptr < 4, 0)) {
4097 u->rst.error = 1;
4098 goto error;
4099 }
4100 if(__builtin_expect(u->rst.ptr > 253, 0)) {
4101 u->rst.error = 2;
4102 goto error;
4103 }
4104#endif
4105 u->rst.ptr += 2;
4106 }
4107 break;
4108 case 0xf9: /* SUB2kr */
4109 __asm__("evaluxn_f9_SUB2kr:");
4110 {
4111 u16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)), b = (u->rst.dat[u->rst.ptr - 3] | (u->rst.dat[u->rst.ptr - 4] << 8));
4112 u->rst.dat[u->rst.ptr] = (b - a) >> 8;
4113 u->rst.dat[u->rst.ptr + 1] = (b - a) & 0xff;
4114#ifndef NO_STACK_CHECKS
4115 if(__builtin_expect(u->rst.ptr < 4, 0)) {
4116 u->rst.error = 1;
4117 goto error;
4118 }
4119 if(__builtin_expect(u->rst.ptr > 253, 0)) {
4120 u->rst.error = 2;
4121 goto error;
4122 }
4123#endif
4124 u->rst.ptr += 2;
4125 }
4126 break;
4127 case 0xfa: /* MUL2kr */
4128 __asm__("evaluxn_fa_MUL2kr:");
4129 {
4130 u16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)), b = (u->rst.dat[u->rst.ptr - 3] | (u->rst.dat[u->rst.ptr - 4] << 8));
4131 u->rst.dat[u->rst.ptr] = (b * a) >> 8;
4132 u->rst.dat[u->rst.ptr + 1] = (b * a) & 0xff;
4133#ifndef NO_STACK_CHECKS
4134 if(__builtin_expect(u->rst.ptr < 4, 0)) {
4135 u->rst.error = 1;
4136 goto error;
4137 }
4138 if(__builtin_expect(u->rst.ptr > 253, 0)) {
4139 u->rst.error = 2;
4140 goto error;
4141 }
4142#endif
4143 u->rst.ptr += 2;
4144 }
4145 break;
4146 case 0xfb: /* DIV2kr */
4147 __asm__("evaluxn_fb_DIV2kr:");
4148 {
4149 u16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)), b = (u->rst.dat[u->rst.ptr - 3] | (u->rst.dat[u->rst.ptr - 4] << 8));
4150 if(a == 0) {
4151 u->rst.error = 3;
4152#ifndef NO_STACK_CHECKS
4153 goto error;
4154#endif
4155 a = 1;
4156 }
4157 u->rst.dat[u->rst.ptr] = (b / a) >> 8;
4158 u->rst.dat[u->rst.ptr + 1] = (b / a) & 0xff;
4159#ifndef NO_STACK_CHECKS
4160 if(__builtin_expect(u->rst.ptr < 4, 0)) {
4161 u->rst.error = 1;
4162 goto error;
4163 }
4164 if(__builtin_expect(u->rst.ptr > 253, 0)) {
4165 u->rst.error = 2;
4166 goto error;
4167 }
4168#endif
4169 u->rst.ptr += 2;
4170 }
4171 break;
4172 case 0xfc: /* AND2kr */
4173 __asm__("evaluxn_fc_AND2kr:");
4174 {
4175 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2], c = u->rst.dat[u->rst.ptr - 3], d = u->rst.dat[u->rst.ptr - 4];
4176 u->rst.dat[u->rst.ptr] = d & b;
4177 u->rst.dat[u->rst.ptr + 1] = c & a;
4178#ifndef NO_STACK_CHECKS
4179 if(__builtin_expect(u->rst.ptr < 4, 0)) {
4180 u->rst.error = 1;
4181 goto error;
4182 }
4183 if(__builtin_expect(u->rst.ptr > 253, 0)) {
4184 u->rst.error = 2;
4185 goto error;
4186 }
4187#endif
4188 u->rst.ptr += 2;
4189 }
4190 break;
4191 case 0xfd: /* ORA2kr */
4192 __asm__("evaluxn_fd_ORA2kr:");
4193 {
4194 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2], c = u->rst.dat[u->rst.ptr - 3], d = u->rst.dat[u->rst.ptr - 4];
4195 u->rst.dat[u->rst.ptr] = d | b;
4196 u->rst.dat[u->rst.ptr + 1] = c | a;
4197#ifndef NO_STACK_CHECKS
4198 if(__builtin_expect(u->rst.ptr < 4, 0)) {
4199 u->rst.error = 1;
4200 goto error;
4201 }
4202 if(__builtin_expect(u->rst.ptr > 253, 0)) {
4203 u->rst.error = 2;
4204 goto error;
4205 }
4206#endif
4207 u->rst.ptr += 2;
4208 }
4209 break;
4210 case 0xfe: /* EOR2kr */
4211 __asm__("evaluxn_fe_EOR2kr:");
4212 {
4213 u8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2], c = u->rst.dat[u->rst.ptr - 3], d = u->rst.dat[u->rst.ptr - 4];
4214 u->rst.dat[u->rst.ptr] = d ^ b;
4215 u->rst.dat[u->rst.ptr + 1] = c ^ a;
4216#ifndef NO_STACK_CHECKS
4217 if(__builtin_expect(u->rst.ptr < 4, 0)) {
4218 u->rst.error = 1;
4219 goto error;
4220 }
4221 if(__builtin_expect(u->rst.ptr > 253, 0)) {
4222 u->rst.error = 2;
4223 goto error;
4224 }
4225#endif
4226 u->rst.ptr += 2;
4227 }
4228 break;
4229 case 0xff: /* SFT2kr */
4230 __asm__("evaluxn_ff_SFT2kr:");
4231 {
4232 u8 a = u->rst.dat[u->rst.ptr - 1];
4233 u16 b = (u->rst.dat[u->rst.ptr - 2] | (u->rst.dat[u->rst.ptr - 3] << 8));
4234 u->rst.dat[u->rst.ptr] = (b >> (a & 0x0f) << ((a & 0xf0) >> 4)) >> 8;
4235 u->rst.dat[u->rst.ptr + 1] = (b >> (a & 0x0f) << ((a & 0xf0) >> 4)) & 0xff;
4236#ifndef NO_STACK_CHECKS
4237 if(__builtin_expect(u->rst.ptr < 3, 0)) {
4238 u->rst.error = 1;
4239 goto error;
4240 }
4241 if(__builtin_expect(u->rst.ptr > 253, 0)) {
4242 u->rst.error = 2;
4243 goto error;
4244 }
4245#endif
4246 u->rst.ptr += 2;
4247 }
4248 break;
4249#pragma GCC diagnostic pop
4250 }
4251 }
4252 return 1;
4253#ifndef NO_STACK_CHECKS
4254error:
4255 return 0;
4256#endif
4257}
4258
4259Device *
4260uxn_port(Uxn *u, u8 id, char *name, void (*talkfn)(Device *d, u8 b0, u8 w))
4261{
4262 Device *d = &u->dev[id];
4263 d->addr = id * 0x10;
4264 d->u = u;
4265 d->mem = u->ram.dat;
4266 d->talk = talkfn;
4267 (void)name;
4268 return d;
4269}
diff --git a/src/uxn.h b/src/uxn.h
deleted file mode 100644
index 5d68528..0000000
--- a/src/uxn.h
+++ /dev/null
@@ -1,57 +0,0 @@
1#ifndef UXNGBA_UXN_H
2#define UXNGBA_UXN_H
3
4#include <stdio.h>
5
6/*
7Copyright (c) 2021 Devine Lu Linvega
8
9Permission to use, copy, modify, and distribute this software for any
10purpose with or without fee is hereby granted, provided that the above
11copyright notice and this permission notice appear in all copies.
12
13THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14WITH REGARD TO THIS SOFTWARE.
15*/
16
17#define PAGE_PROGRAM 0x0100
18#define DEVPEEK16(o, x) { (o) = (d->dat[(x)] << 8) + d->dat[(x) + 1]; }
19#define DEVPOKE16(x, y) { d->dat[(x)] = (y) >> 8; d->dat[(x) + 1] = (y); }
20
21typedef struct {
22 u8 ptr, kptr, error;
23 u8 dat[256];
24} Stack;
25
26typedef struct {
27 u16 ptr;
28 u8 *dat;
29} Memory;
30
31typedef struct Device {
32 struct Uxn *u;
33 u8 addr, dat[16], *mem;
34 u16 vector;
35 void (*talk)(struct Device *d, u8, u8);
36} Device;
37
38typedef struct Uxn {
39 Stack wst, rst, *src, *dst;
40 Memory ram;
41 Device dev[16];
42} Uxn;
43
44struct Uxn;
45
46static inline void mempoke8(u8 *m, u16 a, u8 b) { m[a] = b; }
47static inline u8 mempeek8(u8 *m, u16 a) { return m[a]; }
48static inline void mempoke16(u8 *m, u16 a, u16 b) { mempoke8(m, a, b >> 8); mempoke8(m, a + 1, b); }
49static inline u16 mempeek16(u8 *m, u16 a) { return (mempeek8(m, a) << 8) + mempeek8(m, a + 1); }
50static inline void devpoke8(Device *d, u8 a, u8 b) { d->dat[a & 0xf] = b; d->talk(d, a & 0x0f, 1); }
51static inline u8 devpeek8(Device *d, u8 a) { d->talk(d, a & 0x0f, 0); return d->dat[a & 0xf]; }
52static inline void devpoke16(Device *d, u8 a, u16 b) { devpoke8(d, a, b >> 8); devpoke8(d, a + 1, b); }
53static inline u16 devpeek16(Device *d, u16 a) { return (devpeek8(d, a) << 8) + devpeek8(d, a + 1); }
54
55int uxn_eval(Uxn *u, u16 vec);
56Device *uxn_port(Uxn *u, u8 id, char *name, void (*talkfn)(Device *, u8, u8));
57#endif // UXNGBA_UXN_H
diff --git a/tools/bin2carr/Makefile b/tools/bin2carr/Makefile
deleted file mode 100644
index a9ff816..0000000
--- a/tools/bin2carr/Makefile
+++ /dev/null
@@ -1,47 +0,0 @@
1.POSIX:
2.SUFFIXES:
3
4# Source code location and files to watch for changes.
5SRC_DIR := src
6SRC_MAIN := $(SRC_DIR)/main.c
7WATCH_SRC := $(wildcard $(SRC_DIR)/*.c)
8WATCH_SRC += $(wildcard $(SRC_DIR)/*.h)
9
10# Output library names and executables.
11BIN_NAME := bin2carr
12BUILD_DIR := build
13BIN := $(BUILD_DIR)/$(BIN_NAME)
14
15# Compiler and linker configuration.
16CC := gcc
17CFLAGS := -Wall -Wextra -pedantic -std=c99 -DBIN_NAME=\"$(BIN_NAME)\"
18LDFLAGS := -lm
19LDLIBS :=
20RELEASE_CFLAGS := -DNDEBUG -O2
21DEBUG_CFLAGS := -DDEBUG -g
22
23.PHONY: static clean run
24
25# Setup debug/release builds.
26# make clean && make <target> DEBUG=0
27# make clean && make <target> DEBUG=1
28DEBUG ?= 0
29ifeq ($(DEBUG), 1)
30 CFLAGS += $(DEBUG_CFLAGS)
31else
32 CFLAGS += $(RELEASE_CFLAGS)
33endif
34
35static: $(BUILD_DIR) $(BIN)
36
37$(BIN): $(SRC_MAIN) $(WATCH_SRC)
38 $(CC) $(CFLAGS) $(LDFLAGS) -o $(BIN) $(SRC_MAIN) $(LDLIBS)
39
40$(BUILD_DIR):
41 mkdir -p $(BUILD_DIR)
42
43run: $(BIN)
44 exec $(BIN)
45
46clean:
47 rm -r $(BUILD_DIR)
diff --git a/tools/bin2carr/src/main.c b/tools/bin2carr/src/main.c
deleted file mode 100644
index 699db61..0000000
--- a/tools/bin2carr/src/main.c
+++ /dev/null
@@ -1,232 +0,0 @@
1#include <getopt.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5
6#include "shorthand.h"
7
8typedef enum {
9 ELEM_U8, ELEM_S8, ELEM_U16, ELEM_S16,
10 ELEM_U32, ELEM_S32, ELEM_U64, ELEM_S64,
11} ElemSize;
12
13void
14write_array(FILE *file_in, FILE *file_out, char *arr_name, ElemSize elem_size) {
15 char *arr_type;
16 size_t n_elem = 0;
17 switch (elem_size) {
18 case ELEM_U8:
19 arr_type = "u8";
20 n_elem = 8;
21 break;
22 case ELEM_S8:
23 arr_type = "s8";
24 n_elem = 8;
25 break;
26 case ELEM_U16:
27 arr_type = "u16";
28 n_elem = 8;
29 break;
30 case ELEM_S16:
31 arr_type = "s16";
32 n_elem = 8;
33 break;
34 case ELEM_U32:
35 arr_type = "u32";
36 n_elem = 4;
37 break;
38 case ELEM_S32:
39 arr_type = "s32";
40 n_elem = 4;
41 break;
42 case ELEM_U64:
43 arr_type = "u64";
44 n_elem = 4;
45 break;
46 case ELEM_S64:
47 arr_type = "s64";
48 n_elem = 4;
49 break;
50 default:
51 arr_type = "u8";
52 n_elem = 8;
53 break;
54 }
55 fprintf(file_out, "const %s %s[] = {\n", arr_type, arr_name);
56 size_t n_read = 0;
57 size_t counter = 0;
58 do {
59 if (counter == 0) {
60 fprintf(file_out, " ");
61 }
62 switch (elem_size) {
63 case ELEM_U8:
64 case ELEM_S8: {
65 u8 elem;
66 n_read = fread(&elem, sizeof(u8), 1, file_in);
67 fprintf(file_out, "0x%02x,", elem);
68 break;
69 }
70 case ELEM_U16:
71 case ELEM_S16: {
72 u16 elem;
73 n_read = fread(&elem, sizeof(u16), 1, file_in);
74 fprintf(file_out, "0x%04x,", elem);
75 break;
76 }
77 case ELEM_U32:
78 case ELEM_S32: {
79 u32 elem;
80 n_read = fread(&elem, sizeof(u32), 1, file_in);
81 fprintf(file_out, "0x%08x,", elem);
82 break;
83 }
84 case ELEM_U64:
85 case ELEM_S64: {
86 u64 elem;
87 n_read = fread(&elem, sizeof(u64), 1, file_in);
88 fprintf(file_out, "0x%016lx,", elem);
89 break;
90 }
91 }
92
93 if (counter == n_elem - 1) {
94 fprintf(file_out, "\n");
95 counter = 0;
96 } else {
97 fprintf(file_out, " ");
98 counter++;
99 }
100 } while(n_read != 0);
101 if (counter != 0) {
102 fseek(file_out, -1, SEEK_CUR);
103 fprintf(file_out, "\n");
104 }
105 fprintf(file_out, "};\n");
106}
107
108void
109print_usage(void) {
110 printf("Usage: %s [options] <filename>\n", BIN_NAME);
111 printf("\n");
112 printf("\t-e <u16>\tSize of array elements.\n");
113 printf("\t-n <arr_name>\tName of the output array.\n");
114 printf("\t-o <out_file.c>\tPath to the output file. If blank, stdout will be used.\n");
115 printf("\n");
116}
117
118int
119main(int argc, char *argv[]) {
120 // Initialize default parameters.
121 char *in_file_path = NULL;
122 char *out_file_path = NULL;
123 char arr_name[256] = {0};
124 ElemSize elem_size = ELEM_U8;
125
126 // Process options.
127 int option;
128 while ((option = getopt(argc, argv, "e:n:o:")) != -1) {
129 switch (option) {
130 case 'e': {
131 // Element size.
132 char *size = optarg;
133 if (strcmp(size, "u8") == 0) {
134 elem_size = ELEM_U8;
135 } else if (strcmp(size, "s8") == 0) {
136 elem_size = ELEM_S8;
137 } else if (strcmp(size, "u16") == 0) {
138 elem_size = ELEM_U16;
139 } else if (strcmp(size, "s16") == 0) {
140 elem_size = ELEM_S16;
141 } else if (strcmp(size, "u32") == 0) {
142 elem_size = ELEM_U32;
143 } else if (strcmp(size, "s32") == 0) {
144 elem_size = ELEM_S32;
145 } else if (strcmp(size, "u64") == 0) {
146 elem_size = ELEM_U64;
147 } else if (strcmp(size, "s64") == 0) {
148 elem_size = ELEM_S64;
149 }
150 } break;
151 case 'n': {
152 // Array name.
153 char *ptr = optarg;
154 size_t k = 0;
155 while(*ptr) {
156 switch (*ptr) {
157 case '.':
158 case '/':
159 case '-':
160 case '\\':
161 ptr++;
162 break;
163 default: {
164 arr_name[k++] = *ptr++;
165 } break;
166 }
167 }
168 } break;
169 case 'o': {
170 // Output file.
171 out_file_path = optarg;
172 } break;
173 default: {
174 print_usage();
175 return EXIT_FAILURE;
176 } break;
177 }
178 }
179
180 // Get the path to the file to be exported.
181 if (optind != argc - 1) {
182 fprintf(stderr, "%s: No input file given.\n", BIN_NAME);
183 print_usage();
184 return EXIT_FAILURE;
185 }
186 in_file_path = argv[optind];
187
188 // Check if there is a default array name.
189 if (arr_name[0] == '\0') {
190 char *ptr = in_file_path;
191 size_t k = 0;
192 while(*ptr) {
193 switch (*ptr) {
194 case '.':
195 case '/':
196 case '-':
197 case '\\':
198 ptr++;
199 break;
200 default: {
201 arr_name[k++] = *ptr++;
202 } break;
203 }
204 }
205 }
206
207 // Try to open input file.
208 FILE *file_in = fopen(in_file_path, "r");
209 if (file_in == NULL) {
210 fprintf(stderr, "%s: can't open input file: %s\n", BIN_NAME,
211 in_file_path);
212 return EXIT_FAILURE;
213 }
214
215 // Write output to file.
216 if (out_file_path == NULL) {
217 write_array(file_in, stdout, arr_name, elem_size);
218 } else {
219 FILE *file_out = fopen(out_file_path, "w");
220 if (!file_out) {
221 fprintf(stderr, "%s: can't open output file: %s\n", BIN_NAME, out_file_path);
222 fclose(file_in);
223 return EXIT_FAILURE;
224 }
225 write_array(file_in, file_out, arr_name, elem_size);
226 fclose(file_out);
227 }
228
229 // Cleanup.
230 fclose(file_in);
231 return EXIT_SUCCESS;
232}
diff --git a/tools/bin2carr/src/shorthand.h b/tools/bin2carr/src/shorthand.h
deleted file mode 100644
index 9c2e2f0..0000000
--- a/tools/bin2carr/src/shorthand.h
+++ /dev/null
@@ -1,35 +0,0 @@
1#ifndef MIC_SHORTHAND_H
2#define MIC_SHORTHAND_H
3
4#include <assert.h>
5#include <stdbool.h>
6#include <stddef.h>
7#include <stdint.h>
8
9//
10// This simple header just typedefs the basic C define types to a shorter name,
11// loads the quality of life bool macro for _Bool and defines shorthand macros
12// for byte sizes. We need that the targeted architecture uses the floating
13// point representation as described on the IEEE-754 standard.
14//
15
16_Static_assert(sizeof(double) == 8, "no support for IEEE-754");
17_Static_assert(sizeof(float) == 4, "no support for IEEE-754");
18
19typedef uint8_t u8;
20typedef uint16_t u16;
21typedef uint32_t u32;
22typedef uint64_t u64;
23typedef int8_t s8;
24typedef int16_t s16;
25typedef int32_t s32;
26typedef int64_t s64;
27typedef float f32;
28typedef double f64;
29
30#define KB(N) ((u64)(N) * 1024)
31#define MB(N) ((u64)KB(N) * 1024)
32#define GB(N) ((u64)MB(N) * 1024)
33#define TB(N) ((u64)GB(N) * 1024)
34
35#endif // MIC_SHORTHAND_H