├── .gitignore ├── LICENSE.txt ├── Makefile ├── README.md ├── index.html ├── rom2html ├── rom2url ├── roms ├── animation.rom ├── asma.rom ├── audio.channels.rom ├── audio.rom ├── automata.rom ├── bifurcan.rom ├── console.lib.rom ├── console.rom ├── controller.buttons.rom ├── controller.keys.rom ├── darena.rom ├── datetime.rom ├── drum-rack.rom ├── file.load.rom ├── file.rom ├── file.save.rom ├── hover.rom ├── label.rom ├── life.rom ├── mouse.rom ├── musictracker.rom ├── neralie.rom ├── piano.rom ├── picture.rom ├── polycat.rom ├── proportional-font.rom ├── screen.rom ├── shapes.rom ├── theme.rom └── wallpaper.rom ├── src ├── devices │ ├── apu.c │ ├── apu.h │ ├── mpu.c │ ├── mpu.h │ ├── ppu.c │ └── ppu.h ├── uxn-fast.c ├── uxn.h └── webuxn.c └── webuxn.js /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) Bruno Garcia 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 9 | FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | PERFORMANCE OF THIS SOFTWARE. 14 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Build-time dependencies 2 | CC = emcc 3 | WASM_OPT = "$(EMSDK)/upstream/bin/wasm-opt" 4 | ROLLUP = npx rollup 5 | TERSER = npx terser 6 | 7 | BUILD_DIR ?= ./build 8 | SRC_DIRS ?= ./src 9 | 10 | RELEASE=1 11 | ifeq ($(RELEASE),1) 12 | OPT_FLAGS = -O2 13 | else 14 | OPT_FLAGS = -g4 --source-map-base "http://0.0.0.0:7001/build/" # -s DEMANGLE_SUPPORT=1 15 | endif 16 | LDFLAGS = $(OPT_FLAGS) --no-entry -s WASM=1 -s ERROR_ON_UNDEFINED_SYMBOLS=0 17 | CFLAGS ?= $(INC_FLAGS) -MMD -MP $(OPT_FLAGS) -W -Wall -Wextra 18 | 19 | SRCS := $(shell find $(SRC_DIRS) -name "*.c") 20 | OBJS := $(SRCS:%=$(BUILD_DIR)/%.o) 21 | DEPS := $(OBJS:.o=.d) 22 | 23 | INC_DIRS := $(shell find $(SRC_DIRS) -type d) 24 | INC_FLAGS := $(addprefix -I,$(INC_DIRS)) 25 | 26 | all: $(BUILD_DIR)/webuxn.wasm $(BUILD_DIR)/webuxn.min.js 27 | 28 | $(BUILD_DIR)/webuxn.wasm: $(OBJS) 29 | $(CC) $(OBJS) -o $@ $(LDFLAGS) 30 | ifeq ($(RELEASE),1) 31 | $(WASM_OPT) -O4 $@ -o $@.opt 32 | mv $@.opt $@ 33 | endif 34 | 35 | $(BUILD_DIR)/%.wat: $(BUILD_DIR)/%.wasm 36 | $(WASM_DIS) $< -o $@ 37 | 38 | $(BUILD_DIR)/%.c.o: %.c 39 | mkdir -p $(dir $@) 40 | $(CC) $(CFLAGS) -c $< -o $@ 41 | 42 | $(BUILD_DIR)/%.min.js: %.js 43 | $(ROLLUP) $< --format iife --output.name webuxn | $(TERSER) --compress --mangle > $@ 44 | 45 | .PHONY: clean 46 | 47 | clean: 48 | $(RM) -r $(BUILD_DIR) 49 | 50 | -include $(DEPS) 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # webuxn 2 | 3 | A light-weight port of the [uxn virtual machine](https://100r.co/site/uxn.html) to the web via WebAssembly. 4 | 5 | ## Demos 6 | 7 | - [life.rom](https://aduros.com/webuxn/?rom=roms/life.rom) 8 | - [darena.rom](https://aduros.com/webuxn/?rom=roms/darena.rom) 9 | - [animation.rom](https://aduros.com/webuxn/?rom=roms/animation.rom) 10 | - [musictracker.rom](https://aduros.com/webuxn/?rom=roms/musictracker.rom) 11 | - [Bring Your Own Rom](https://aduros.com/webuxn/) 12 | 13 | ## Hotkeys 14 | 15 | - F2: Save state 16 | - F4: Load state 17 | - F5: Reboot 18 | - F9: Take screenshot 19 | - F11: Toggle fullscreen 20 | 21 | ## rom2html 22 | 23 | `rom2html` bakes a rom and VM into a fully self-contained html that can be easily distributed. 24 | 25 | ``` 26 | make 27 | ./rom2html roms/life.rom > life.html 28 | ``` 29 | 30 | ## rom2url 31 | 32 | `rom2url` embeds a rom into a playable URL. The rom is never uploaded to a server, but embedded into 33 | the URL string itself. This is one way you can share (or pirate?) roms even if you don't have a 34 | website. If your rom is small enough, it can even fit into a QR code and printed onto paper. 35 | 36 | ``` 37 | ./rom2url roms/animation.rom | qrencode -o qrcode.png 38 | ``` 39 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | WebUxn 7 | 39 | 40 | 41 | 42 | 43 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /rom2html: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // 3 | // Packages a rom into a self-contained html file 4 | 5 | const fs = require("fs"); 6 | const path = require("path"); 7 | 8 | if (process.argv.length < 3) { 9 | console.error("Usage: rom2html ROM"); 10 | process.exit(1); 11 | } 12 | 13 | const js = fs.readFileSync("build/webuxn.min.js"); 14 | const wasmBuffer = fs.readFileSync("build/webuxn.wasm"); 15 | const romBuffer = fs.readFileSync(process.argv[2]); 16 | 17 | // Based on https://www.npmjs.com/package/z85 18 | function encodeZ85 (buffer) { 19 | var extra = buffer.length % 4; 20 | if (extra > 0) { 21 | buffer = Buffer.concat([buffer, Buffer.alloc(4-extra)]); 22 | } 23 | 24 | var encoder = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-:+=^!/*?&<>()[]{}@%$#".split(""); 25 | 26 | var str = "", 27 | byte_nbr = 0, 28 | size = buffer.length, 29 | value = 0; 30 | while (byte_nbr < size) { 31 | var characterCode = buffer[byte_nbr++]; 32 | value = (value * 256) + characterCode; 33 | if ((byte_nbr % 4) == 0) { 34 | var divisor = 85 * 85 * 85 * 85; 35 | while (divisor >= 1) { 36 | var idx = Math.floor(value / divisor) % 85; 37 | str += encoder[idx]; 38 | divisor /= 85; 39 | } 40 | value = 0 41 | } 42 | } 43 | 44 | return str; 45 | } 46 | 47 | function encodeJs (buffer) { 48 | return "decodeZ85(\""+encodeZ85(buffer)+"\", "+buffer.length+")"; 49 | } 50 | 51 | console.log(` 52 | 53 | 54 | 55 | 56 | ${path.basename(process.argv[2])} 57 | 78 | 79 | 80 | 81 | 120 | 121 | 122 | `); 123 | -------------------------------------------------------------------------------- /rom2url: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // 3 | // Generates a link from a rom file 4 | 5 | const fs = require("fs"); 6 | const path = require("path"); 7 | 8 | if (process.argv.length < 3) { 9 | console.error("Usage: rom2url ROM"); 10 | process.exit(1); 11 | } 12 | 13 | const romBuffer = fs.readFileSync(process.argv[2]); 14 | 15 | // Based on https://www.npmjs.com/package/z85 16 | function encodeZ85 (buffer) { 17 | var extra = buffer.length % 4; 18 | if (extra > 0) { 19 | buffer = Buffer.concat([buffer, Buffer.alloc(4-extra)]); 20 | } 21 | 22 | var encoder = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-:+=^!/*?&<>()[]{}@%$#".split(""); 23 | 24 | var str = "", 25 | byte_nbr = 0, 26 | size = buffer.length, 27 | value = 0; 28 | while (byte_nbr < size) { 29 | var characterCode = buffer[byte_nbr++]; 30 | value = (value * 256) + characterCode; 31 | if ((byte_nbr % 4) == 0) { 32 | var divisor = 85 * 85 * 85 * 85; 33 | while (divisor >= 1) { 34 | var idx = Math.floor(value / divisor) % 85; 35 | str += encoder[idx]; 36 | divisor /= 85; 37 | } 38 | value = 0 39 | } 40 | } 41 | 42 | // Prevent % escape sequences 43 | str = str.replace(/%/g, "%25"); 44 | 45 | return str; 46 | } 47 | 48 | console.log("https://aduros.com/webuxn/?raw#" + encodeZ85(romBuffer)); 49 | -------------------------------------------------------------------------------- /roms/animation.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aduros/webuxn/1c796b4cb014f5669107c18917dd51df71e39a45/roms/animation.rom -------------------------------------------------------------------------------- /roms/asma.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aduros/webuxn/1c796b4cb014f5669107c18917dd51df71e39a45/roms/asma.rom -------------------------------------------------------------------------------- /roms/audio.channels.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aduros/webuxn/1c796b4cb014f5669107c18917dd51df71e39a45/roms/audio.channels.rom -------------------------------------------------------------------------------- /roms/audio.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aduros/webuxn/1c796b4cb014f5669107c18917dd51df71e39a45/roms/audio.rom -------------------------------------------------------------------------------- /roms/automata.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aduros/webuxn/1c796b4cb014f5669107c18917dd51df71e39a45/roms/automata.rom -------------------------------------------------------------------------------- /roms/bifurcan.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aduros/webuxn/1c796b4cb014f5669107c18917dd51df71e39a45/roms/bifurcan.rom -------------------------------------------------------------------------------- /roms/console.lib.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aduros/webuxn/1c796b4cb014f5669107c18917dd51df71e39a45/roms/console.lib.rom -------------------------------------------------------------------------------- /roms/console.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aduros/webuxn/1c796b4cb014f5669107c18917dd51df71e39a45/roms/console.rom -------------------------------------------------------------------------------- /roms/controller.buttons.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aduros/webuxn/1c796b4cb014f5669107c18917dd51df71e39a45/roms/controller.buttons.rom -------------------------------------------------------------------------------- /roms/controller.keys.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aduros/webuxn/1c796b4cb014f5669107c18917dd51df71e39a45/roms/controller.keys.rom -------------------------------------------------------------------------------- /roms/darena.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aduros/webuxn/1c796b4cb014f5669107c18917dd51df71e39a45/roms/darena.rom -------------------------------------------------------------------------------- /roms/datetime.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aduros/webuxn/1c796b4cb014f5669107c18917dd51df71e39a45/roms/datetime.rom -------------------------------------------------------------------------------- /roms/drum-rack.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aduros/webuxn/1c796b4cb014f5669107c18917dd51df71e39a45/roms/drum-rack.rom -------------------------------------------------------------------------------- /roms/file.load.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aduros/webuxn/1c796b4cb014f5669107c18917dd51df71e39a45/roms/file.load.rom -------------------------------------------------------------------------------- /roms/file.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aduros/webuxn/1c796b4cb014f5669107c18917dd51df71e39a45/roms/file.rom -------------------------------------------------------------------------------- /roms/file.save.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aduros/webuxn/1c796b4cb014f5669107c18917dd51df71e39a45/roms/file.save.rom -------------------------------------------------------------------------------- /roms/hover.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aduros/webuxn/1c796b4cb014f5669107c18917dd51df71e39a45/roms/hover.rom -------------------------------------------------------------------------------- /roms/label.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aduros/webuxn/1c796b4cb014f5669107c18917dd51df71e39a45/roms/label.rom -------------------------------------------------------------------------------- /roms/life.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aduros/webuxn/1c796b4cb014f5669107c18917dd51df71e39a45/roms/life.rom -------------------------------------------------------------------------------- /roms/mouse.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aduros/webuxn/1c796b4cb014f5669107c18917dd51df71e39a45/roms/mouse.rom -------------------------------------------------------------------------------- /roms/musictracker.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aduros/webuxn/1c796b4cb014f5669107c18917dd51df71e39a45/roms/musictracker.rom -------------------------------------------------------------------------------- /roms/neralie.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aduros/webuxn/1c796b4cb014f5669107c18917dd51df71e39a45/roms/neralie.rom -------------------------------------------------------------------------------- /roms/piano.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aduros/webuxn/1c796b4cb014f5669107c18917dd51df71e39a45/roms/piano.rom -------------------------------------------------------------------------------- /roms/picture.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aduros/webuxn/1c796b4cb014f5669107c18917dd51df71e39a45/roms/picture.rom -------------------------------------------------------------------------------- /roms/polycat.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aduros/webuxn/1c796b4cb014f5669107c18917dd51df71e39a45/roms/polycat.rom -------------------------------------------------------------------------------- /roms/proportional-font.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aduros/webuxn/1c796b4cb014f5669107c18917dd51df71e39a45/roms/proportional-font.rom -------------------------------------------------------------------------------- /roms/screen.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aduros/webuxn/1c796b4cb014f5669107c18917dd51df71e39a45/roms/screen.rom -------------------------------------------------------------------------------- /roms/shapes.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aduros/webuxn/1c796b4cb014f5669107c18917dd51df71e39a45/roms/shapes.rom -------------------------------------------------------------------------------- /roms/theme.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aduros/webuxn/1c796b4cb014f5669107c18917dd51df71e39a45/roms/theme.rom -------------------------------------------------------------------------------- /roms/wallpaper.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aduros/webuxn/1c796b4cb014f5669107c18917dd51df71e39a45/roms/wallpaper.rom -------------------------------------------------------------------------------- /src/devices/apu.c: -------------------------------------------------------------------------------- 1 | #include "../uxn.h" 2 | #include "apu.h" 3 | 4 | /* 5 | Copyright (c) 2021 Devine Lu Linvega 6 | Copyright (c) 2021 Andrew Alderwick 7 | 8 | Permission to use, copy, modify, and distribute this software for any 9 | purpose with or without fee is hereby granted, provided that the above 10 | copyright notice and this permission notice appear in all copies. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 | WITH REGARD TO THIS SOFTWARE. 14 | */ 15 | 16 | #define NOTE_PERIOD (SAMPLE_FREQUENCY * 0x4000 / 11025) 17 | #define ADSR_STEP (SAMPLE_FREQUENCY / 0xf) 18 | 19 | /* clang-format off */ 20 | 21 | static Uint32 advances[12] = { 22 | 0x80000, 0x879c8, 0x8facd, 0x9837f, 0xa1451, 0xaadc1, 23 | 0xb504f, 0xbfc88, 0xcb2ff, 0xd7450, 0xe411f, 0xf1a1c 24 | }; 25 | 26 | /* clang-format on */ 27 | 28 | static Sint32 29 | envelope(Apu *c, Uint32 age) 30 | { 31 | if(!c->r) return 0x0888; 32 | if(age < c->a) return 0x0888 * age / c->a; 33 | if(age < c->d) return 0x0444 * (2 * c->d - c->a - age) / (c->d - c->a); 34 | if(age < c->s) return 0x0444; 35 | if(age < c->r) return 0x0444 * (c->r - age) / (c->r - c->s); 36 | c->advance = 0; 37 | return 0x0000; 38 | } 39 | 40 | void 41 | apu_render(Apu *c, Sint16 *sample, Sint16 *end) 42 | { 43 | Sint32 s; 44 | if(!c->advance || !c->period) return; 45 | while(sample < end) { 46 | c->count += c->advance; 47 | c->i += c->count / c->period; 48 | c->count %= c->period; 49 | if(c->i >= c->len) { 50 | if(!c->repeat) { 51 | c->advance = 0; 52 | return; 53 | } 54 | c->i %= c->len; 55 | } 56 | s = (Sint8)(c->addr[c->i] + 0x80) * envelope(c, c->age++); 57 | *sample++ += s * c->volume[0] / 0x180; 58 | *sample++ += s * c->volume[1] / 0x180; 59 | } 60 | } 61 | 62 | void 63 | apu_start(Apu *c, Uint16 adsr, Uint8 pitch) 64 | { 65 | if(pitch < 108 && c->len) 66 | c->advance = advances[pitch % 12] >> (8 - pitch / 12); 67 | else { 68 | c->advance = 0; 69 | return; 70 | } 71 | c->a = ADSR_STEP * (adsr >> 12); 72 | c->d = ADSR_STEP * (adsr >> 8 & 0xf) + c->a; 73 | c->s = ADSR_STEP * (adsr >> 4 & 0xf) + c->d; 74 | c->r = ADSR_STEP * (adsr >> 0 & 0xf) + c->s; 75 | c->age = 0; 76 | c->i = 0; 77 | if(c->len <= 0x100) /* single cycle mode */ 78 | c->period = NOTE_PERIOD * 337 / 2 / c->len; 79 | else /* sample repeat mode */ 80 | c->period = NOTE_PERIOD; 81 | } 82 | 83 | Uint8 84 | apu_get_vu(Apu *c) 85 | { 86 | size_t i; 87 | Sint32 sum[2]; 88 | if(!c->advance || !c->period) return 0; 89 | for(i = 0; i < 2; ++i) { 90 | sum[i] = envelope(c, c->age) * c->volume[i] / 0x800; 91 | if(sum[i] > 0xf) sum[i] = 0xf; 92 | } 93 | return (sum[0] << 4) | sum[1]; 94 | } 95 | -------------------------------------------------------------------------------- /src/devices/apu.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2021 Devine Lu Linvega 3 | Copyright (c) 2021 Andrew Alderwick 4 | 5 | Permission to use, copy, modify, and distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | WITH REGARD TO THIS SOFTWARE. 11 | */ 12 | 13 | typedef unsigned int Uint32; 14 | typedef signed int Sint32; 15 | 16 | #define SAMPLE_FREQUENCY 44100 17 | #define POLYPHONY 4 18 | 19 | typedef struct { 20 | Uint8 *addr; 21 | Uint32 count, advance, period, age, a, d, s, r; 22 | Uint16 i, len; 23 | Sint8 volume[2]; 24 | Uint8 pitch, repeat; 25 | } Apu; 26 | 27 | void apu_render(Apu *c, Sint16 *sample, Sint16 *end); 28 | void apu_start(Apu *c, Uint16 adsr, Uint8 pitch); 29 | Uint8 apu_get_vu(Apu *c); 30 | -------------------------------------------------------------------------------- /src/devices/mpu.c: -------------------------------------------------------------------------------- 1 | #include "mpu.h" 2 | 3 | /* 4 | Copyright (c) 2021 Devine Lu Linvega 5 | Copyright (c) 2021 Andrew Alderwick 6 | 7 | Permission to use, copy, modify, and distribute this software for any 8 | purpose with or without fee is hereby granted, provided that the above 9 | copyright notice and this permission notice appear in all copies. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 | WITH REGARD TO THIS SOFTWARE. 13 | */ 14 | 15 | int 16 | initmpu(Mpu *m, Uint8 device) 17 | { 18 | /* 19 | int i; 20 | Pm_Initialize(); 21 | for(i = 0; i < Pm_CountDevices(); ++i) 22 | printf("Device #%d -> %s%s\n", 23 | i, 24 | Pm_GetDeviceInfo(i)->name, 25 | i == device ? "[x]" : "[ ]"); 26 | Pm_OpenInput(&m->midi, device, NULL, 128, 0, NULL); 27 | m->queue = 0; 28 | m->error = pmNoError; 29 | */ 30 | (void)m; 31 | (void)device; 32 | return 1; 33 | } 34 | 35 | void 36 | listenmpu(Mpu *m) 37 | { 38 | /* 39 | const int result = Pm_Read(m->midi, m->events, 32); 40 | if(result < 0) { 41 | m->error = (PmError)result; 42 | m->queue = 0; 43 | return; 44 | } 45 | m->queue = result; 46 | */ 47 | (void)m; 48 | } 49 | -------------------------------------------------------------------------------- /src/devices/mpu.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | /* #include */ 4 | 5 | /* 6 | Copyright (c) 2021 Devine Lu Linvega 7 | Copyright (c) 2021 Andrew Alderwick 8 | 9 | Permission to use, copy, modify, and distribute this software for any 10 | purpose with or without fee is hereby granted, provided that the above 11 | copyright notice and this permission notice appear in all copies. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14 | WITH REGARD TO THIS SOFTWARE. 15 | */ 16 | 17 | typedef unsigned char Uint8; 18 | 19 | typedef struct { 20 | int message; 21 | } PmEvent; 22 | 23 | typedef struct { 24 | Uint8 queue; 25 | PmEvent events[32]; 26 | /* 27 | PmStream *midi; 28 | PmError error; 29 | */ 30 | } Mpu; 31 | 32 | int initmpu(Mpu *m, Uint8 device); 33 | void listenmpu(Mpu *m); 34 | -------------------------------------------------------------------------------- /src/devices/ppu.c: -------------------------------------------------------------------------------- 1 | #include "ppu.h" 2 | 3 | /* 4 | Copyright (c) 2021 Devine Lu Linvega 5 | Copyright (c) 2021 Andrew Alderwick 6 | 7 | Permission to use, copy, modify, and distribute this software for any 8 | purpose with or without fee is hereby granted, provided that the above 9 | copyright notice and this permission notice appear in all copies. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 | WITH REGARD TO THIS SOFTWARE. 13 | */ 14 | 15 | static Uint8 font[][8] = { 16 | {0x00, 0x7c, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7c}, 17 | {0x00, 0x30, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, 18 | {0x00, 0x7c, 0x82, 0x02, 0x7c, 0x80, 0x80, 0xfe}, 19 | {0x00, 0x7c, 0x82, 0x02, 0x1c, 0x02, 0x82, 0x7c}, 20 | {0x00, 0x0c, 0x14, 0x24, 0x44, 0x84, 0xfe, 0x04}, 21 | {0x00, 0xfe, 0x80, 0x80, 0x7c, 0x02, 0x82, 0x7c}, 22 | {0x00, 0x7c, 0x82, 0x80, 0xfc, 0x82, 0x82, 0x7c}, 23 | {0x00, 0x7c, 0x82, 0x02, 0x1e, 0x02, 0x02, 0x02}, 24 | {0x00, 0x7c, 0x82, 0x82, 0x7c, 0x82, 0x82, 0x7c}, 25 | {0x00, 0x7c, 0x82, 0x82, 0x7e, 0x02, 0x82, 0x7c}, 26 | {0x00, 0x7c, 0x82, 0x02, 0x7e, 0x82, 0x82, 0x7e}, 27 | {0x00, 0xfc, 0x82, 0x82, 0xfc, 0x82, 0x82, 0xfc}, 28 | {0x00, 0x7c, 0x82, 0x80, 0x80, 0x80, 0x82, 0x7c}, 29 | {0x00, 0xfc, 0x82, 0x82, 0x82, 0x82, 0x82, 0xfc}, 30 | {0x00, 0x7c, 0x82, 0x80, 0xf0, 0x80, 0x82, 0x7c}, 31 | {0x00, 0x7c, 0x82, 0x80, 0xf0, 0x80, 0x80, 0x80}}; 32 | 33 | Uint8 34 | readpixel(Uint8 *sprite, Uint8 h, Uint8 v) 35 | { 36 | Uint8 ch1 = ((sprite[v] >> h) & 0x1); 37 | Uint8 ch2 = (((sprite[v + 8] >> h) & 0x1) << 1); 38 | return ch1 + ch2; 39 | } 40 | 41 | void 42 | clear(Ppu *p) 43 | { 44 | int i, sz = p->height * p->width; 45 | for(i = 0; i < sz; ++i) { 46 | p->fg.pixels[i] = p->fg.colors[0]; 47 | p->bg.pixels[i] = p->bg.colors[0]; 48 | } 49 | } 50 | 51 | void 52 | putcolors(Ppu *p, Uint8 *addr) 53 | { 54 | int i; 55 | for(i = 0; i < 4; ++i) { 56 | Uint8 57 | r = (*(addr + i / 2) >> (!(i % 2) << 2)) & 0x0f, 58 | g = (*(addr + 2 + i / 2) >> (!(i % 2) << 2)) & 0x0f, 59 | b = (*(addr + 4 + i / 2) >> (!(i % 2) << 2)) & 0x0f; 60 | p->bg.colors[i] = 0xff000000 | (r << 20) | (r << 16) | (g << 12) | (g << 8) | (b << 4) | b; 61 | p->fg.colors[i] = 0xff000000 | (r << 20) | (r << 16) | (g << 12) | (g << 8) | (b << 4) | b; 62 | } 63 | p->fg.colors[0] = 0; 64 | clear(p); 65 | } 66 | 67 | void 68 | putpixel(Ppu *p, Layer *layer, Uint16 x, Uint16 y, Uint8 color) 69 | { 70 | if(x >= p->width || y >= p->height) 71 | return; 72 | layer->pixels[y * p->width + x] = layer->colors[color]; 73 | } 74 | 75 | void 76 | puticn(Ppu *p, Layer *layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy) 77 | { 78 | Uint16 v, h; 79 | for(v = 0; v < 8; v++) 80 | for(h = 0; h < 8; h++) { 81 | Uint8 ch1 = ((sprite[v] >> (7 - h)) & 0x1); 82 | if(ch1 == 1 || (color != 0x05 && color != 0x0a && color != 0x0f)) 83 | putpixel(p, 84 | layer, 85 | x + (flipx ? 7 - h : h), 86 | y + (flipy ? 7 - v : v), 87 | ch1 ? color % 4 : color / 4); 88 | } 89 | } 90 | 91 | void 92 | putchr(Ppu *p, Layer *layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy) 93 | { 94 | Uint16 v, h; 95 | for(v = 0; v < 8; v++) 96 | for(h = 0; h < 8; h++) { 97 | Uint8 ch1 = ((sprite[v] >> (7 - h)) & 0x1) * color; 98 | Uint8 ch2 = ((sprite[v + 8] >> (7 - h)) & 0x1) * color; 99 | putpixel(p, 100 | layer, 101 | x + (flipx ? 7 - h : h), 102 | y + (flipy ? 7 - v : v), 103 | (((ch1 + ch2 * 2) + color / 4) & 0x3)); 104 | } 105 | } 106 | 107 | /* output */ 108 | 109 | void 110 | inspect(Ppu *p, Uint8 *stack, Uint8 ptr) 111 | { 112 | Uint8 i, x, y, b; 113 | for(i = 0; i < 0x20; ++i) { /* memory */ 114 | x = ((i % 8) * 3 + 1) * 8, y = (i / 8 + 1) * 8, b = stack[i]; 115 | puticn(p, &p->bg, x, y, font[(b >> 4) & 0xf], 1 + (ptr == i) * 0x7, 0, 0); 116 | puticn(p, &p->bg, x + 8, y, font[b & 0xf], 1 + (ptr == i) * 0x7, 0, 0); 117 | } 118 | for(x = 0; x < 0x20; ++x) { 119 | putpixel(p, &p->bg, x, p->height / 2, 2); 120 | putpixel(p, &p->bg, p->width - x, p->height / 2, 2); 121 | putpixel(p, &p->bg, p->width / 2, p->height - x, 2); 122 | putpixel(p, &p->bg, p->width / 2, x, 2); 123 | putpixel(p, &p->bg, p->width / 2 - 16 + x, p->height / 2, 2); 124 | putpixel(p, &p->bg, p->width / 2, p->height / 2 - 16 + x, 2); 125 | } 126 | } 127 | 128 | int 129 | initppu(Ppu *p, Uint8 hor, Uint8 ver) 130 | { 131 | /* p->hor = hor; */ 132 | /* p->ver = ver; */ 133 | /* p->width = 8 * p->hor; */ 134 | /* p->height = 8 * p->ver; */ 135 | /* if(!(p->bg.pixels = malloc(p->width * p->height * sizeof(Uint32)))) */ 136 | /* return 0; */ 137 | /* if(!(p->fg.pixels = malloc(p->width * p->height * sizeof(Uint32)))) */ 138 | /* return 0; */ 139 | /* clear(p); */ 140 | return 1; 141 | } 142 | -------------------------------------------------------------------------------- /src/devices/ppu.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* 5 | Copyright (c) 2021 Devine Lu Linvega 6 | Copyright (c) 2021 Andrew Alderwick 7 | 8 | Permission to use, copy, modify, and distribute this software for any 9 | purpose with or without fee is hereby granted, provided that the above 10 | copyright notice and this permission notice appear in all copies. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 | WITH REGARD TO THIS SOFTWARE. 14 | */ 15 | 16 | typedef unsigned char Uint8; 17 | typedef unsigned short Uint16; 18 | typedef unsigned int Uint32; 19 | 20 | #define WIDTH 384 21 | #define HEIGHT 256 22 | 23 | typedef struct Layer { 24 | Uint32 pixels[WIDTH*HEIGHT], colors[4]; 25 | } Layer; 26 | 27 | typedef struct Ppu { 28 | Uint16 hor, ver, width, height; 29 | Layer fg, bg; 30 | } Ppu; 31 | 32 | int initppu(Ppu *p, Uint8 hor, Uint8 ver); 33 | void putcolors(Ppu *p, Uint8 *addr); 34 | void putpixel(Ppu *p, Layer *layer, Uint16 x, Uint16 y, Uint8 color); 35 | void puticn(Ppu *p, Layer *layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy); 36 | void putchr(Ppu *p, Layer *layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy); 37 | void inspect(Ppu *p, Uint8 *stack, Uint8 ptr); 38 | -------------------------------------------------------------------------------- /src/uxn-fast.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "uxn.h" 3 | 4 | // webuxn: disable stuff for emscripten 5 | #define __asm__ 6 | #define printf 7 | 8 | /* 9 | Copyright (u) 2021 Devine Lu Linvega 10 | Copyright (u) 2021 Andrew Alderwick 11 | 12 | Permission to use, copy, modify, and distribute this software for any 13 | purpose with or without fee is hereby granted, provided that the above 14 | copyright notice and this permission notice appear in all copies. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 17 | WITH REGARD TO THIS SOFTWARE. 18 | */ 19 | 20 | /* 21 | ^ 22 | /!\ THIS FILE IS AUTOMATICALLY GENERATED 23 | --- 24 | 25 | Its contents can get overwritten with the processed contents of src/uxn.c. 26 | See etc/mkuxn-fast.moon for instructions. 27 | 28 | */ 29 | 30 | #pragma mark - Operations 31 | 32 | /* clang-format off */ 33 | void mempoke8(Uint8 *m, Uint16 a, Uint8 b) { m[a] = b; } 34 | Uint8 mempeek8(Uint8 *m, Uint16 a) { return m[a]; } 35 | void devpoke8(Device *d, Uint8 a, Uint8 b) { d->dat[a & 0xf] = b; d->talk(d, a & 0x0f, 1); } 36 | Uint8 devpeek8(Device *d, Uint8 a) { d->talk(d, a & 0x0f, 0); return d->dat[a & 0xf]; } 37 | void mempoke16(Uint8 *m, Uint16 a, Uint16 b) { mempoke8(m, a, b >> 8); mempoke8(m, a + 1, b); } 38 | Uint16 mempeek16(Uint8 *m, Uint16 a) { return (mempeek8(m, a) << 8) + mempeek8(m, a + 1); } 39 | void devpoke16(Device *d, Uint8 a, Uint16 b) { devpoke8(d, a, b >> 8); devpoke8(d, a + 1, b); } 40 | Uint16 devpeek16(Device *d, Uint16 a) { return (devpeek8(d, a) << 8) + devpeek8(d, a + 1); } 41 | 42 | #ifndef NO_STACK_CHECKS 43 | static const char *errors[] = {"underflow", "overflow", "division by zero"}; 44 | 45 | int 46 | haltuxn(Uxn *u, Uint8 error, char *name, int id) 47 | { 48 | printf("Halted: %s %s#%04x, at 0x%04x\n", name, errors[error - 1], id, u->ram.ptr); 49 | u->ram.ptr = 0; 50 | return 0; 51 | } 52 | #endif 53 | 54 | /* clang-format on */ 55 | 56 | #pragma mark - Core 57 | 58 | int 59 | evaluxn(Uxn *u, Uint16 vec) 60 | { 61 | Uint8 instr; 62 | u->ram.ptr = vec; 63 | while(u->ram.ptr) { 64 | instr = u->ram.dat[u->ram.ptr++]; 65 | switch(instr) { 66 | #pragma GCC diagnostic push 67 | #pragma GCC diagnostic ignored "-Wunused-value" 68 | #pragma GCC diagnostic ignored "-Wunused-variable" 69 | case 0x00: /* BRK */ 70 | case 0x20: /* BRK2 */ 71 | case 0x40: /* BRKr */ 72 | case 0x60: /* BRK2r */ 73 | case 0x80: /* BRKk */ 74 | case 0xa0: /* BRK2k */ 75 | case 0xc0: /* BRKkr */ 76 | case 0xe0: /* BRK2kr */ 77 | __asm__("evaluxn_00_BRK:"); 78 | { 79 | u->ram.ptr = 0; 80 | } 81 | break; 82 | case 0x01: /* LIT */ 83 | case 0x81: /* LITk */ 84 | __asm__("evaluxn_01_LIT:"); 85 | { 86 | u->wst.dat[u->wst.ptr] = mempeek8(u->ram.dat, u->ram.ptr++); 87 | #ifndef NO_STACK_CHECKS 88 | if(__builtin_expect(u->wst.ptr > 254, 0)) { 89 | u->wst.error = 2; 90 | goto error; 91 | } 92 | #endif 93 | u->wst.ptr += 1; 94 | } 95 | break; 96 | case 0x02: /* NOP */ 97 | case 0x22: /* NOP2 */ 98 | case 0x42: /* NOPr */ 99 | case 0x62: /* NOP2r */ 100 | case 0x82: /* NOPk */ 101 | case 0xa2: /* NOP2k */ 102 | case 0xc2: /* NOPkr */ 103 | case 0xe2: /* NOP2kr */ 104 | __asm__("evaluxn_02_NOP:"); 105 | { 106 | (void)u; 107 | } 108 | break; 109 | case 0x03: /* POP */ 110 | __asm__("evaluxn_03_POP:"); 111 | { 112 | u->wst.dat[u->wst.ptr - 1]; 113 | #ifndef NO_STACK_CHECKS 114 | if(__builtin_expect(u->wst.ptr < 1, 0)) { 115 | u->wst.error = 1; 116 | goto error; 117 | } 118 | #endif 119 | u->wst.ptr -= 1; 120 | } 121 | break; 122 | case 0x04: /* DUP */ 123 | __asm__("evaluxn_04_DUP:"); 124 | { 125 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 126 | u->wst.dat[u->wst.ptr] = a; 127 | #ifndef NO_STACK_CHECKS 128 | if(__builtin_expect(u->wst.ptr < 1, 0)) { 129 | u->wst.error = 1; 130 | goto error; 131 | } 132 | if(__builtin_expect(u->wst.ptr > 254, 0)) { 133 | u->wst.error = 2; 134 | goto error; 135 | } 136 | #endif 137 | u->wst.ptr += 1; 138 | } 139 | break; 140 | case 0x05: /* SWP */ 141 | __asm__("evaluxn_05_SWP:"); 142 | { 143 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 144 | u->wst.dat[u->wst.ptr - 2] = a; 145 | u->wst.dat[u->wst.ptr - 1] = b; 146 | #ifndef NO_STACK_CHECKS 147 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 148 | u->wst.error = 1; 149 | goto error; 150 | } 151 | #endif 152 | } 153 | break; 154 | case 0x06: /* OVR */ 155 | __asm__("evaluxn_06_OVR:"); 156 | { 157 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 158 | u->wst.dat[u->wst.ptr] = b; 159 | #ifndef NO_STACK_CHECKS 160 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 161 | u->wst.error = 1; 162 | goto error; 163 | } 164 | if(__builtin_expect(u->wst.ptr > 254, 0)) { 165 | u->wst.error = 2; 166 | goto error; 167 | } 168 | #endif 169 | u->wst.ptr += 1; 170 | } 171 | break; 172 | case 0x07: /* ROT */ 173 | __asm__("evaluxn_07_ROT:"); 174 | { 175 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2], c = u->wst.dat[u->wst.ptr - 3]; 176 | u->wst.dat[u->wst.ptr - 3] = b; 177 | u->wst.dat[u->wst.ptr - 2] = a; 178 | u->wst.dat[u->wst.ptr - 1] = c; 179 | #ifndef NO_STACK_CHECKS 180 | if(__builtin_expect(u->wst.ptr < 3, 0)) { 181 | u->wst.error = 1; 182 | goto error; 183 | } 184 | #endif 185 | } 186 | break; 187 | case 0x08: /* EQU */ 188 | __asm__("evaluxn_08_EQU:"); 189 | { 190 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 191 | u->wst.dat[u->wst.ptr - 2] = b == a; 192 | #ifndef NO_STACK_CHECKS 193 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 194 | u->wst.error = 1; 195 | goto error; 196 | } 197 | #endif 198 | u->wst.ptr -= 1; 199 | } 200 | break; 201 | case 0x09: /* NEQ */ 202 | __asm__("evaluxn_09_NEQ:"); 203 | { 204 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 205 | u->wst.dat[u->wst.ptr - 2] = b != a; 206 | #ifndef NO_STACK_CHECKS 207 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 208 | u->wst.error = 1; 209 | goto error; 210 | } 211 | #endif 212 | u->wst.ptr -= 1; 213 | } 214 | break; 215 | case 0x0a: /* GTH */ 216 | __asm__("evaluxn_0a_GTH:"); 217 | { 218 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 219 | u->wst.dat[u->wst.ptr - 2] = b > a; 220 | #ifndef NO_STACK_CHECKS 221 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 222 | u->wst.error = 1; 223 | goto error; 224 | } 225 | #endif 226 | u->wst.ptr -= 1; 227 | } 228 | break; 229 | case 0x0b: /* LTH */ 230 | __asm__("evaluxn_0b_LTH:"); 231 | { 232 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 233 | u->wst.dat[u->wst.ptr - 2] = b < a; 234 | #ifndef NO_STACK_CHECKS 235 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 236 | u->wst.error = 1; 237 | goto error; 238 | } 239 | #endif 240 | u->wst.ptr -= 1; 241 | } 242 | break; 243 | case 0x0c: /* JMP */ 244 | __asm__("evaluxn_0c_JMP:"); 245 | { 246 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 247 | u->ram.ptr += (Sint8)a; 248 | #ifndef NO_STACK_CHECKS 249 | if(__builtin_expect(u->wst.ptr < 1, 0)) { 250 | u->wst.error = 1; 251 | goto error; 252 | } 253 | #endif 254 | u->wst.ptr -= 1; 255 | } 256 | break; 257 | case 0x0d: /* JCN */ 258 | __asm__("evaluxn_0d_JCN:"); 259 | { 260 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 261 | if(u->wst.dat[u->wst.ptr - 2]) u->ram.ptr += (Sint8)a; 262 | #ifndef NO_STACK_CHECKS 263 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 264 | u->wst.error = 1; 265 | goto error; 266 | } 267 | #endif 268 | u->wst.ptr -= 2; 269 | } 270 | break; 271 | case 0x0e: /* JSR */ 272 | __asm__("evaluxn_0e_JSR:"); 273 | { 274 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 275 | u->rst.dat[u->rst.ptr] = u->ram.ptr >> 8; 276 | u->rst.dat[u->rst.ptr + 1] = u->ram.ptr & 0xff; 277 | u->ram.ptr += (Sint8)a; 278 | #ifndef NO_STACK_CHECKS 279 | if(__builtin_expect(u->wst.ptr < 1, 0)) { 280 | u->wst.error = 1; 281 | goto error; 282 | } 283 | #endif 284 | u->wst.ptr -= 1; 285 | #ifndef NO_STACK_CHECKS 286 | if(__builtin_expect(u->rst.ptr > 253, 0)) { 287 | u->rst.error = 2; 288 | goto error; 289 | } 290 | #endif 291 | u->rst.ptr += 2; 292 | } 293 | break; 294 | case 0x0f: /* STH */ 295 | __asm__("evaluxn_0f_STH:"); 296 | { 297 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 298 | u->rst.dat[u->rst.ptr] = a; 299 | #ifndef NO_STACK_CHECKS 300 | if(__builtin_expect(u->wst.ptr < 1, 0)) { 301 | u->wst.error = 1; 302 | goto error; 303 | } 304 | #endif 305 | u->wst.ptr -= 1; 306 | #ifndef NO_STACK_CHECKS 307 | if(__builtin_expect(u->rst.ptr > 254, 0)) { 308 | u->rst.error = 2; 309 | goto error; 310 | } 311 | #endif 312 | u->rst.ptr += 1; 313 | } 314 | break; 315 | case 0x10: /* LDZ */ 316 | __asm__("evaluxn_10_LDZ:"); 317 | { 318 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 319 | u->wst.dat[u->wst.ptr - 1] = mempeek8(u->ram.dat, a); 320 | #ifndef NO_STACK_CHECKS 321 | if(__builtin_expect(u->wst.ptr < 1, 0)) { 322 | u->wst.error = 1; 323 | goto error; 324 | } 325 | #endif 326 | } 327 | break; 328 | case 0x11: /* STZ */ 329 | __asm__("evaluxn_11_STZ:"); 330 | { 331 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 332 | Uint8 b = u->wst.dat[u->wst.ptr - 2]; 333 | mempoke8(u->ram.dat, a, b); 334 | #ifndef NO_STACK_CHECKS 335 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 336 | u->wst.error = 1; 337 | goto error; 338 | } 339 | #endif 340 | u->wst.ptr -= 2; 341 | } 342 | break; 343 | case 0x12: /* LDR */ 344 | __asm__("evaluxn_12_LDR:"); 345 | { 346 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 347 | u->wst.dat[u->wst.ptr - 1] = mempeek8(u->ram.dat, u->ram.ptr + (Sint8)a); 348 | #ifndef NO_STACK_CHECKS 349 | if(__builtin_expect(u->wst.ptr < 1, 0)) { 350 | u->wst.error = 1; 351 | goto error; 352 | } 353 | #endif 354 | } 355 | break; 356 | case 0x13: /* STR */ 357 | __asm__("evaluxn_13_STR:"); 358 | { 359 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 360 | Uint8 b = u->wst.dat[u->wst.ptr - 2]; 361 | mempoke8(u->ram.dat, u->ram.ptr + (Sint8)a, b); 362 | #ifndef NO_STACK_CHECKS 363 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 364 | u->wst.error = 1; 365 | goto error; 366 | } 367 | #endif 368 | u->wst.ptr -= 2; 369 | } 370 | break; 371 | case 0x14: /* LDA */ 372 | __asm__("evaluxn_14_LDA:"); 373 | { 374 | Uint16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)); 375 | u->wst.dat[u->wst.ptr - 2] = mempeek8(u->ram.dat, a); 376 | #ifndef NO_STACK_CHECKS 377 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 378 | u->wst.error = 1; 379 | goto error; 380 | } 381 | #endif 382 | u->wst.ptr -= 1; 383 | } 384 | break; 385 | case 0x15: /* STA */ 386 | __asm__("evaluxn_15_STA:"); 387 | { 388 | Uint16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)); 389 | Uint8 b = u->wst.dat[u->wst.ptr - 3]; 390 | mempoke8(u->ram.dat, a, b); 391 | #ifndef NO_STACK_CHECKS 392 | if(__builtin_expect(u->wst.ptr < 3, 0)) { 393 | u->wst.error = 1; 394 | goto error; 395 | } 396 | #endif 397 | u->wst.ptr -= 3; 398 | } 399 | break; 400 | case 0x16: /* DEI */ 401 | __asm__("evaluxn_16_DEI:"); 402 | { 403 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 404 | u->wst.dat[u->wst.ptr - 1] = devpeek8(&u->dev[a >> 4], a); 405 | #ifndef NO_STACK_CHECKS 406 | if(__builtin_expect(u->wst.ptr < 1, 0)) { 407 | u->wst.error = 1; 408 | goto error; 409 | } 410 | #endif 411 | } 412 | break; 413 | case 0x17: /* DEO */ 414 | __asm__("evaluxn_17_DEO:"); 415 | { 416 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 417 | devpoke8(&u->dev[a >> 4], a, b); 418 | #ifndef NO_STACK_CHECKS 419 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 420 | u->wst.error = 1; 421 | goto error; 422 | } 423 | #endif 424 | u->wst.ptr -= 2; 425 | } 426 | break; 427 | case 0x18: /* ADD */ 428 | __asm__("evaluxn_18_ADD:"); 429 | { 430 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 431 | u->wst.dat[u->wst.ptr - 2] = b + a; 432 | #ifndef NO_STACK_CHECKS 433 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 434 | u->wst.error = 1; 435 | goto error; 436 | } 437 | #endif 438 | u->wst.ptr -= 1; 439 | } 440 | break; 441 | case 0x19: /* SUB */ 442 | __asm__("evaluxn_19_SUB:"); 443 | { 444 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 445 | u->wst.dat[u->wst.ptr - 2] = b - a; 446 | #ifndef NO_STACK_CHECKS 447 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 448 | u->wst.error = 1; 449 | goto error; 450 | } 451 | #endif 452 | u->wst.ptr -= 1; 453 | } 454 | break; 455 | case 0x1a: /* MUL */ 456 | __asm__("evaluxn_1a_MUL:"); 457 | { 458 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 459 | u->wst.dat[u->wst.ptr - 2] = b * a; 460 | #ifndef NO_STACK_CHECKS 461 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 462 | u->wst.error = 1; 463 | goto error; 464 | } 465 | #endif 466 | u->wst.ptr -= 1; 467 | } 468 | break; 469 | case 0x1b: /* DIV */ 470 | __asm__("evaluxn_1b_DIV:"); 471 | { 472 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 473 | if(a == 0) { 474 | u->wst.error = 3; 475 | #ifndef NO_STACK_CHECKS 476 | goto error; 477 | #endif 478 | a = 1; 479 | } 480 | u->wst.dat[u->wst.ptr - 2] = b / a; 481 | #ifndef NO_STACK_CHECKS 482 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 483 | u->wst.error = 1; 484 | goto error; 485 | } 486 | #endif 487 | u->wst.ptr -= 1; 488 | } 489 | break; 490 | case 0x1c: /* AND */ 491 | __asm__("evaluxn_1c_AND:"); 492 | { 493 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 494 | u->wst.dat[u->wst.ptr - 2] = b & a; 495 | #ifndef NO_STACK_CHECKS 496 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 497 | u->wst.error = 1; 498 | goto error; 499 | } 500 | #endif 501 | u->wst.ptr -= 1; 502 | } 503 | break; 504 | case 0x1d: /* ORA */ 505 | __asm__("evaluxn_1d_ORA:"); 506 | { 507 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 508 | u->wst.dat[u->wst.ptr - 2] = b | a; 509 | #ifndef NO_STACK_CHECKS 510 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 511 | u->wst.error = 1; 512 | goto error; 513 | } 514 | #endif 515 | u->wst.ptr -= 1; 516 | } 517 | break; 518 | case 0x1e: /* EOR */ 519 | __asm__("evaluxn_1e_EOR:"); 520 | { 521 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 522 | u->wst.dat[u->wst.ptr - 2] = b ^ a; 523 | #ifndef NO_STACK_CHECKS 524 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 525 | u->wst.error = 1; 526 | goto error; 527 | } 528 | #endif 529 | u->wst.ptr -= 1; 530 | } 531 | break; 532 | case 0x1f: /* SFT */ 533 | __asm__("evaluxn_1f_SFT:"); 534 | { 535 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 536 | u->wst.dat[u->wst.ptr - 2] = b >> (a & 0x07) << ((a & 0x70) >> 4); 537 | #ifndef NO_STACK_CHECKS 538 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 539 | u->wst.error = 1; 540 | goto error; 541 | } 542 | #endif 543 | u->wst.ptr -= 1; 544 | } 545 | break; 546 | case 0x21: /* LIT2 */ 547 | case 0xa1: /* LIT2k */ 548 | __asm__("evaluxn_21_LIT2:"); 549 | { 550 | u->wst.dat[u->wst.ptr] = mempeek8(u->ram.dat, u->ram.ptr++); 551 | u->wst.dat[u->wst.ptr + 1] = mempeek8(u->ram.dat, u->ram.ptr++); 552 | #ifndef NO_STACK_CHECKS 553 | if(__builtin_expect(u->wst.ptr > 253, 0)) { 554 | u->wst.error = 2; 555 | goto error; 556 | } 557 | #endif 558 | u->wst.ptr += 2; 559 | } 560 | break; 561 | case 0x23: /* POP2 */ 562 | __asm__("evaluxn_23_POP2:"); 563 | { 564 | (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)); 565 | #ifndef NO_STACK_CHECKS 566 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 567 | u->wst.error = 1; 568 | goto error; 569 | } 570 | #endif 571 | u->wst.ptr -= 2; 572 | } 573 | break; 574 | case 0x24: /* DUP2 */ 575 | __asm__("evaluxn_24_DUP2:"); 576 | { 577 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 578 | u->wst.dat[u->wst.ptr] = b; 579 | u->wst.dat[u->wst.ptr + 1] = a; 580 | #ifndef NO_STACK_CHECKS 581 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 582 | u->wst.error = 1; 583 | goto error; 584 | } 585 | if(__builtin_expect(u->wst.ptr > 253, 0)) { 586 | u->wst.error = 2; 587 | goto error; 588 | } 589 | #endif 590 | u->wst.ptr += 2; 591 | } 592 | break; 593 | case 0x25: /* SWP2 */ 594 | __asm__("evaluxn_25_SWP2:"); 595 | { 596 | Uint8 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]; 597 | u->wst.dat[u->wst.ptr - 4] = b; 598 | u->wst.dat[u->wst.ptr - 3] = a; 599 | u->wst.dat[u->wst.ptr - 2] = d; 600 | u->wst.dat[u->wst.ptr - 1] = c; 601 | #ifndef NO_STACK_CHECKS 602 | if(__builtin_expect(u->wst.ptr < 4, 0)) { 603 | u->wst.error = 1; 604 | goto error; 605 | } 606 | #endif 607 | } 608 | break; 609 | case 0x26: /* OVR2 */ 610 | __asm__("evaluxn_26_OVR2:"); 611 | { 612 | Uint8 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]; 613 | u->wst.dat[u->wst.ptr] = d; 614 | u->wst.dat[u->wst.ptr + 1] = c; 615 | #ifndef NO_STACK_CHECKS 616 | if(__builtin_expect(u->wst.ptr < 4, 0)) { 617 | u->wst.error = 1; 618 | goto error; 619 | } 620 | if(__builtin_expect(u->wst.ptr > 253, 0)) { 621 | u->wst.error = 2; 622 | goto error; 623 | } 624 | #endif 625 | u->wst.ptr += 2; 626 | } 627 | break; 628 | case 0x27: /* ROT2 */ 629 | __asm__("evaluxn_27_ROT2:"); 630 | { 631 | Uint8 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]; 632 | u->wst.dat[u->wst.ptr - 6] = d; 633 | u->wst.dat[u->wst.ptr - 5] = c; 634 | u->wst.dat[u->wst.ptr - 4] = b; 635 | u->wst.dat[u->wst.ptr - 3] = a; 636 | u->wst.dat[u->wst.ptr - 2] = f; 637 | u->wst.dat[u->wst.ptr - 1] = e; 638 | #ifndef NO_STACK_CHECKS 639 | if(__builtin_expect(u->wst.ptr < 6, 0)) { 640 | u->wst.error = 1; 641 | goto error; 642 | } 643 | #endif 644 | } 645 | break; 646 | case 0x28: /* EQU2 */ 647 | __asm__("evaluxn_28_EQU2:"); 648 | { 649 | Uint16 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)); 650 | u->wst.dat[u->wst.ptr - 4] = b == a; 651 | #ifndef NO_STACK_CHECKS 652 | if(__builtin_expect(u->wst.ptr < 4, 0)) { 653 | u->wst.error = 1; 654 | goto error; 655 | } 656 | #endif 657 | u->wst.ptr -= 3; 658 | } 659 | break; 660 | case 0x29: /* NEQ2 */ 661 | __asm__("evaluxn_29_NEQ2:"); 662 | { 663 | Uint16 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)); 664 | u->wst.dat[u->wst.ptr - 4] = b != a; 665 | #ifndef NO_STACK_CHECKS 666 | if(__builtin_expect(u->wst.ptr < 4, 0)) { 667 | u->wst.error = 1; 668 | goto error; 669 | } 670 | #endif 671 | u->wst.ptr -= 3; 672 | } 673 | break; 674 | case 0x2a: /* GTH2 */ 675 | __asm__("evaluxn_2a_GTH2:"); 676 | { 677 | Uint16 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)); 678 | u->wst.dat[u->wst.ptr - 4] = b > a; 679 | #ifndef NO_STACK_CHECKS 680 | if(__builtin_expect(u->wst.ptr < 4, 0)) { 681 | u->wst.error = 1; 682 | goto error; 683 | } 684 | #endif 685 | u->wst.ptr -= 3; 686 | } 687 | break; 688 | case 0x2b: /* LTH2 */ 689 | __asm__("evaluxn_2b_LTH2:"); 690 | { 691 | Uint16 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)); 692 | u->wst.dat[u->wst.ptr - 4] = b < a; 693 | #ifndef NO_STACK_CHECKS 694 | if(__builtin_expect(u->wst.ptr < 4, 0)) { 695 | u->wst.error = 1; 696 | goto error; 697 | } 698 | #endif 699 | u->wst.ptr -= 3; 700 | } 701 | break; 702 | case 0x2c: /* JMP2 */ 703 | __asm__("evaluxn_2c_JMP2:"); 704 | { 705 | u->ram.ptr = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)); 706 | #ifndef NO_STACK_CHECKS 707 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 708 | u->wst.error = 1; 709 | goto error; 710 | } 711 | #endif 712 | u->wst.ptr -= 2; 713 | } 714 | break; 715 | case 0x2d: /* JCN2 */ 716 | __asm__("evaluxn_2d_JCN2:"); 717 | { 718 | Uint16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)); 719 | if(u->wst.dat[u->wst.ptr - 3]) u->ram.ptr = a; 720 | #ifndef NO_STACK_CHECKS 721 | if(__builtin_expect(u->wst.ptr < 3, 0)) { 722 | u->wst.error = 1; 723 | goto error; 724 | } 725 | #endif 726 | u->wst.ptr -= 3; 727 | } 728 | break; 729 | case 0x2e: /* JSR2 */ 730 | __asm__("evaluxn_2e_JSR2:"); 731 | { 732 | u->rst.dat[u->rst.ptr] = u->ram.ptr >> 8; 733 | u->rst.dat[u->rst.ptr + 1] = u->ram.ptr & 0xff; 734 | u->ram.ptr = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)); 735 | #ifndef NO_STACK_CHECKS 736 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 737 | u->wst.error = 1; 738 | goto error; 739 | } 740 | #endif 741 | u->wst.ptr -= 2; 742 | #ifndef NO_STACK_CHECKS 743 | if(__builtin_expect(u->rst.ptr > 253, 0)) { 744 | u->rst.error = 2; 745 | goto error; 746 | } 747 | #endif 748 | u->rst.ptr += 2; 749 | } 750 | break; 751 | case 0x2f: /* STH2 */ 752 | __asm__("evaluxn_2f_STH2:"); 753 | { 754 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 755 | u->rst.dat[u->rst.ptr] = b; 756 | u->rst.dat[u->rst.ptr + 1] = a; 757 | #ifndef NO_STACK_CHECKS 758 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 759 | u->wst.error = 1; 760 | goto error; 761 | } 762 | #endif 763 | u->wst.ptr -= 2; 764 | #ifndef NO_STACK_CHECKS 765 | if(__builtin_expect(u->rst.ptr > 253, 0)) { 766 | u->rst.error = 2; 767 | goto error; 768 | } 769 | #endif 770 | u->rst.ptr += 2; 771 | } 772 | break; 773 | case 0x30: /* LDZ2 */ 774 | __asm__("evaluxn_30_LDZ2:"); 775 | { 776 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 777 | u->wst.dat[u->wst.ptr - 1] = mempeek8(u->ram.dat, a); 778 | u->wst.dat[u->wst.ptr] = mempeek8(u->ram.dat, a + 1); 779 | #ifndef NO_STACK_CHECKS 780 | if(__builtin_expect(u->wst.ptr < 1, 0)) { 781 | u->wst.error = 1; 782 | goto error; 783 | } 784 | if(__builtin_expect(u->wst.ptr > 254, 0)) { 785 | u->wst.error = 2; 786 | goto error; 787 | } 788 | #endif 789 | u->wst.ptr += 1; 790 | } 791 | break; 792 | case 0x31: /* STZ2 */ 793 | __asm__("evaluxn_31_STZ2:"); 794 | { 795 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 796 | Uint16 b = (u->wst.dat[u->wst.ptr - 2] | (u->wst.dat[u->wst.ptr - 3] << 8)); 797 | mempoke16(u->ram.dat, a, b); 798 | #ifndef NO_STACK_CHECKS 799 | if(__builtin_expect(u->wst.ptr < 3, 0)) { 800 | u->wst.error = 1; 801 | goto error; 802 | } 803 | #endif 804 | u->wst.ptr -= 3; 805 | } 806 | break; 807 | case 0x32: /* LDR2 */ 808 | __asm__("evaluxn_32_LDR2:"); 809 | { 810 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 811 | u->wst.dat[u->wst.ptr - 1] = mempeek8(u->ram.dat, u->ram.ptr + (Sint8)a); 812 | u->wst.dat[u->wst.ptr] = mempeek8(u->ram.dat, u->ram.ptr + (Sint8)a + 1); 813 | #ifndef NO_STACK_CHECKS 814 | if(__builtin_expect(u->wst.ptr < 1, 0)) { 815 | u->wst.error = 1; 816 | goto error; 817 | } 818 | if(__builtin_expect(u->wst.ptr > 254, 0)) { 819 | u->wst.error = 2; 820 | goto error; 821 | } 822 | #endif 823 | u->wst.ptr += 1; 824 | } 825 | break; 826 | case 0x33: /* STR2 */ 827 | __asm__("evaluxn_33_STR2:"); 828 | { 829 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 830 | Uint16 b = (u->wst.dat[u->wst.ptr - 2] | (u->wst.dat[u->wst.ptr - 3] << 8)); 831 | mempoke16(u->ram.dat, u->ram.ptr + (Sint8)a, b); 832 | #ifndef NO_STACK_CHECKS 833 | if(__builtin_expect(u->wst.ptr < 3, 0)) { 834 | u->wst.error = 1; 835 | goto error; 836 | } 837 | #endif 838 | u->wst.ptr -= 3; 839 | } 840 | break; 841 | case 0x34: /* LDA2 */ 842 | __asm__("evaluxn_34_LDA2:"); 843 | { 844 | Uint16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)); 845 | u->wst.dat[u->wst.ptr - 2] = mempeek8(u->ram.dat, a); 846 | u->wst.dat[u->wst.ptr - 1] = mempeek8(u->ram.dat, a + 1); 847 | #ifndef NO_STACK_CHECKS 848 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 849 | u->wst.error = 1; 850 | goto error; 851 | } 852 | #endif 853 | } 854 | break; 855 | case 0x35: /* STA2 */ 856 | __asm__("evaluxn_35_STA2:"); 857 | { 858 | Uint16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)); 859 | Uint16 b = (u->wst.dat[u->wst.ptr - 3] | (u->wst.dat[u->wst.ptr - 4] << 8)); 860 | mempoke16(u->ram.dat, a, b); 861 | #ifndef NO_STACK_CHECKS 862 | if(__builtin_expect(u->wst.ptr < 4, 0)) { 863 | u->wst.error = 1; 864 | goto error; 865 | } 866 | #endif 867 | u->wst.ptr -= 4; 868 | } 869 | break; 870 | case 0x36: /* DEI2 */ 871 | __asm__("evaluxn_36_DEI2:"); 872 | { 873 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 874 | u->wst.dat[u->wst.ptr - 1] = devpeek8(&u->dev[a >> 4], a); 875 | u->wst.dat[u->wst.ptr] = devpeek8(&u->dev[a >> 4], a + 1); 876 | #ifndef NO_STACK_CHECKS 877 | if(__builtin_expect(u->wst.ptr < 1, 0)) { 878 | u->wst.error = 1; 879 | goto error; 880 | } 881 | if(__builtin_expect(u->wst.ptr > 254, 0)) { 882 | u->wst.error = 2; 883 | goto error; 884 | } 885 | #endif 886 | u->wst.ptr += 1; 887 | } 888 | break; 889 | case 0x37: /* DEO2 */ 890 | __asm__("evaluxn_37_DEO2:"); 891 | { 892 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 893 | Uint16 b = (u->wst.dat[u->wst.ptr - 2] | (u->wst.dat[u->wst.ptr - 3] << 8)); 894 | devpoke16(&u->dev[a >> 4], a, b); 895 | #ifndef NO_STACK_CHECKS 896 | if(__builtin_expect(u->wst.ptr < 3, 0)) { 897 | u->wst.error = 1; 898 | goto error; 899 | } 900 | #endif 901 | u->wst.ptr -= 3; 902 | } 903 | break; 904 | case 0x38: /* ADD2 */ 905 | __asm__("evaluxn_38_ADD2:"); 906 | { 907 | Uint16 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)); 908 | u->wst.dat[u->wst.ptr - 4] = (b + a) >> 8; 909 | u->wst.dat[u->wst.ptr - 3] = (b + a) & 0xff; 910 | #ifndef NO_STACK_CHECKS 911 | if(__builtin_expect(u->wst.ptr < 4, 0)) { 912 | u->wst.error = 1; 913 | goto error; 914 | } 915 | #endif 916 | u->wst.ptr -= 2; 917 | } 918 | break; 919 | case 0x39: /* SUB2 */ 920 | __asm__("evaluxn_39_SUB2:"); 921 | { 922 | Uint16 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)); 923 | u->wst.dat[u->wst.ptr - 4] = (b - a) >> 8; 924 | u->wst.dat[u->wst.ptr - 3] = (b - a) & 0xff; 925 | #ifndef NO_STACK_CHECKS 926 | if(__builtin_expect(u->wst.ptr < 4, 0)) { 927 | u->wst.error = 1; 928 | goto error; 929 | } 930 | #endif 931 | u->wst.ptr -= 2; 932 | } 933 | break; 934 | case 0x3a: /* MUL2 */ 935 | __asm__("evaluxn_3a_MUL2:"); 936 | { 937 | Uint16 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)); 938 | u->wst.dat[u->wst.ptr - 4] = (b * a) >> 8; 939 | u->wst.dat[u->wst.ptr - 3] = (b * a) & 0xff; 940 | #ifndef NO_STACK_CHECKS 941 | if(__builtin_expect(u->wst.ptr < 4, 0)) { 942 | u->wst.error = 1; 943 | goto error; 944 | } 945 | #endif 946 | u->wst.ptr -= 2; 947 | } 948 | break; 949 | case 0x3b: /* DIV2 */ 950 | __asm__("evaluxn_3b_DIV2:"); 951 | { 952 | Uint16 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)); 953 | if(a == 0) { 954 | u->wst.error = 3; 955 | #ifndef NO_STACK_CHECKS 956 | goto error; 957 | #endif 958 | a = 1; 959 | } 960 | u->wst.dat[u->wst.ptr - 4] = (b / a) >> 8; 961 | u->wst.dat[u->wst.ptr - 3] = (b / a) & 0xff; 962 | #ifndef NO_STACK_CHECKS 963 | if(__builtin_expect(u->wst.ptr < 4, 0)) { 964 | u->wst.error = 1; 965 | goto error; 966 | } 967 | #endif 968 | u->wst.ptr -= 2; 969 | } 970 | break; 971 | case 0x3c: /* AND2 */ 972 | __asm__("evaluxn_3c_AND2:"); 973 | { 974 | Uint8 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]; 975 | u->wst.dat[u->wst.ptr - 4] = d & b; 976 | u->wst.dat[u->wst.ptr - 3] = c & a; 977 | #ifndef NO_STACK_CHECKS 978 | if(__builtin_expect(u->wst.ptr < 4, 0)) { 979 | u->wst.error = 1; 980 | goto error; 981 | } 982 | #endif 983 | u->wst.ptr -= 2; 984 | } 985 | break; 986 | case 0x3d: /* ORA2 */ 987 | __asm__("evaluxn_3d_ORA2:"); 988 | { 989 | Uint8 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]; 990 | u->wst.dat[u->wst.ptr - 4] = d | b; 991 | u->wst.dat[u->wst.ptr - 3] = c | a; 992 | #ifndef NO_STACK_CHECKS 993 | if(__builtin_expect(u->wst.ptr < 4, 0)) { 994 | u->wst.error = 1; 995 | goto error; 996 | } 997 | #endif 998 | u->wst.ptr -= 2; 999 | } 1000 | break; 1001 | case 0x3e: /* EOR2 */ 1002 | __asm__("evaluxn_3e_EOR2:"); 1003 | { 1004 | Uint8 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]; 1005 | u->wst.dat[u->wst.ptr - 4] = d ^ b; 1006 | u->wst.dat[u->wst.ptr - 3] = c ^ a; 1007 | #ifndef NO_STACK_CHECKS 1008 | if(__builtin_expect(u->wst.ptr < 4, 0)) { 1009 | u->wst.error = 1; 1010 | goto error; 1011 | } 1012 | #endif 1013 | u->wst.ptr -= 2; 1014 | } 1015 | break; 1016 | case 0x3f: /* SFT2 */ 1017 | __asm__("evaluxn_3f_SFT2:"); 1018 | { 1019 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 1020 | Uint16 b = (u->wst.dat[u->wst.ptr - 2] | (u->wst.dat[u->wst.ptr - 3] << 8)); 1021 | u->wst.dat[u->wst.ptr - 3] = (b >> (a & 0x0f) << ((a & 0xf0) >> 4)) >> 8; 1022 | u->wst.dat[u->wst.ptr - 2] = (b >> (a & 0x0f) << ((a & 0xf0) >> 4)) & 0xff; 1023 | #ifndef NO_STACK_CHECKS 1024 | if(__builtin_expect(u->wst.ptr < 3, 0)) { 1025 | u->wst.error = 1; 1026 | goto error; 1027 | } 1028 | #endif 1029 | u->wst.ptr -= 1; 1030 | } 1031 | break; 1032 | case 0x41: /* LITr */ 1033 | case 0xc1: /* LITkr */ 1034 | __asm__("evaluxn_41_LITr:"); 1035 | { 1036 | u->rst.dat[u->rst.ptr] = mempeek8(u->ram.dat, u->ram.ptr++); 1037 | #ifndef NO_STACK_CHECKS 1038 | if(__builtin_expect(u->rst.ptr > 254, 0)) { 1039 | u->rst.error = 2; 1040 | goto error; 1041 | } 1042 | #endif 1043 | u->rst.ptr += 1; 1044 | } 1045 | break; 1046 | case 0x43: /* POPr */ 1047 | __asm__("evaluxn_43_POPr:"); 1048 | { 1049 | u->rst.dat[u->rst.ptr - 1]; 1050 | #ifndef NO_STACK_CHECKS 1051 | if(__builtin_expect(u->rst.ptr < 1, 0)) { 1052 | u->rst.error = 1; 1053 | goto error; 1054 | } 1055 | #endif 1056 | u->rst.ptr -= 1; 1057 | } 1058 | break; 1059 | case 0x44: /* DUPr */ 1060 | __asm__("evaluxn_44_DUPr:"); 1061 | { 1062 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 1063 | u->rst.dat[u->rst.ptr] = a; 1064 | #ifndef NO_STACK_CHECKS 1065 | if(__builtin_expect(u->rst.ptr < 1, 0)) { 1066 | u->rst.error = 1; 1067 | goto error; 1068 | } 1069 | if(__builtin_expect(u->rst.ptr > 254, 0)) { 1070 | u->rst.error = 2; 1071 | goto error; 1072 | } 1073 | #endif 1074 | u->rst.ptr += 1; 1075 | } 1076 | break; 1077 | case 0x45: /* SWPr */ 1078 | __asm__("evaluxn_45_SWPr:"); 1079 | { 1080 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 1081 | u->rst.dat[u->rst.ptr - 2] = a; 1082 | u->rst.dat[u->rst.ptr - 1] = b; 1083 | #ifndef NO_STACK_CHECKS 1084 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 1085 | u->rst.error = 1; 1086 | goto error; 1087 | } 1088 | #endif 1089 | } 1090 | break; 1091 | case 0x46: /* OVRr */ 1092 | __asm__("evaluxn_46_OVRr:"); 1093 | { 1094 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 1095 | u->rst.dat[u->rst.ptr] = b; 1096 | #ifndef NO_STACK_CHECKS 1097 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 1098 | u->rst.error = 1; 1099 | goto error; 1100 | } 1101 | if(__builtin_expect(u->rst.ptr > 254, 0)) { 1102 | u->rst.error = 2; 1103 | goto error; 1104 | } 1105 | #endif 1106 | u->rst.ptr += 1; 1107 | } 1108 | break; 1109 | case 0x47: /* ROTr */ 1110 | __asm__("evaluxn_47_ROTr:"); 1111 | { 1112 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2], c = u->rst.dat[u->rst.ptr - 3]; 1113 | u->rst.dat[u->rst.ptr - 3] = b; 1114 | u->rst.dat[u->rst.ptr - 2] = a; 1115 | u->rst.dat[u->rst.ptr - 1] = c; 1116 | #ifndef NO_STACK_CHECKS 1117 | if(__builtin_expect(u->rst.ptr < 3, 0)) { 1118 | u->rst.error = 1; 1119 | goto error; 1120 | } 1121 | #endif 1122 | } 1123 | break; 1124 | case 0x48: /* EQUr */ 1125 | __asm__("evaluxn_48_EQUr:"); 1126 | { 1127 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 1128 | u->rst.dat[u->rst.ptr - 2] = b == a; 1129 | #ifndef NO_STACK_CHECKS 1130 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 1131 | u->rst.error = 1; 1132 | goto error; 1133 | } 1134 | #endif 1135 | u->rst.ptr -= 1; 1136 | } 1137 | break; 1138 | case 0x49: /* NEQr */ 1139 | __asm__("evaluxn_49_NEQr:"); 1140 | { 1141 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 1142 | u->rst.dat[u->rst.ptr - 2] = b != a; 1143 | #ifndef NO_STACK_CHECKS 1144 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 1145 | u->rst.error = 1; 1146 | goto error; 1147 | } 1148 | #endif 1149 | u->rst.ptr -= 1; 1150 | } 1151 | break; 1152 | case 0x4a: /* GTHr */ 1153 | __asm__("evaluxn_4a_GTHr:"); 1154 | { 1155 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 1156 | u->rst.dat[u->rst.ptr - 2] = b > a; 1157 | #ifndef NO_STACK_CHECKS 1158 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 1159 | u->rst.error = 1; 1160 | goto error; 1161 | } 1162 | #endif 1163 | u->rst.ptr -= 1; 1164 | } 1165 | break; 1166 | case 0x4b: /* LTHr */ 1167 | __asm__("evaluxn_4b_LTHr:"); 1168 | { 1169 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 1170 | u->rst.dat[u->rst.ptr - 2] = b < a; 1171 | #ifndef NO_STACK_CHECKS 1172 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 1173 | u->rst.error = 1; 1174 | goto error; 1175 | } 1176 | #endif 1177 | u->rst.ptr -= 1; 1178 | } 1179 | break; 1180 | case 0x4c: /* JMPr */ 1181 | __asm__("evaluxn_4c_JMPr:"); 1182 | { 1183 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 1184 | u->ram.ptr += (Sint8)a; 1185 | #ifndef NO_STACK_CHECKS 1186 | if(__builtin_expect(u->rst.ptr < 1, 0)) { 1187 | u->rst.error = 1; 1188 | goto error; 1189 | } 1190 | #endif 1191 | u->rst.ptr -= 1; 1192 | } 1193 | break; 1194 | case 0x4d: /* JCNr */ 1195 | __asm__("evaluxn_4d_JCNr:"); 1196 | { 1197 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 1198 | if(u->rst.dat[u->rst.ptr - 2]) u->ram.ptr += (Sint8)a; 1199 | #ifndef NO_STACK_CHECKS 1200 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 1201 | u->rst.error = 1; 1202 | goto error; 1203 | } 1204 | #endif 1205 | u->rst.ptr -= 2; 1206 | } 1207 | break; 1208 | case 0x4e: /* JSRr */ 1209 | __asm__("evaluxn_4e_JSRr:"); 1210 | { 1211 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 1212 | u->wst.dat[u->wst.ptr] = u->ram.ptr >> 8; 1213 | u->wst.dat[u->wst.ptr + 1] = u->ram.ptr & 0xff; 1214 | u->ram.ptr += (Sint8)a; 1215 | #ifndef NO_STACK_CHECKS 1216 | if(__builtin_expect(u->rst.ptr < 1, 0)) { 1217 | u->rst.error = 1; 1218 | goto error; 1219 | } 1220 | #endif 1221 | u->rst.ptr -= 1; 1222 | #ifndef NO_STACK_CHECKS 1223 | if(__builtin_expect(u->wst.ptr > 253, 0)) { 1224 | u->wst.error = 2; 1225 | goto error; 1226 | } 1227 | #endif 1228 | u->wst.ptr += 2; 1229 | } 1230 | break; 1231 | case 0x4f: /* STHr */ 1232 | __asm__("evaluxn_4f_STHr:"); 1233 | { 1234 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 1235 | u->wst.dat[u->wst.ptr] = a; 1236 | #ifndef NO_STACK_CHECKS 1237 | if(__builtin_expect(u->rst.ptr < 1, 0)) { 1238 | u->rst.error = 1; 1239 | goto error; 1240 | } 1241 | #endif 1242 | u->rst.ptr -= 1; 1243 | #ifndef NO_STACK_CHECKS 1244 | if(__builtin_expect(u->wst.ptr > 254, 0)) { 1245 | u->wst.error = 2; 1246 | goto error; 1247 | } 1248 | #endif 1249 | u->wst.ptr += 1; 1250 | } 1251 | break; 1252 | case 0x50: /* LDZr */ 1253 | __asm__("evaluxn_50_LDZr:"); 1254 | { 1255 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 1256 | u->rst.dat[u->rst.ptr - 1] = mempeek8(u->ram.dat, a); 1257 | #ifndef NO_STACK_CHECKS 1258 | if(__builtin_expect(u->rst.ptr < 1, 0)) { 1259 | u->rst.error = 1; 1260 | goto error; 1261 | } 1262 | #endif 1263 | } 1264 | break; 1265 | case 0x51: /* STZr */ 1266 | __asm__("evaluxn_51_STZr:"); 1267 | { 1268 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 1269 | Uint8 b = u->rst.dat[u->rst.ptr - 2]; 1270 | mempoke8(u->ram.dat, a, b); 1271 | #ifndef NO_STACK_CHECKS 1272 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 1273 | u->rst.error = 1; 1274 | goto error; 1275 | } 1276 | #endif 1277 | u->rst.ptr -= 2; 1278 | } 1279 | break; 1280 | case 0x52: /* LDRr */ 1281 | __asm__("evaluxn_52_LDRr:"); 1282 | { 1283 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 1284 | u->rst.dat[u->rst.ptr - 1] = mempeek8(u->ram.dat, u->ram.ptr + (Sint8)a); 1285 | #ifndef NO_STACK_CHECKS 1286 | if(__builtin_expect(u->rst.ptr < 1, 0)) { 1287 | u->rst.error = 1; 1288 | goto error; 1289 | } 1290 | #endif 1291 | } 1292 | break; 1293 | case 0x53: /* STRr */ 1294 | __asm__("evaluxn_53_STRr:"); 1295 | { 1296 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 1297 | Uint8 b = u->rst.dat[u->rst.ptr - 2]; 1298 | mempoke8(u->ram.dat, u->ram.ptr + (Sint8)a, b); 1299 | #ifndef NO_STACK_CHECKS 1300 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 1301 | u->rst.error = 1; 1302 | goto error; 1303 | } 1304 | #endif 1305 | u->rst.ptr -= 2; 1306 | } 1307 | break; 1308 | case 0x54: /* LDAr */ 1309 | __asm__("evaluxn_54_LDAr:"); 1310 | { 1311 | Uint16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)); 1312 | u->rst.dat[u->rst.ptr - 2] = mempeek8(u->ram.dat, a); 1313 | #ifndef NO_STACK_CHECKS 1314 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 1315 | u->rst.error = 1; 1316 | goto error; 1317 | } 1318 | #endif 1319 | u->rst.ptr -= 1; 1320 | } 1321 | break; 1322 | case 0x55: /* STAr */ 1323 | __asm__("evaluxn_55_STAr:"); 1324 | { 1325 | Uint16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)); 1326 | Uint8 b = u->rst.dat[u->rst.ptr - 3]; 1327 | mempoke8(u->ram.dat, a, b); 1328 | #ifndef NO_STACK_CHECKS 1329 | if(__builtin_expect(u->rst.ptr < 3, 0)) { 1330 | u->rst.error = 1; 1331 | goto error; 1332 | } 1333 | #endif 1334 | u->rst.ptr -= 3; 1335 | } 1336 | break; 1337 | case 0x56: /* DEIr */ 1338 | __asm__("evaluxn_56_DEIr:"); 1339 | { 1340 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 1341 | u->rst.dat[u->rst.ptr - 1] = devpeek8(&u->dev[a >> 4], a); 1342 | #ifndef NO_STACK_CHECKS 1343 | if(__builtin_expect(u->rst.ptr < 1, 0)) { 1344 | u->rst.error = 1; 1345 | goto error; 1346 | } 1347 | #endif 1348 | } 1349 | break; 1350 | case 0x57: /* DEOr */ 1351 | __asm__("evaluxn_57_DEOr:"); 1352 | { 1353 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 1354 | devpoke8(&u->dev[a >> 4], a, b); 1355 | #ifndef NO_STACK_CHECKS 1356 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 1357 | u->rst.error = 1; 1358 | goto error; 1359 | } 1360 | #endif 1361 | u->rst.ptr -= 2; 1362 | } 1363 | break; 1364 | case 0x58: /* ADDr */ 1365 | __asm__("evaluxn_58_ADDr:"); 1366 | { 1367 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 1368 | u->rst.dat[u->rst.ptr - 2] = b + a; 1369 | #ifndef NO_STACK_CHECKS 1370 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 1371 | u->rst.error = 1; 1372 | goto error; 1373 | } 1374 | #endif 1375 | u->rst.ptr -= 1; 1376 | } 1377 | break; 1378 | case 0x59: /* SUBr */ 1379 | __asm__("evaluxn_59_SUBr:"); 1380 | { 1381 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 1382 | u->rst.dat[u->rst.ptr - 2] = b - a; 1383 | #ifndef NO_STACK_CHECKS 1384 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 1385 | u->rst.error = 1; 1386 | goto error; 1387 | } 1388 | #endif 1389 | u->rst.ptr -= 1; 1390 | } 1391 | break; 1392 | case 0x5a: /* MULr */ 1393 | __asm__("evaluxn_5a_MULr:"); 1394 | { 1395 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 1396 | u->rst.dat[u->rst.ptr - 2] = b * a; 1397 | #ifndef NO_STACK_CHECKS 1398 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 1399 | u->rst.error = 1; 1400 | goto error; 1401 | } 1402 | #endif 1403 | u->rst.ptr -= 1; 1404 | } 1405 | break; 1406 | case 0x5b: /* DIVr */ 1407 | __asm__("evaluxn_5b_DIVr:"); 1408 | { 1409 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 1410 | if(a == 0) { 1411 | u->rst.error = 3; 1412 | #ifndef NO_STACK_CHECKS 1413 | goto error; 1414 | #endif 1415 | a = 1; 1416 | } 1417 | u->rst.dat[u->rst.ptr - 2] = b / a; 1418 | #ifndef NO_STACK_CHECKS 1419 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 1420 | u->rst.error = 1; 1421 | goto error; 1422 | } 1423 | #endif 1424 | u->rst.ptr -= 1; 1425 | } 1426 | break; 1427 | case 0x5c: /* ANDr */ 1428 | __asm__("evaluxn_5c_ANDr:"); 1429 | { 1430 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 1431 | u->rst.dat[u->rst.ptr - 2] = b & a; 1432 | #ifndef NO_STACK_CHECKS 1433 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 1434 | u->rst.error = 1; 1435 | goto error; 1436 | } 1437 | #endif 1438 | u->rst.ptr -= 1; 1439 | } 1440 | break; 1441 | case 0x5d: /* ORAr */ 1442 | __asm__("evaluxn_5d_ORAr:"); 1443 | { 1444 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 1445 | u->rst.dat[u->rst.ptr - 2] = b | a; 1446 | #ifndef NO_STACK_CHECKS 1447 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 1448 | u->rst.error = 1; 1449 | goto error; 1450 | } 1451 | #endif 1452 | u->rst.ptr -= 1; 1453 | } 1454 | break; 1455 | case 0x5e: /* EORr */ 1456 | __asm__("evaluxn_5e_EORr:"); 1457 | { 1458 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 1459 | u->rst.dat[u->rst.ptr - 2] = b ^ a; 1460 | #ifndef NO_STACK_CHECKS 1461 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 1462 | u->rst.error = 1; 1463 | goto error; 1464 | } 1465 | #endif 1466 | u->rst.ptr -= 1; 1467 | } 1468 | break; 1469 | case 0x5f: /* SFTr */ 1470 | __asm__("evaluxn_5f_SFTr:"); 1471 | { 1472 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 1473 | u->rst.dat[u->rst.ptr - 2] = b >> (a & 0x07) << ((a & 0x70) >> 4); 1474 | #ifndef NO_STACK_CHECKS 1475 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 1476 | u->rst.error = 1; 1477 | goto error; 1478 | } 1479 | #endif 1480 | u->rst.ptr -= 1; 1481 | } 1482 | break; 1483 | case 0x61: /* LIT2r */ 1484 | case 0xe1: /* LIT2kr */ 1485 | __asm__("evaluxn_61_LIT2r:"); 1486 | { 1487 | u->rst.dat[u->rst.ptr] = mempeek8(u->ram.dat, u->ram.ptr++); 1488 | u->rst.dat[u->rst.ptr + 1] = mempeek8(u->ram.dat, u->ram.ptr++); 1489 | #ifndef NO_STACK_CHECKS 1490 | if(__builtin_expect(u->rst.ptr > 253, 0)) { 1491 | u->rst.error = 2; 1492 | goto error; 1493 | } 1494 | #endif 1495 | u->rst.ptr += 2; 1496 | } 1497 | break; 1498 | case 0x63: /* POP2r */ 1499 | __asm__("evaluxn_63_POP2r:"); 1500 | { 1501 | (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)); 1502 | #ifndef NO_STACK_CHECKS 1503 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 1504 | u->rst.error = 1; 1505 | goto error; 1506 | } 1507 | #endif 1508 | u->rst.ptr -= 2; 1509 | } 1510 | break; 1511 | case 0x64: /* DUP2r */ 1512 | __asm__("evaluxn_64_DUP2r:"); 1513 | { 1514 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 1515 | u->rst.dat[u->rst.ptr] = b; 1516 | u->rst.dat[u->rst.ptr + 1] = a; 1517 | #ifndef NO_STACK_CHECKS 1518 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 1519 | u->rst.error = 1; 1520 | goto error; 1521 | } 1522 | if(__builtin_expect(u->rst.ptr > 253, 0)) { 1523 | u->rst.error = 2; 1524 | goto error; 1525 | } 1526 | #endif 1527 | u->rst.ptr += 2; 1528 | } 1529 | break; 1530 | case 0x65: /* SWP2r */ 1531 | __asm__("evaluxn_65_SWP2r:"); 1532 | { 1533 | Uint8 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]; 1534 | u->rst.dat[u->rst.ptr - 4] = b; 1535 | u->rst.dat[u->rst.ptr - 3] = a; 1536 | u->rst.dat[u->rst.ptr - 2] = d; 1537 | u->rst.dat[u->rst.ptr - 1] = c; 1538 | #ifndef NO_STACK_CHECKS 1539 | if(__builtin_expect(u->rst.ptr < 4, 0)) { 1540 | u->rst.error = 1; 1541 | goto error; 1542 | } 1543 | #endif 1544 | } 1545 | break; 1546 | case 0x66: /* OVR2r */ 1547 | __asm__("evaluxn_66_OVR2r:"); 1548 | { 1549 | Uint8 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]; 1550 | u->rst.dat[u->rst.ptr] = d; 1551 | u->rst.dat[u->rst.ptr + 1] = c; 1552 | #ifndef NO_STACK_CHECKS 1553 | if(__builtin_expect(u->rst.ptr < 4, 0)) { 1554 | u->rst.error = 1; 1555 | goto error; 1556 | } 1557 | if(__builtin_expect(u->rst.ptr > 253, 0)) { 1558 | u->rst.error = 2; 1559 | goto error; 1560 | } 1561 | #endif 1562 | u->rst.ptr += 2; 1563 | } 1564 | break; 1565 | case 0x67: /* ROT2r */ 1566 | __asm__("evaluxn_67_ROT2r:"); 1567 | { 1568 | Uint8 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]; 1569 | u->rst.dat[u->rst.ptr - 6] = d; 1570 | u->rst.dat[u->rst.ptr - 5] = c; 1571 | u->rst.dat[u->rst.ptr - 4] = b; 1572 | u->rst.dat[u->rst.ptr - 3] = a; 1573 | u->rst.dat[u->rst.ptr - 2] = f; 1574 | u->rst.dat[u->rst.ptr - 1] = e; 1575 | #ifndef NO_STACK_CHECKS 1576 | if(__builtin_expect(u->rst.ptr < 6, 0)) { 1577 | u->rst.error = 1; 1578 | goto error; 1579 | } 1580 | #endif 1581 | } 1582 | break; 1583 | case 0x68: /* EQU2r */ 1584 | __asm__("evaluxn_68_EQU2r:"); 1585 | { 1586 | Uint16 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)); 1587 | u->rst.dat[u->rst.ptr - 4] = b == a; 1588 | #ifndef NO_STACK_CHECKS 1589 | if(__builtin_expect(u->rst.ptr < 4, 0)) { 1590 | u->rst.error = 1; 1591 | goto error; 1592 | } 1593 | #endif 1594 | u->rst.ptr -= 3; 1595 | } 1596 | break; 1597 | case 0x69: /* NEQ2r */ 1598 | __asm__("evaluxn_69_NEQ2r:"); 1599 | { 1600 | Uint16 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)); 1601 | u->rst.dat[u->rst.ptr - 4] = b != a; 1602 | #ifndef NO_STACK_CHECKS 1603 | if(__builtin_expect(u->rst.ptr < 4, 0)) { 1604 | u->rst.error = 1; 1605 | goto error; 1606 | } 1607 | #endif 1608 | u->rst.ptr -= 3; 1609 | } 1610 | break; 1611 | case 0x6a: /* GTH2r */ 1612 | __asm__("evaluxn_6a_GTH2r:"); 1613 | { 1614 | Uint16 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)); 1615 | u->rst.dat[u->rst.ptr - 4] = b > a; 1616 | #ifndef NO_STACK_CHECKS 1617 | if(__builtin_expect(u->rst.ptr < 4, 0)) { 1618 | u->rst.error = 1; 1619 | goto error; 1620 | } 1621 | #endif 1622 | u->rst.ptr -= 3; 1623 | } 1624 | break; 1625 | case 0x6b: /* LTH2r */ 1626 | __asm__("evaluxn_6b_LTH2r:"); 1627 | { 1628 | Uint16 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)); 1629 | u->rst.dat[u->rst.ptr - 4] = b < a; 1630 | #ifndef NO_STACK_CHECKS 1631 | if(__builtin_expect(u->rst.ptr < 4, 0)) { 1632 | u->rst.error = 1; 1633 | goto error; 1634 | } 1635 | #endif 1636 | u->rst.ptr -= 3; 1637 | } 1638 | break; 1639 | case 0x6c: /* JMP2r */ 1640 | __asm__("evaluxn_6c_JMP2r:"); 1641 | { 1642 | u->ram.ptr = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)); 1643 | #ifndef NO_STACK_CHECKS 1644 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 1645 | u->rst.error = 1; 1646 | goto error; 1647 | } 1648 | #endif 1649 | u->rst.ptr -= 2; 1650 | } 1651 | break; 1652 | case 0x6d: /* JCN2r */ 1653 | __asm__("evaluxn_6d_JCN2r:"); 1654 | { 1655 | Uint16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)); 1656 | if(u->rst.dat[u->rst.ptr - 3]) u->ram.ptr = a; 1657 | #ifndef NO_STACK_CHECKS 1658 | if(__builtin_expect(u->rst.ptr < 3, 0)) { 1659 | u->rst.error = 1; 1660 | goto error; 1661 | } 1662 | #endif 1663 | u->rst.ptr -= 3; 1664 | } 1665 | break; 1666 | case 0x6e: /* JSR2r */ 1667 | __asm__("evaluxn_6e_JSR2r:"); 1668 | { 1669 | u->wst.dat[u->wst.ptr] = u->ram.ptr >> 8; 1670 | u->wst.dat[u->wst.ptr + 1] = u->ram.ptr & 0xff; 1671 | u->ram.ptr = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)); 1672 | #ifndef NO_STACK_CHECKS 1673 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 1674 | u->rst.error = 1; 1675 | goto error; 1676 | } 1677 | #endif 1678 | u->rst.ptr -= 2; 1679 | #ifndef NO_STACK_CHECKS 1680 | if(__builtin_expect(u->wst.ptr > 253, 0)) { 1681 | u->wst.error = 2; 1682 | goto error; 1683 | } 1684 | #endif 1685 | u->wst.ptr += 2; 1686 | } 1687 | break; 1688 | case 0x6f: /* STH2r */ 1689 | __asm__("evaluxn_6f_STH2r:"); 1690 | { 1691 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 1692 | u->wst.dat[u->wst.ptr] = b; 1693 | u->wst.dat[u->wst.ptr + 1] = a; 1694 | #ifndef NO_STACK_CHECKS 1695 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 1696 | u->rst.error = 1; 1697 | goto error; 1698 | } 1699 | #endif 1700 | u->rst.ptr -= 2; 1701 | #ifndef NO_STACK_CHECKS 1702 | if(__builtin_expect(u->wst.ptr > 253, 0)) { 1703 | u->wst.error = 2; 1704 | goto error; 1705 | } 1706 | #endif 1707 | u->wst.ptr += 2; 1708 | } 1709 | break; 1710 | case 0x70: /* LDZ2r */ 1711 | __asm__("evaluxn_70_LDZ2r:"); 1712 | { 1713 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 1714 | u->rst.dat[u->rst.ptr - 1] = mempeek8(u->ram.dat, a); 1715 | u->rst.dat[u->rst.ptr] = mempeek8(u->ram.dat, a + 1); 1716 | #ifndef NO_STACK_CHECKS 1717 | if(__builtin_expect(u->rst.ptr < 1, 0)) { 1718 | u->rst.error = 1; 1719 | goto error; 1720 | } 1721 | if(__builtin_expect(u->rst.ptr > 254, 0)) { 1722 | u->rst.error = 2; 1723 | goto error; 1724 | } 1725 | #endif 1726 | u->rst.ptr += 1; 1727 | } 1728 | break; 1729 | case 0x71: /* STZ2r */ 1730 | __asm__("evaluxn_71_STZ2r:"); 1731 | { 1732 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 1733 | Uint16 b = (u->rst.dat[u->rst.ptr - 2] | (u->rst.dat[u->rst.ptr - 3] << 8)); 1734 | mempoke16(u->ram.dat, a, b); 1735 | #ifndef NO_STACK_CHECKS 1736 | if(__builtin_expect(u->rst.ptr < 3, 0)) { 1737 | u->rst.error = 1; 1738 | goto error; 1739 | } 1740 | #endif 1741 | u->rst.ptr -= 3; 1742 | } 1743 | break; 1744 | case 0x72: /* LDR2r */ 1745 | __asm__("evaluxn_72_LDR2r:"); 1746 | { 1747 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 1748 | u->rst.dat[u->rst.ptr - 1] = mempeek8(u->ram.dat, u->ram.ptr + (Sint8)a); 1749 | u->rst.dat[u->rst.ptr] = mempeek8(u->ram.dat, u->ram.ptr + (Sint8)a + 1); 1750 | #ifndef NO_STACK_CHECKS 1751 | if(__builtin_expect(u->rst.ptr < 1, 0)) { 1752 | u->rst.error = 1; 1753 | goto error; 1754 | } 1755 | if(__builtin_expect(u->rst.ptr > 254, 0)) { 1756 | u->rst.error = 2; 1757 | goto error; 1758 | } 1759 | #endif 1760 | u->rst.ptr += 1; 1761 | } 1762 | break; 1763 | case 0x73: /* STR2r */ 1764 | __asm__("evaluxn_73_STR2r:"); 1765 | { 1766 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 1767 | Uint16 b = (u->rst.dat[u->rst.ptr - 2] | (u->rst.dat[u->rst.ptr - 3] << 8)); 1768 | mempoke16(u->ram.dat, u->ram.ptr + (Sint8)a, b); 1769 | #ifndef NO_STACK_CHECKS 1770 | if(__builtin_expect(u->rst.ptr < 3, 0)) { 1771 | u->rst.error = 1; 1772 | goto error; 1773 | } 1774 | #endif 1775 | u->rst.ptr -= 3; 1776 | } 1777 | break; 1778 | case 0x74: /* LDA2r */ 1779 | __asm__("evaluxn_74_LDA2r:"); 1780 | { 1781 | Uint16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)); 1782 | u->rst.dat[u->rst.ptr - 2] = mempeek8(u->ram.dat, a); 1783 | u->rst.dat[u->rst.ptr - 1] = mempeek8(u->ram.dat, a + 1); 1784 | #ifndef NO_STACK_CHECKS 1785 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 1786 | u->rst.error = 1; 1787 | goto error; 1788 | } 1789 | #endif 1790 | } 1791 | break; 1792 | case 0x75: /* STA2r */ 1793 | __asm__("evaluxn_75_STA2r:"); 1794 | { 1795 | Uint16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)); 1796 | Uint16 b = (u->rst.dat[u->rst.ptr - 3] | (u->rst.dat[u->rst.ptr - 4] << 8)); 1797 | mempoke16(u->ram.dat, a, b); 1798 | #ifndef NO_STACK_CHECKS 1799 | if(__builtin_expect(u->rst.ptr < 4, 0)) { 1800 | u->rst.error = 1; 1801 | goto error; 1802 | } 1803 | #endif 1804 | u->rst.ptr -= 4; 1805 | } 1806 | break; 1807 | case 0x76: /* DEI2r */ 1808 | __asm__("evaluxn_76_DEI2r:"); 1809 | { 1810 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 1811 | u->rst.dat[u->rst.ptr - 1] = devpeek8(&u->dev[a >> 4], a); 1812 | u->rst.dat[u->rst.ptr] = devpeek8(&u->dev[a >> 4], a + 1); 1813 | #ifndef NO_STACK_CHECKS 1814 | if(__builtin_expect(u->rst.ptr < 1, 0)) { 1815 | u->rst.error = 1; 1816 | goto error; 1817 | } 1818 | if(__builtin_expect(u->rst.ptr > 254, 0)) { 1819 | u->rst.error = 2; 1820 | goto error; 1821 | } 1822 | #endif 1823 | u->rst.ptr += 1; 1824 | } 1825 | break; 1826 | case 0x77: /* DEO2r */ 1827 | __asm__("evaluxn_77_DEO2r:"); 1828 | { 1829 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 1830 | Uint16 b = (u->rst.dat[u->rst.ptr - 2] | (u->rst.dat[u->rst.ptr - 3] << 8)); 1831 | devpoke16(&u->dev[a >> 4], a, b); 1832 | #ifndef NO_STACK_CHECKS 1833 | if(__builtin_expect(u->rst.ptr < 3, 0)) { 1834 | u->rst.error = 1; 1835 | goto error; 1836 | } 1837 | #endif 1838 | u->rst.ptr -= 3; 1839 | } 1840 | break; 1841 | case 0x78: /* ADD2r */ 1842 | __asm__("evaluxn_78_ADD2r:"); 1843 | { 1844 | Uint16 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)); 1845 | u->rst.dat[u->rst.ptr - 4] = (b + a) >> 8; 1846 | u->rst.dat[u->rst.ptr - 3] = (b + a) & 0xff; 1847 | #ifndef NO_STACK_CHECKS 1848 | if(__builtin_expect(u->rst.ptr < 4, 0)) { 1849 | u->rst.error = 1; 1850 | goto error; 1851 | } 1852 | #endif 1853 | u->rst.ptr -= 2; 1854 | } 1855 | break; 1856 | case 0x79: /* SUB2r */ 1857 | __asm__("evaluxn_79_SUB2r:"); 1858 | { 1859 | Uint16 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)); 1860 | u->rst.dat[u->rst.ptr - 4] = (b - a) >> 8; 1861 | u->rst.dat[u->rst.ptr - 3] = (b - a) & 0xff; 1862 | #ifndef NO_STACK_CHECKS 1863 | if(__builtin_expect(u->rst.ptr < 4, 0)) { 1864 | u->rst.error = 1; 1865 | goto error; 1866 | } 1867 | #endif 1868 | u->rst.ptr -= 2; 1869 | } 1870 | break; 1871 | case 0x7a: /* MUL2r */ 1872 | __asm__("evaluxn_7a_MUL2r:"); 1873 | { 1874 | Uint16 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)); 1875 | u->rst.dat[u->rst.ptr - 4] = (b * a) >> 8; 1876 | u->rst.dat[u->rst.ptr - 3] = (b * a) & 0xff; 1877 | #ifndef NO_STACK_CHECKS 1878 | if(__builtin_expect(u->rst.ptr < 4, 0)) { 1879 | u->rst.error = 1; 1880 | goto error; 1881 | } 1882 | #endif 1883 | u->rst.ptr -= 2; 1884 | } 1885 | break; 1886 | case 0x7b: /* DIV2r */ 1887 | __asm__("evaluxn_7b_DIV2r:"); 1888 | { 1889 | Uint16 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)); 1890 | if(a == 0) { 1891 | u->rst.error = 3; 1892 | #ifndef NO_STACK_CHECKS 1893 | goto error; 1894 | #endif 1895 | a = 1; 1896 | } 1897 | u->rst.dat[u->rst.ptr - 4] = (b / a) >> 8; 1898 | u->rst.dat[u->rst.ptr - 3] = (b / a) & 0xff; 1899 | #ifndef NO_STACK_CHECKS 1900 | if(__builtin_expect(u->rst.ptr < 4, 0)) { 1901 | u->rst.error = 1; 1902 | goto error; 1903 | } 1904 | #endif 1905 | u->rst.ptr -= 2; 1906 | } 1907 | break; 1908 | case 0x7c: /* AND2r */ 1909 | __asm__("evaluxn_7c_AND2r:"); 1910 | { 1911 | Uint8 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]; 1912 | u->rst.dat[u->rst.ptr - 4] = d & b; 1913 | u->rst.dat[u->rst.ptr - 3] = c & a; 1914 | #ifndef NO_STACK_CHECKS 1915 | if(__builtin_expect(u->rst.ptr < 4, 0)) { 1916 | u->rst.error = 1; 1917 | goto error; 1918 | } 1919 | #endif 1920 | u->rst.ptr -= 2; 1921 | } 1922 | break; 1923 | case 0x7d: /* ORA2r */ 1924 | __asm__("evaluxn_7d_ORA2r:"); 1925 | { 1926 | Uint8 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]; 1927 | u->rst.dat[u->rst.ptr - 4] = d | b; 1928 | u->rst.dat[u->rst.ptr - 3] = c | a; 1929 | #ifndef NO_STACK_CHECKS 1930 | if(__builtin_expect(u->rst.ptr < 4, 0)) { 1931 | u->rst.error = 1; 1932 | goto error; 1933 | } 1934 | #endif 1935 | u->rst.ptr -= 2; 1936 | } 1937 | break; 1938 | case 0x7e: /* EOR2r */ 1939 | __asm__("evaluxn_7e_EOR2r:"); 1940 | { 1941 | Uint8 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]; 1942 | u->rst.dat[u->rst.ptr - 4] = d ^ b; 1943 | u->rst.dat[u->rst.ptr - 3] = c ^ a; 1944 | #ifndef NO_STACK_CHECKS 1945 | if(__builtin_expect(u->rst.ptr < 4, 0)) { 1946 | u->rst.error = 1; 1947 | goto error; 1948 | } 1949 | #endif 1950 | u->rst.ptr -= 2; 1951 | } 1952 | break; 1953 | case 0x7f: /* SFT2r */ 1954 | __asm__("evaluxn_7f_SFT2r:"); 1955 | { 1956 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 1957 | Uint16 b = (u->rst.dat[u->rst.ptr - 2] | (u->rst.dat[u->rst.ptr - 3] << 8)); 1958 | u->rst.dat[u->rst.ptr - 3] = (b >> (a & 0x0f) << ((a & 0xf0) >> 4)) >> 8; 1959 | u->rst.dat[u->rst.ptr - 2] = (b >> (a & 0x0f) << ((a & 0xf0) >> 4)) & 0xff; 1960 | #ifndef NO_STACK_CHECKS 1961 | if(__builtin_expect(u->rst.ptr < 3, 0)) { 1962 | u->rst.error = 1; 1963 | goto error; 1964 | } 1965 | #endif 1966 | u->rst.ptr -= 1; 1967 | } 1968 | break; 1969 | case 0x83: /* POPk */ 1970 | __asm__("evaluxn_83_POPk:"); 1971 | { 1972 | u->wst.dat[u->wst.ptr - 1]; 1973 | #ifndef NO_STACK_CHECKS 1974 | if(__builtin_expect(u->wst.ptr < 1, 0)) { 1975 | u->wst.error = 1; 1976 | goto error; 1977 | } 1978 | #endif 1979 | } 1980 | break; 1981 | case 0x84: /* DUPk */ 1982 | __asm__("evaluxn_84_DUPk:"); 1983 | { 1984 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 1985 | u->wst.dat[u->wst.ptr] = a; 1986 | u->wst.dat[u->wst.ptr + 1] = a; 1987 | #ifndef NO_STACK_CHECKS 1988 | if(__builtin_expect(u->wst.ptr < 1, 0)) { 1989 | u->wst.error = 1; 1990 | goto error; 1991 | } 1992 | if(__builtin_expect(u->wst.ptr > 253, 0)) { 1993 | u->wst.error = 2; 1994 | goto error; 1995 | } 1996 | #endif 1997 | u->wst.ptr += 2; 1998 | } 1999 | break; 2000 | case 0x85: /* SWPk */ 2001 | __asm__("evaluxn_85_SWPk:"); 2002 | { 2003 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 2004 | u->wst.dat[u->wst.ptr] = a; 2005 | u->wst.dat[u->wst.ptr + 1] = b; 2006 | #ifndef NO_STACK_CHECKS 2007 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 2008 | u->wst.error = 1; 2009 | goto error; 2010 | } 2011 | if(__builtin_expect(u->wst.ptr > 253, 0)) { 2012 | u->wst.error = 2; 2013 | goto error; 2014 | } 2015 | #endif 2016 | u->wst.ptr += 2; 2017 | } 2018 | break; 2019 | case 0x86: /* OVRk */ 2020 | __asm__("evaluxn_86_OVRk:"); 2021 | { 2022 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 2023 | u->wst.dat[u->wst.ptr] = b; 2024 | u->wst.dat[u->wst.ptr + 1] = a; 2025 | u->wst.dat[u->wst.ptr + 2] = b; 2026 | #ifndef NO_STACK_CHECKS 2027 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 2028 | u->wst.error = 1; 2029 | goto error; 2030 | } 2031 | if(__builtin_expect(u->wst.ptr > 252, 0)) { 2032 | u->wst.error = 2; 2033 | goto error; 2034 | } 2035 | #endif 2036 | u->wst.ptr += 3; 2037 | } 2038 | break; 2039 | case 0x87: /* ROTk */ 2040 | __asm__("evaluxn_87_ROTk:"); 2041 | { 2042 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2], c = u->wst.dat[u->wst.ptr - 3]; 2043 | u->wst.dat[u->wst.ptr] = b; 2044 | u->wst.dat[u->wst.ptr + 1] = a; 2045 | u->wst.dat[u->wst.ptr + 2] = c; 2046 | #ifndef NO_STACK_CHECKS 2047 | if(__builtin_expect(u->wst.ptr < 3, 0)) { 2048 | u->wst.error = 1; 2049 | goto error; 2050 | } 2051 | if(__builtin_expect(u->wst.ptr > 252, 0)) { 2052 | u->wst.error = 2; 2053 | goto error; 2054 | } 2055 | #endif 2056 | u->wst.ptr += 3; 2057 | } 2058 | break; 2059 | case 0x88: /* EQUk */ 2060 | __asm__("evaluxn_88_EQUk:"); 2061 | { 2062 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 2063 | u->wst.dat[u->wst.ptr] = b == a; 2064 | #ifndef NO_STACK_CHECKS 2065 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 2066 | u->wst.error = 1; 2067 | goto error; 2068 | } 2069 | if(__builtin_expect(u->wst.ptr > 254, 0)) { 2070 | u->wst.error = 2; 2071 | goto error; 2072 | } 2073 | #endif 2074 | u->wst.ptr += 1; 2075 | } 2076 | break; 2077 | case 0x89: /* NEQk */ 2078 | __asm__("evaluxn_89_NEQk:"); 2079 | { 2080 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 2081 | u->wst.dat[u->wst.ptr] = b != a; 2082 | #ifndef NO_STACK_CHECKS 2083 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 2084 | u->wst.error = 1; 2085 | goto error; 2086 | } 2087 | if(__builtin_expect(u->wst.ptr > 254, 0)) { 2088 | u->wst.error = 2; 2089 | goto error; 2090 | } 2091 | #endif 2092 | u->wst.ptr += 1; 2093 | } 2094 | break; 2095 | case 0x8a: /* GTHk */ 2096 | __asm__("evaluxn_8a_GTHk:"); 2097 | { 2098 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 2099 | u->wst.dat[u->wst.ptr] = b > a; 2100 | #ifndef NO_STACK_CHECKS 2101 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 2102 | u->wst.error = 1; 2103 | goto error; 2104 | } 2105 | if(__builtin_expect(u->wst.ptr > 254, 0)) { 2106 | u->wst.error = 2; 2107 | goto error; 2108 | } 2109 | #endif 2110 | u->wst.ptr += 1; 2111 | } 2112 | break; 2113 | case 0x8b: /* LTHk */ 2114 | __asm__("evaluxn_8b_LTHk:"); 2115 | { 2116 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 2117 | u->wst.dat[u->wst.ptr] = b < a; 2118 | #ifndef NO_STACK_CHECKS 2119 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 2120 | u->wst.error = 1; 2121 | goto error; 2122 | } 2123 | if(__builtin_expect(u->wst.ptr > 254, 0)) { 2124 | u->wst.error = 2; 2125 | goto error; 2126 | } 2127 | #endif 2128 | u->wst.ptr += 1; 2129 | } 2130 | break; 2131 | case 0x8c: /* JMPk */ 2132 | __asm__("evaluxn_8c_JMPk:"); 2133 | { 2134 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 2135 | u->ram.ptr += (Sint8)a; 2136 | #ifndef NO_STACK_CHECKS 2137 | if(__builtin_expect(u->wst.ptr < 1, 0)) { 2138 | u->wst.error = 1; 2139 | goto error; 2140 | } 2141 | #endif 2142 | } 2143 | break; 2144 | case 0x8d: /* JCNk */ 2145 | __asm__("evaluxn_8d_JCNk:"); 2146 | { 2147 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 2148 | if(u->wst.dat[u->wst.ptr - 2]) u->ram.ptr += (Sint8)a; 2149 | #ifndef NO_STACK_CHECKS 2150 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 2151 | u->wst.error = 1; 2152 | goto error; 2153 | } 2154 | #endif 2155 | } 2156 | break; 2157 | case 0x8e: /* JSRk */ 2158 | __asm__("evaluxn_8e_JSRk:"); 2159 | { 2160 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 2161 | u->rst.dat[u->rst.ptr] = u->ram.ptr >> 8; 2162 | u->rst.dat[u->rst.ptr + 1] = u->ram.ptr & 0xff; 2163 | u->ram.ptr += (Sint8)a; 2164 | #ifndef NO_STACK_CHECKS 2165 | if(__builtin_expect(u->wst.ptr < 1, 0)) { 2166 | u->wst.error = 1; 2167 | goto error; 2168 | } 2169 | if(__builtin_expect(u->rst.ptr > 253, 0)) { 2170 | u->rst.error = 2; 2171 | goto error; 2172 | } 2173 | #endif 2174 | u->rst.ptr += 2; 2175 | } 2176 | break; 2177 | case 0x8f: /* STHk */ 2178 | __asm__("evaluxn_8f_STHk:"); 2179 | { 2180 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 2181 | u->rst.dat[u->rst.ptr] = a; 2182 | #ifndef NO_STACK_CHECKS 2183 | if(__builtin_expect(u->wst.ptr < 1, 0)) { 2184 | u->wst.error = 1; 2185 | goto error; 2186 | } 2187 | if(__builtin_expect(u->rst.ptr > 254, 0)) { 2188 | u->rst.error = 2; 2189 | goto error; 2190 | } 2191 | #endif 2192 | u->rst.ptr += 1; 2193 | } 2194 | break; 2195 | case 0x90: /* LDZk */ 2196 | __asm__("evaluxn_90_LDZk:"); 2197 | { 2198 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 2199 | u->wst.dat[u->wst.ptr] = mempeek8(u->ram.dat, a); 2200 | #ifndef NO_STACK_CHECKS 2201 | if(__builtin_expect(u->wst.ptr < 1, 0)) { 2202 | u->wst.error = 1; 2203 | goto error; 2204 | } 2205 | if(__builtin_expect(u->wst.ptr > 254, 0)) { 2206 | u->wst.error = 2; 2207 | goto error; 2208 | } 2209 | #endif 2210 | u->wst.ptr += 1; 2211 | } 2212 | break; 2213 | case 0x91: /* STZk */ 2214 | __asm__("evaluxn_91_STZk:"); 2215 | { 2216 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 2217 | Uint8 b = u->wst.dat[u->wst.ptr - 2]; 2218 | mempoke8(u->ram.dat, a, b); 2219 | #ifndef NO_STACK_CHECKS 2220 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 2221 | u->wst.error = 1; 2222 | goto error; 2223 | } 2224 | #endif 2225 | } 2226 | break; 2227 | case 0x92: /* LDRk */ 2228 | __asm__("evaluxn_92_LDRk:"); 2229 | { 2230 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 2231 | u->wst.dat[u->wst.ptr] = mempeek8(u->ram.dat, u->ram.ptr + (Sint8)a); 2232 | #ifndef NO_STACK_CHECKS 2233 | if(__builtin_expect(u->wst.ptr < 1, 0)) { 2234 | u->wst.error = 1; 2235 | goto error; 2236 | } 2237 | if(__builtin_expect(u->wst.ptr > 254, 0)) { 2238 | u->wst.error = 2; 2239 | goto error; 2240 | } 2241 | #endif 2242 | u->wst.ptr += 1; 2243 | } 2244 | break; 2245 | case 0x93: /* STRk */ 2246 | __asm__("evaluxn_93_STRk:"); 2247 | { 2248 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 2249 | Uint8 b = u->wst.dat[u->wst.ptr - 2]; 2250 | mempoke8(u->ram.dat, u->ram.ptr + (Sint8)a, b); 2251 | #ifndef NO_STACK_CHECKS 2252 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 2253 | u->wst.error = 1; 2254 | goto error; 2255 | } 2256 | #endif 2257 | } 2258 | break; 2259 | case 0x94: /* LDAk */ 2260 | __asm__("evaluxn_94_LDAk:"); 2261 | { 2262 | Uint16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)); 2263 | u->wst.dat[u->wst.ptr] = mempeek8(u->ram.dat, a); 2264 | #ifndef NO_STACK_CHECKS 2265 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 2266 | u->wst.error = 1; 2267 | goto error; 2268 | } 2269 | if(__builtin_expect(u->wst.ptr > 254, 0)) { 2270 | u->wst.error = 2; 2271 | goto error; 2272 | } 2273 | #endif 2274 | u->wst.ptr += 1; 2275 | } 2276 | break; 2277 | case 0x95: /* STAk */ 2278 | __asm__("evaluxn_95_STAk:"); 2279 | { 2280 | Uint16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)); 2281 | Uint8 b = u->wst.dat[u->wst.ptr - 3]; 2282 | mempoke8(u->ram.dat, a, b); 2283 | #ifndef NO_STACK_CHECKS 2284 | if(__builtin_expect(u->wst.ptr < 3, 0)) { 2285 | u->wst.error = 1; 2286 | goto error; 2287 | } 2288 | #endif 2289 | } 2290 | break; 2291 | case 0x96: /* DEIk */ 2292 | __asm__("evaluxn_96_DEIk:"); 2293 | { 2294 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 2295 | u->wst.dat[u->wst.ptr] = devpeek8(&u->dev[a >> 4], a); 2296 | #ifndef NO_STACK_CHECKS 2297 | if(__builtin_expect(u->wst.ptr < 1, 0)) { 2298 | u->wst.error = 1; 2299 | goto error; 2300 | } 2301 | if(__builtin_expect(u->wst.ptr > 254, 0)) { 2302 | u->wst.error = 2; 2303 | goto error; 2304 | } 2305 | #endif 2306 | u->wst.ptr += 1; 2307 | } 2308 | break; 2309 | case 0x97: /* DEOk */ 2310 | __asm__("evaluxn_97_DEOk:"); 2311 | { 2312 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 2313 | devpoke8(&u->dev[a >> 4], a, b); 2314 | #ifndef NO_STACK_CHECKS 2315 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 2316 | u->wst.error = 1; 2317 | goto error; 2318 | } 2319 | #endif 2320 | } 2321 | break; 2322 | case 0x98: /* ADDk */ 2323 | __asm__("evaluxn_98_ADDk:"); 2324 | { 2325 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 2326 | u->wst.dat[u->wst.ptr] = b + a; 2327 | #ifndef NO_STACK_CHECKS 2328 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 2329 | u->wst.error = 1; 2330 | goto error; 2331 | } 2332 | if(__builtin_expect(u->wst.ptr > 254, 0)) { 2333 | u->wst.error = 2; 2334 | goto error; 2335 | } 2336 | #endif 2337 | u->wst.ptr += 1; 2338 | } 2339 | break; 2340 | case 0x99: /* SUBk */ 2341 | __asm__("evaluxn_99_SUBk:"); 2342 | { 2343 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 2344 | u->wst.dat[u->wst.ptr] = b - a; 2345 | #ifndef NO_STACK_CHECKS 2346 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 2347 | u->wst.error = 1; 2348 | goto error; 2349 | } 2350 | if(__builtin_expect(u->wst.ptr > 254, 0)) { 2351 | u->wst.error = 2; 2352 | goto error; 2353 | } 2354 | #endif 2355 | u->wst.ptr += 1; 2356 | } 2357 | break; 2358 | case 0x9a: /* MULk */ 2359 | __asm__("evaluxn_9a_MULk:"); 2360 | { 2361 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 2362 | u->wst.dat[u->wst.ptr] = b * a; 2363 | #ifndef NO_STACK_CHECKS 2364 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 2365 | u->wst.error = 1; 2366 | goto error; 2367 | } 2368 | if(__builtin_expect(u->wst.ptr > 254, 0)) { 2369 | u->wst.error = 2; 2370 | goto error; 2371 | } 2372 | #endif 2373 | u->wst.ptr += 1; 2374 | } 2375 | break; 2376 | case 0x9b: /* DIVk */ 2377 | __asm__("evaluxn_9b_DIVk:"); 2378 | { 2379 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 2380 | if(a == 0) { 2381 | u->wst.error = 3; 2382 | #ifndef NO_STACK_CHECKS 2383 | goto error; 2384 | #endif 2385 | a = 1; 2386 | } 2387 | u->wst.dat[u->wst.ptr] = b / a; 2388 | #ifndef NO_STACK_CHECKS 2389 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 2390 | u->wst.error = 1; 2391 | goto error; 2392 | } 2393 | if(__builtin_expect(u->wst.ptr > 254, 0)) { 2394 | u->wst.error = 2; 2395 | goto error; 2396 | } 2397 | #endif 2398 | u->wst.ptr += 1; 2399 | } 2400 | break; 2401 | case 0x9c: /* ANDk */ 2402 | __asm__("evaluxn_9c_ANDk:"); 2403 | { 2404 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 2405 | u->wst.dat[u->wst.ptr] = b & a; 2406 | #ifndef NO_STACK_CHECKS 2407 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 2408 | u->wst.error = 1; 2409 | goto error; 2410 | } 2411 | if(__builtin_expect(u->wst.ptr > 254, 0)) { 2412 | u->wst.error = 2; 2413 | goto error; 2414 | } 2415 | #endif 2416 | u->wst.ptr += 1; 2417 | } 2418 | break; 2419 | case 0x9d: /* ORAk */ 2420 | __asm__("evaluxn_9d_ORAk:"); 2421 | { 2422 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 2423 | u->wst.dat[u->wst.ptr] = b | a; 2424 | #ifndef NO_STACK_CHECKS 2425 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 2426 | u->wst.error = 1; 2427 | goto error; 2428 | } 2429 | if(__builtin_expect(u->wst.ptr > 254, 0)) { 2430 | u->wst.error = 2; 2431 | goto error; 2432 | } 2433 | #endif 2434 | u->wst.ptr += 1; 2435 | } 2436 | break; 2437 | case 0x9e: /* EORk */ 2438 | __asm__("evaluxn_9e_EORk:"); 2439 | { 2440 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 2441 | u->wst.dat[u->wst.ptr] = b ^ a; 2442 | #ifndef NO_STACK_CHECKS 2443 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 2444 | u->wst.error = 1; 2445 | goto error; 2446 | } 2447 | if(__builtin_expect(u->wst.ptr > 254, 0)) { 2448 | u->wst.error = 2; 2449 | goto error; 2450 | } 2451 | #endif 2452 | u->wst.ptr += 1; 2453 | } 2454 | break; 2455 | case 0x9f: /* SFTk */ 2456 | __asm__("evaluxn_9f_SFTk:"); 2457 | { 2458 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 2459 | u->wst.dat[u->wst.ptr] = b >> (a & 0x07) << ((a & 0x70) >> 4); 2460 | #ifndef NO_STACK_CHECKS 2461 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 2462 | u->wst.error = 1; 2463 | goto error; 2464 | } 2465 | if(__builtin_expect(u->wst.ptr > 254, 0)) { 2466 | u->wst.error = 2; 2467 | goto error; 2468 | } 2469 | #endif 2470 | u->wst.ptr += 1; 2471 | } 2472 | break; 2473 | case 0xa3: /* POP2k */ 2474 | __asm__("evaluxn_a3_POP2k:"); 2475 | { 2476 | (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)); 2477 | #ifndef NO_STACK_CHECKS 2478 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 2479 | u->wst.error = 1; 2480 | goto error; 2481 | } 2482 | #endif 2483 | } 2484 | break; 2485 | case 0xa4: /* DUP2k */ 2486 | __asm__("evaluxn_a4_DUP2k:"); 2487 | { 2488 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 2489 | u->wst.dat[u->wst.ptr] = b; 2490 | u->wst.dat[u->wst.ptr + 1] = a; 2491 | u->wst.dat[u->wst.ptr + 2] = b; 2492 | u->wst.dat[u->wst.ptr + 3] = a; 2493 | #ifndef NO_STACK_CHECKS 2494 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 2495 | u->wst.error = 1; 2496 | goto error; 2497 | } 2498 | if(__builtin_expect(u->wst.ptr > 251, 0)) { 2499 | u->wst.error = 2; 2500 | goto error; 2501 | } 2502 | #endif 2503 | u->wst.ptr += 4; 2504 | } 2505 | break; 2506 | case 0xa5: /* SWP2k */ 2507 | __asm__("evaluxn_a5_SWP2k:"); 2508 | { 2509 | Uint8 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]; 2510 | u->wst.dat[u->wst.ptr] = b; 2511 | u->wst.dat[u->wst.ptr + 1] = a; 2512 | u->wst.dat[u->wst.ptr + 2] = d; 2513 | u->wst.dat[u->wst.ptr + 3] = c; 2514 | #ifndef NO_STACK_CHECKS 2515 | if(__builtin_expect(u->wst.ptr < 4, 0)) { 2516 | u->wst.error = 1; 2517 | goto error; 2518 | } 2519 | if(__builtin_expect(u->wst.ptr > 251, 0)) { 2520 | u->wst.error = 2; 2521 | goto error; 2522 | } 2523 | #endif 2524 | u->wst.ptr += 4; 2525 | } 2526 | break; 2527 | case 0xa6: /* OVR2k */ 2528 | __asm__("evaluxn_a6_OVR2k:"); 2529 | { 2530 | Uint8 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]; 2531 | u->wst.dat[u->wst.ptr] = d; 2532 | u->wst.dat[u->wst.ptr + 1] = c; 2533 | u->wst.dat[u->wst.ptr + 2] = b; 2534 | u->wst.dat[u->wst.ptr + 3] = a; 2535 | u->wst.dat[u->wst.ptr + 4] = d; 2536 | u->wst.dat[u->wst.ptr + 5] = c; 2537 | #ifndef NO_STACK_CHECKS 2538 | if(__builtin_expect(u->wst.ptr < 4, 0)) { 2539 | u->wst.error = 1; 2540 | goto error; 2541 | } 2542 | if(__builtin_expect(u->wst.ptr > 249, 0)) { 2543 | u->wst.error = 2; 2544 | goto error; 2545 | } 2546 | #endif 2547 | u->wst.ptr += 6; 2548 | } 2549 | break; 2550 | case 0xa7: /* ROT2k */ 2551 | __asm__("evaluxn_a7_ROT2k:"); 2552 | { 2553 | Uint8 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]; 2554 | u->wst.dat[u->wst.ptr] = d; 2555 | u->wst.dat[u->wst.ptr + 1] = c; 2556 | u->wst.dat[u->wst.ptr + 2] = b; 2557 | u->wst.dat[u->wst.ptr + 3] = a; 2558 | u->wst.dat[u->wst.ptr + 4] = f; 2559 | u->wst.dat[u->wst.ptr + 5] = e; 2560 | #ifndef NO_STACK_CHECKS 2561 | if(__builtin_expect(u->wst.ptr < 6, 0)) { 2562 | u->wst.error = 1; 2563 | goto error; 2564 | } 2565 | if(__builtin_expect(u->wst.ptr > 249, 0)) { 2566 | u->wst.error = 2; 2567 | goto error; 2568 | } 2569 | #endif 2570 | u->wst.ptr += 6; 2571 | } 2572 | break; 2573 | case 0xa8: /* EQU2k */ 2574 | __asm__("evaluxn_a8_EQU2k:"); 2575 | { 2576 | Uint16 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)); 2577 | u->wst.dat[u->wst.ptr] = b == a; 2578 | #ifndef NO_STACK_CHECKS 2579 | if(__builtin_expect(u->wst.ptr < 4, 0)) { 2580 | u->wst.error = 1; 2581 | goto error; 2582 | } 2583 | if(__builtin_expect(u->wst.ptr > 254, 0)) { 2584 | u->wst.error = 2; 2585 | goto error; 2586 | } 2587 | #endif 2588 | u->wst.ptr += 1; 2589 | } 2590 | break; 2591 | case 0xa9: /* NEQ2k */ 2592 | __asm__("evaluxn_a9_NEQ2k:"); 2593 | { 2594 | Uint16 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)); 2595 | u->wst.dat[u->wst.ptr] = b != a; 2596 | #ifndef NO_STACK_CHECKS 2597 | if(__builtin_expect(u->wst.ptr < 4, 0)) { 2598 | u->wst.error = 1; 2599 | goto error; 2600 | } 2601 | if(__builtin_expect(u->wst.ptr > 254, 0)) { 2602 | u->wst.error = 2; 2603 | goto error; 2604 | } 2605 | #endif 2606 | u->wst.ptr += 1; 2607 | } 2608 | break; 2609 | case 0xaa: /* GTH2k */ 2610 | __asm__("evaluxn_aa_GTH2k:"); 2611 | { 2612 | Uint16 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)); 2613 | u->wst.dat[u->wst.ptr] = b > a; 2614 | #ifndef NO_STACK_CHECKS 2615 | if(__builtin_expect(u->wst.ptr < 4, 0)) { 2616 | u->wst.error = 1; 2617 | goto error; 2618 | } 2619 | if(__builtin_expect(u->wst.ptr > 254, 0)) { 2620 | u->wst.error = 2; 2621 | goto error; 2622 | } 2623 | #endif 2624 | u->wst.ptr += 1; 2625 | } 2626 | break; 2627 | case 0xab: /* LTH2k */ 2628 | __asm__("evaluxn_ab_LTH2k:"); 2629 | { 2630 | Uint16 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)); 2631 | u->wst.dat[u->wst.ptr] = b < a; 2632 | #ifndef NO_STACK_CHECKS 2633 | if(__builtin_expect(u->wst.ptr < 4, 0)) { 2634 | u->wst.error = 1; 2635 | goto error; 2636 | } 2637 | if(__builtin_expect(u->wst.ptr > 254, 0)) { 2638 | u->wst.error = 2; 2639 | goto error; 2640 | } 2641 | #endif 2642 | u->wst.ptr += 1; 2643 | } 2644 | break; 2645 | case 0xac: /* JMP2k */ 2646 | __asm__("evaluxn_ac_JMP2k:"); 2647 | { 2648 | u->ram.ptr = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)); 2649 | #ifndef NO_STACK_CHECKS 2650 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 2651 | u->wst.error = 1; 2652 | goto error; 2653 | } 2654 | #endif 2655 | } 2656 | break; 2657 | case 0xad: /* JCN2k */ 2658 | __asm__("evaluxn_ad_JCN2k:"); 2659 | { 2660 | Uint16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)); 2661 | if(u->wst.dat[u->wst.ptr - 3]) u->ram.ptr = a; 2662 | #ifndef NO_STACK_CHECKS 2663 | if(__builtin_expect(u->wst.ptr < 3, 0)) { 2664 | u->wst.error = 1; 2665 | goto error; 2666 | } 2667 | #endif 2668 | } 2669 | break; 2670 | case 0xae: /* JSR2k */ 2671 | __asm__("evaluxn_ae_JSR2k:"); 2672 | { 2673 | u->rst.dat[u->rst.ptr] = u->ram.ptr >> 8; 2674 | u->rst.dat[u->rst.ptr + 1] = u->ram.ptr & 0xff; 2675 | u->ram.ptr = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)); 2676 | #ifndef NO_STACK_CHECKS 2677 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 2678 | u->wst.error = 1; 2679 | goto error; 2680 | } 2681 | if(__builtin_expect(u->rst.ptr > 253, 0)) { 2682 | u->rst.error = 2; 2683 | goto error; 2684 | } 2685 | #endif 2686 | u->rst.ptr += 2; 2687 | } 2688 | break; 2689 | case 0xaf: /* STH2k */ 2690 | __asm__("evaluxn_af_STH2k:"); 2691 | { 2692 | Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 2693 | u->rst.dat[u->rst.ptr] = b; 2694 | u->rst.dat[u->rst.ptr + 1] = a; 2695 | #ifndef NO_STACK_CHECKS 2696 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 2697 | u->wst.error = 1; 2698 | goto error; 2699 | } 2700 | if(__builtin_expect(u->rst.ptr > 253, 0)) { 2701 | u->rst.error = 2; 2702 | goto error; 2703 | } 2704 | #endif 2705 | u->rst.ptr += 2; 2706 | } 2707 | break; 2708 | case 0xb0: /* LDZ2k */ 2709 | __asm__("evaluxn_b0_LDZ2k:"); 2710 | { 2711 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 2712 | u->wst.dat[u->wst.ptr] = mempeek8(u->ram.dat, a); 2713 | u->wst.dat[u->wst.ptr + 1] = mempeek8(u->ram.dat, a + 1); 2714 | #ifndef NO_STACK_CHECKS 2715 | if(__builtin_expect(u->wst.ptr < 1, 0)) { 2716 | u->wst.error = 1; 2717 | goto error; 2718 | } 2719 | if(__builtin_expect(u->wst.ptr > 253, 0)) { 2720 | u->wst.error = 2; 2721 | goto error; 2722 | } 2723 | #endif 2724 | u->wst.ptr += 2; 2725 | } 2726 | break; 2727 | case 0xb1: /* STZ2k */ 2728 | __asm__("evaluxn_b1_STZ2k:"); 2729 | { 2730 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 2731 | Uint16 b = (u->wst.dat[u->wst.ptr - 2] | (u->wst.dat[u->wst.ptr - 3] << 8)); 2732 | mempoke16(u->ram.dat, a, b); 2733 | #ifndef NO_STACK_CHECKS 2734 | if(__builtin_expect(u->wst.ptr < 3, 0)) { 2735 | u->wst.error = 1; 2736 | goto error; 2737 | } 2738 | #endif 2739 | } 2740 | break; 2741 | case 0xb2: /* LDR2k */ 2742 | __asm__("evaluxn_b2_LDR2k:"); 2743 | { 2744 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 2745 | u->wst.dat[u->wst.ptr] = mempeek8(u->ram.dat, u->ram.ptr + (Sint8)a); 2746 | u->wst.dat[u->wst.ptr + 1] = mempeek8(u->ram.dat, u->ram.ptr + (Sint8)a + 1); 2747 | #ifndef NO_STACK_CHECKS 2748 | if(__builtin_expect(u->wst.ptr < 1, 0)) { 2749 | u->wst.error = 1; 2750 | goto error; 2751 | } 2752 | if(__builtin_expect(u->wst.ptr > 253, 0)) { 2753 | u->wst.error = 2; 2754 | goto error; 2755 | } 2756 | #endif 2757 | u->wst.ptr += 2; 2758 | } 2759 | break; 2760 | case 0xb3: /* STR2k */ 2761 | __asm__("evaluxn_b3_STR2k:"); 2762 | { 2763 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 2764 | Uint16 b = (u->wst.dat[u->wst.ptr - 2] | (u->wst.dat[u->wst.ptr - 3] << 8)); 2765 | mempoke16(u->ram.dat, u->ram.ptr + (Sint8)a, b); 2766 | #ifndef NO_STACK_CHECKS 2767 | if(__builtin_expect(u->wst.ptr < 3, 0)) { 2768 | u->wst.error = 1; 2769 | goto error; 2770 | } 2771 | #endif 2772 | } 2773 | break; 2774 | case 0xb4: /* LDA2k */ 2775 | __asm__("evaluxn_b4_LDA2k:"); 2776 | { 2777 | Uint16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)); 2778 | u->wst.dat[u->wst.ptr] = mempeek8(u->ram.dat, a); 2779 | u->wst.dat[u->wst.ptr + 1] = mempeek8(u->ram.dat, a + 1); 2780 | #ifndef NO_STACK_CHECKS 2781 | if(__builtin_expect(u->wst.ptr < 2, 0)) { 2782 | u->wst.error = 1; 2783 | goto error; 2784 | } 2785 | if(__builtin_expect(u->wst.ptr > 253, 0)) { 2786 | u->wst.error = 2; 2787 | goto error; 2788 | } 2789 | #endif 2790 | u->wst.ptr += 2; 2791 | } 2792 | break; 2793 | case 0xb5: /* STA2k */ 2794 | __asm__("evaluxn_b5_STA2k:"); 2795 | { 2796 | Uint16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)); 2797 | Uint16 b = (u->wst.dat[u->wst.ptr - 3] | (u->wst.dat[u->wst.ptr - 4] << 8)); 2798 | mempoke16(u->ram.dat, a, b); 2799 | #ifndef NO_STACK_CHECKS 2800 | if(__builtin_expect(u->wst.ptr < 4, 0)) { 2801 | u->wst.error = 1; 2802 | goto error; 2803 | } 2804 | #endif 2805 | } 2806 | break; 2807 | case 0xb6: /* DEI2k */ 2808 | __asm__("evaluxn_b6_DEI2k:"); 2809 | { 2810 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 2811 | u->wst.dat[u->wst.ptr] = devpeek8(&u->dev[a >> 4], a); 2812 | u->wst.dat[u->wst.ptr + 1] = devpeek8(&u->dev[a >> 4], a + 1); 2813 | #ifndef NO_STACK_CHECKS 2814 | if(__builtin_expect(u->wst.ptr < 1, 0)) { 2815 | u->wst.error = 1; 2816 | goto error; 2817 | } 2818 | if(__builtin_expect(u->wst.ptr > 253, 0)) { 2819 | u->wst.error = 2; 2820 | goto error; 2821 | } 2822 | #endif 2823 | u->wst.ptr += 2; 2824 | } 2825 | break; 2826 | case 0xb7: /* DEO2k */ 2827 | __asm__("evaluxn_b7_DEO2k:"); 2828 | { 2829 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 2830 | Uint16 b = (u->wst.dat[u->wst.ptr - 2] | (u->wst.dat[u->wst.ptr - 3] << 8)); 2831 | devpoke16(&u->dev[a >> 4], a, b); 2832 | #ifndef NO_STACK_CHECKS 2833 | if(__builtin_expect(u->wst.ptr < 3, 0)) { 2834 | u->wst.error = 1; 2835 | goto error; 2836 | } 2837 | #endif 2838 | } 2839 | break; 2840 | case 0xb8: /* ADD2k */ 2841 | __asm__("evaluxn_b8_ADD2k:"); 2842 | { 2843 | Uint16 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)); 2844 | u->wst.dat[u->wst.ptr] = (b + a) >> 8; 2845 | u->wst.dat[u->wst.ptr + 1] = (b + a) & 0xff; 2846 | #ifndef NO_STACK_CHECKS 2847 | if(__builtin_expect(u->wst.ptr < 4, 0)) { 2848 | u->wst.error = 1; 2849 | goto error; 2850 | } 2851 | if(__builtin_expect(u->wst.ptr > 253, 0)) { 2852 | u->wst.error = 2; 2853 | goto error; 2854 | } 2855 | #endif 2856 | u->wst.ptr += 2; 2857 | } 2858 | break; 2859 | case 0xb9: /* SUB2k */ 2860 | __asm__("evaluxn_b9_SUB2k:"); 2861 | { 2862 | Uint16 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)); 2863 | u->wst.dat[u->wst.ptr] = (b - a) >> 8; 2864 | u->wst.dat[u->wst.ptr + 1] = (b - a) & 0xff; 2865 | #ifndef NO_STACK_CHECKS 2866 | if(__builtin_expect(u->wst.ptr < 4, 0)) { 2867 | u->wst.error = 1; 2868 | goto error; 2869 | } 2870 | if(__builtin_expect(u->wst.ptr > 253, 0)) { 2871 | u->wst.error = 2; 2872 | goto error; 2873 | } 2874 | #endif 2875 | u->wst.ptr += 2; 2876 | } 2877 | break; 2878 | case 0xba: /* MUL2k */ 2879 | __asm__("evaluxn_ba_MUL2k:"); 2880 | { 2881 | Uint16 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)); 2882 | u->wst.dat[u->wst.ptr] = (b * a) >> 8; 2883 | u->wst.dat[u->wst.ptr + 1] = (b * a) & 0xff; 2884 | #ifndef NO_STACK_CHECKS 2885 | if(__builtin_expect(u->wst.ptr < 4, 0)) { 2886 | u->wst.error = 1; 2887 | goto error; 2888 | } 2889 | if(__builtin_expect(u->wst.ptr > 253, 0)) { 2890 | u->wst.error = 2; 2891 | goto error; 2892 | } 2893 | #endif 2894 | u->wst.ptr += 2; 2895 | } 2896 | break; 2897 | case 0xbb: /* DIV2k */ 2898 | __asm__("evaluxn_bb_DIV2k:"); 2899 | { 2900 | Uint16 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)); 2901 | if(a == 0) { 2902 | u->wst.error = 3; 2903 | #ifndef NO_STACK_CHECKS 2904 | goto error; 2905 | #endif 2906 | a = 1; 2907 | } 2908 | u->wst.dat[u->wst.ptr] = (b / a) >> 8; 2909 | u->wst.dat[u->wst.ptr + 1] = (b / a) & 0xff; 2910 | #ifndef NO_STACK_CHECKS 2911 | if(__builtin_expect(u->wst.ptr < 4, 0)) { 2912 | u->wst.error = 1; 2913 | goto error; 2914 | } 2915 | if(__builtin_expect(u->wst.ptr > 253, 0)) { 2916 | u->wst.error = 2; 2917 | goto error; 2918 | } 2919 | #endif 2920 | u->wst.ptr += 2; 2921 | } 2922 | break; 2923 | case 0xbc: /* AND2k */ 2924 | __asm__("evaluxn_bc_AND2k:"); 2925 | { 2926 | Uint8 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]; 2927 | u->wst.dat[u->wst.ptr] = d & b; 2928 | u->wst.dat[u->wst.ptr + 1] = c & a; 2929 | #ifndef NO_STACK_CHECKS 2930 | if(__builtin_expect(u->wst.ptr < 4, 0)) { 2931 | u->wst.error = 1; 2932 | goto error; 2933 | } 2934 | if(__builtin_expect(u->wst.ptr > 253, 0)) { 2935 | u->wst.error = 2; 2936 | goto error; 2937 | } 2938 | #endif 2939 | u->wst.ptr += 2; 2940 | } 2941 | break; 2942 | case 0xbd: /* ORA2k */ 2943 | __asm__("evaluxn_bd_ORA2k:"); 2944 | { 2945 | Uint8 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]; 2946 | u->wst.dat[u->wst.ptr] = d | b; 2947 | u->wst.dat[u->wst.ptr + 1] = c | a; 2948 | #ifndef NO_STACK_CHECKS 2949 | if(__builtin_expect(u->wst.ptr < 4, 0)) { 2950 | u->wst.error = 1; 2951 | goto error; 2952 | } 2953 | if(__builtin_expect(u->wst.ptr > 253, 0)) { 2954 | u->wst.error = 2; 2955 | goto error; 2956 | } 2957 | #endif 2958 | u->wst.ptr += 2; 2959 | } 2960 | break; 2961 | case 0xbe: /* EOR2k */ 2962 | __asm__("evaluxn_be_EOR2k:"); 2963 | { 2964 | Uint8 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]; 2965 | u->wst.dat[u->wst.ptr] = d ^ b; 2966 | u->wst.dat[u->wst.ptr + 1] = c ^ a; 2967 | #ifndef NO_STACK_CHECKS 2968 | if(__builtin_expect(u->wst.ptr < 4, 0)) { 2969 | u->wst.error = 1; 2970 | goto error; 2971 | } 2972 | if(__builtin_expect(u->wst.ptr > 253, 0)) { 2973 | u->wst.error = 2; 2974 | goto error; 2975 | } 2976 | #endif 2977 | u->wst.ptr += 2; 2978 | } 2979 | break; 2980 | case 0xbf: /* SFT2k */ 2981 | __asm__("evaluxn_bf_SFT2k:"); 2982 | { 2983 | Uint8 a = u->wst.dat[u->wst.ptr - 1]; 2984 | Uint16 b = (u->wst.dat[u->wst.ptr - 2] | (u->wst.dat[u->wst.ptr - 3] << 8)); 2985 | u->wst.dat[u->wst.ptr] = (b >> (a & 0x0f) << ((a & 0xf0) >> 4)) >> 8; 2986 | u->wst.dat[u->wst.ptr + 1] = (b >> (a & 0x0f) << ((a & 0xf0) >> 4)) & 0xff; 2987 | #ifndef NO_STACK_CHECKS 2988 | if(__builtin_expect(u->wst.ptr < 3, 0)) { 2989 | u->wst.error = 1; 2990 | goto error; 2991 | } 2992 | if(__builtin_expect(u->wst.ptr > 253, 0)) { 2993 | u->wst.error = 2; 2994 | goto error; 2995 | } 2996 | #endif 2997 | u->wst.ptr += 2; 2998 | } 2999 | break; 3000 | case 0xc3: /* POPkr */ 3001 | __asm__("evaluxn_c3_POPkr:"); 3002 | { 3003 | u->rst.dat[u->rst.ptr - 1]; 3004 | #ifndef NO_STACK_CHECKS 3005 | if(__builtin_expect(u->rst.ptr < 1, 0)) { 3006 | u->rst.error = 1; 3007 | goto error; 3008 | } 3009 | #endif 3010 | } 3011 | break; 3012 | case 0xc4: /* DUPkr */ 3013 | __asm__("evaluxn_c4_DUPkr:"); 3014 | { 3015 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 3016 | u->rst.dat[u->rst.ptr] = a; 3017 | u->rst.dat[u->rst.ptr + 1] = a; 3018 | #ifndef NO_STACK_CHECKS 3019 | if(__builtin_expect(u->rst.ptr < 1, 0)) { 3020 | u->rst.error = 1; 3021 | goto error; 3022 | } 3023 | if(__builtin_expect(u->rst.ptr > 253, 0)) { 3024 | u->rst.error = 2; 3025 | goto error; 3026 | } 3027 | #endif 3028 | u->rst.ptr += 2; 3029 | } 3030 | break; 3031 | case 0xc5: /* SWPkr */ 3032 | __asm__("evaluxn_c5_SWPkr:"); 3033 | { 3034 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 3035 | u->rst.dat[u->rst.ptr] = a; 3036 | u->rst.dat[u->rst.ptr + 1] = b; 3037 | #ifndef NO_STACK_CHECKS 3038 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 3039 | u->rst.error = 1; 3040 | goto error; 3041 | } 3042 | if(__builtin_expect(u->rst.ptr > 253, 0)) { 3043 | u->rst.error = 2; 3044 | goto error; 3045 | } 3046 | #endif 3047 | u->rst.ptr += 2; 3048 | } 3049 | break; 3050 | case 0xc6: /* OVRkr */ 3051 | __asm__("evaluxn_c6_OVRkr:"); 3052 | { 3053 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 3054 | u->rst.dat[u->rst.ptr] = b; 3055 | u->rst.dat[u->rst.ptr + 1] = a; 3056 | u->rst.dat[u->rst.ptr + 2] = b; 3057 | #ifndef NO_STACK_CHECKS 3058 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 3059 | u->rst.error = 1; 3060 | goto error; 3061 | } 3062 | if(__builtin_expect(u->rst.ptr > 252, 0)) { 3063 | u->rst.error = 2; 3064 | goto error; 3065 | } 3066 | #endif 3067 | u->rst.ptr += 3; 3068 | } 3069 | break; 3070 | case 0xc7: /* ROTkr */ 3071 | __asm__("evaluxn_c7_ROTkr:"); 3072 | { 3073 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2], c = u->rst.dat[u->rst.ptr - 3]; 3074 | u->rst.dat[u->rst.ptr] = b; 3075 | u->rst.dat[u->rst.ptr + 1] = a; 3076 | u->rst.dat[u->rst.ptr + 2] = c; 3077 | #ifndef NO_STACK_CHECKS 3078 | if(__builtin_expect(u->rst.ptr < 3, 0)) { 3079 | u->rst.error = 1; 3080 | goto error; 3081 | } 3082 | if(__builtin_expect(u->rst.ptr > 252, 0)) { 3083 | u->rst.error = 2; 3084 | goto error; 3085 | } 3086 | #endif 3087 | u->rst.ptr += 3; 3088 | } 3089 | break; 3090 | case 0xc8: /* EQUkr */ 3091 | __asm__("evaluxn_c8_EQUkr:"); 3092 | { 3093 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 3094 | u->rst.dat[u->rst.ptr] = b == a; 3095 | #ifndef NO_STACK_CHECKS 3096 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 3097 | u->rst.error = 1; 3098 | goto error; 3099 | } 3100 | if(__builtin_expect(u->rst.ptr > 254, 0)) { 3101 | u->rst.error = 2; 3102 | goto error; 3103 | } 3104 | #endif 3105 | u->rst.ptr += 1; 3106 | } 3107 | break; 3108 | case 0xc9: /* NEQkr */ 3109 | __asm__("evaluxn_c9_NEQkr:"); 3110 | { 3111 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 3112 | u->rst.dat[u->rst.ptr] = b != a; 3113 | #ifndef NO_STACK_CHECKS 3114 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 3115 | u->rst.error = 1; 3116 | goto error; 3117 | } 3118 | if(__builtin_expect(u->rst.ptr > 254, 0)) { 3119 | u->rst.error = 2; 3120 | goto error; 3121 | } 3122 | #endif 3123 | u->rst.ptr += 1; 3124 | } 3125 | break; 3126 | case 0xca: /* GTHkr */ 3127 | __asm__("evaluxn_ca_GTHkr:"); 3128 | { 3129 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 3130 | u->rst.dat[u->rst.ptr] = b > a; 3131 | #ifndef NO_STACK_CHECKS 3132 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 3133 | u->rst.error = 1; 3134 | goto error; 3135 | } 3136 | if(__builtin_expect(u->rst.ptr > 254, 0)) { 3137 | u->rst.error = 2; 3138 | goto error; 3139 | } 3140 | #endif 3141 | u->rst.ptr += 1; 3142 | } 3143 | break; 3144 | case 0xcb: /* LTHkr */ 3145 | __asm__("evaluxn_cb_LTHkr:"); 3146 | { 3147 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 3148 | u->rst.dat[u->rst.ptr] = b < a; 3149 | #ifndef NO_STACK_CHECKS 3150 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 3151 | u->rst.error = 1; 3152 | goto error; 3153 | } 3154 | if(__builtin_expect(u->rst.ptr > 254, 0)) { 3155 | u->rst.error = 2; 3156 | goto error; 3157 | } 3158 | #endif 3159 | u->rst.ptr += 1; 3160 | } 3161 | break; 3162 | case 0xcc: /* JMPkr */ 3163 | __asm__("evaluxn_cc_JMPkr:"); 3164 | { 3165 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 3166 | u->ram.ptr += (Sint8)a; 3167 | #ifndef NO_STACK_CHECKS 3168 | if(__builtin_expect(u->rst.ptr < 1, 0)) { 3169 | u->rst.error = 1; 3170 | goto error; 3171 | } 3172 | #endif 3173 | } 3174 | break; 3175 | case 0xcd: /* JCNkr */ 3176 | __asm__("evaluxn_cd_JCNkr:"); 3177 | { 3178 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 3179 | if(u->rst.dat[u->rst.ptr - 2]) u->ram.ptr += (Sint8)a; 3180 | #ifndef NO_STACK_CHECKS 3181 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 3182 | u->rst.error = 1; 3183 | goto error; 3184 | } 3185 | #endif 3186 | } 3187 | break; 3188 | case 0xce: /* JSRkr */ 3189 | __asm__("evaluxn_ce_JSRkr:"); 3190 | { 3191 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 3192 | u->wst.dat[u->wst.ptr] = u->ram.ptr >> 8; 3193 | u->wst.dat[u->wst.ptr + 1] = u->ram.ptr & 0xff; 3194 | u->ram.ptr += (Sint8)a; 3195 | #ifndef NO_STACK_CHECKS 3196 | if(__builtin_expect(u->rst.ptr < 1, 0)) { 3197 | u->rst.error = 1; 3198 | goto error; 3199 | } 3200 | if(__builtin_expect(u->wst.ptr > 253, 0)) { 3201 | u->wst.error = 2; 3202 | goto error; 3203 | } 3204 | #endif 3205 | u->wst.ptr += 2; 3206 | } 3207 | break; 3208 | case 0xcf: /* STHkr */ 3209 | __asm__("evaluxn_cf_STHkr:"); 3210 | { 3211 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 3212 | u->wst.dat[u->wst.ptr] = a; 3213 | #ifndef NO_STACK_CHECKS 3214 | if(__builtin_expect(u->rst.ptr < 1, 0)) { 3215 | u->rst.error = 1; 3216 | goto error; 3217 | } 3218 | if(__builtin_expect(u->wst.ptr > 254, 0)) { 3219 | u->wst.error = 2; 3220 | goto error; 3221 | } 3222 | #endif 3223 | u->wst.ptr += 1; 3224 | } 3225 | break; 3226 | case 0xd0: /* LDZkr */ 3227 | __asm__("evaluxn_d0_LDZkr:"); 3228 | { 3229 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 3230 | u->rst.dat[u->rst.ptr] = mempeek8(u->ram.dat, a); 3231 | #ifndef NO_STACK_CHECKS 3232 | if(__builtin_expect(u->rst.ptr < 1, 0)) { 3233 | u->rst.error = 1; 3234 | goto error; 3235 | } 3236 | if(__builtin_expect(u->rst.ptr > 254, 0)) { 3237 | u->rst.error = 2; 3238 | goto error; 3239 | } 3240 | #endif 3241 | u->rst.ptr += 1; 3242 | } 3243 | break; 3244 | case 0xd1: /* STZkr */ 3245 | __asm__("evaluxn_d1_STZkr:"); 3246 | { 3247 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 3248 | Uint8 b = u->rst.dat[u->rst.ptr - 2]; 3249 | mempoke8(u->ram.dat, a, b); 3250 | #ifndef NO_STACK_CHECKS 3251 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 3252 | u->rst.error = 1; 3253 | goto error; 3254 | } 3255 | #endif 3256 | } 3257 | break; 3258 | case 0xd2: /* LDRkr */ 3259 | __asm__("evaluxn_d2_LDRkr:"); 3260 | { 3261 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 3262 | u->rst.dat[u->rst.ptr] = mempeek8(u->ram.dat, u->ram.ptr + (Sint8)a); 3263 | #ifndef NO_STACK_CHECKS 3264 | if(__builtin_expect(u->rst.ptr < 1, 0)) { 3265 | u->rst.error = 1; 3266 | goto error; 3267 | } 3268 | if(__builtin_expect(u->rst.ptr > 254, 0)) { 3269 | u->rst.error = 2; 3270 | goto error; 3271 | } 3272 | #endif 3273 | u->rst.ptr += 1; 3274 | } 3275 | break; 3276 | case 0xd3: /* STRkr */ 3277 | __asm__("evaluxn_d3_STRkr:"); 3278 | { 3279 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 3280 | Uint8 b = u->rst.dat[u->rst.ptr - 2]; 3281 | mempoke8(u->ram.dat, u->ram.ptr + (Sint8)a, b); 3282 | #ifndef NO_STACK_CHECKS 3283 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 3284 | u->rst.error = 1; 3285 | goto error; 3286 | } 3287 | #endif 3288 | } 3289 | break; 3290 | case 0xd4: /* LDAkr */ 3291 | __asm__("evaluxn_d4_LDAkr:"); 3292 | { 3293 | Uint16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)); 3294 | u->rst.dat[u->rst.ptr] = mempeek8(u->ram.dat, a); 3295 | #ifndef NO_STACK_CHECKS 3296 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 3297 | u->rst.error = 1; 3298 | goto error; 3299 | } 3300 | if(__builtin_expect(u->rst.ptr > 254, 0)) { 3301 | u->rst.error = 2; 3302 | goto error; 3303 | } 3304 | #endif 3305 | u->rst.ptr += 1; 3306 | } 3307 | break; 3308 | case 0xd5: /* STAkr */ 3309 | __asm__("evaluxn_d5_STAkr:"); 3310 | { 3311 | Uint16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)); 3312 | Uint8 b = u->rst.dat[u->rst.ptr - 3]; 3313 | mempoke8(u->ram.dat, a, b); 3314 | #ifndef NO_STACK_CHECKS 3315 | if(__builtin_expect(u->rst.ptr < 3, 0)) { 3316 | u->rst.error = 1; 3317 | goto error; 3318 | } 3319 | #endif 3320 | } 3321 | break; 3322 | case 0xd6: /* DEIkr */ 3323 | __asm__("evaluxn_d6_DEIkr:"); 3324 | { 3325 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 3326 | u->rst.dat[u->rst.ptr] = devpeek8(&u->dev[a >> 4], a); 3327 | #ifndef NO_STACK_CHECKS 3328 | if(__builtin_expect(u->rst.ptr < 1, 0)) { 3329 | u->rst.error = 1; 3330 | goto error; 3331 | } 3332 | if(__builtin_expect(u->rst.ptr > 254, 0)) { 3333 | u->rst.error = 2; 3334 | goto error; 3335 | } 3336 | #endif 3337 | u->rst.ptr += 1; 3338 | } 3339 | break; 3340 | case 0xd7: /* DEOkr */ 3341 | __asm__("evaluxn_d7_DEOkr:"); 3342 | { 3343 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 3344 | devpoke8(&u->dev[a >> 4], a, b); 3345 | #ifndef NO_STACK_CHECKS 3346 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 3347 | u->rst.error = 1; 3348 | goto error; 3349 | } 3350 | #endif 3351 | } 3352 | break; 3353 | case 0xd8: /* ADDkr */ 3354 | __asm__("evaluxn_d8_ADDkr:"); 3355 | { 3356 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 3357 | u->rst.dat[u->rst.ptr] = b + a; 3358 | #ifndef NO_STACK_CHECKS 3359 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 3360 | u->rst.error = 1; 3361 | goto error; 3362 | } 3363 | if(__builtin_expect(u->rst.ptr > 254, 0)) { 3364 | u->rst.error = 2; 3365 | goto error; 3366 | } 3367 | #endif 3368 | u->rst.ptr += 1; 3369 | } 3370 | break; 3371 | case 0xd9: /* SUBkr */ 3372 | __asm__("evaluxn_d9_SUBkr:"); 3373 | { 3374 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 3375 | u->rst.dat[u->rst.ptr] = b - a; 3376 | #ifndef NO_STACK_CHECKS 3377 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 3378 | u->rst.error = 1; 3379 | goto error; 3380 | } 3381 | if(__builtin_expect(u->rst.ptr > 254, 0)) { 3382 | u->rst.error = 2; 3383 | goto error; 3384 | } 3385 | #endif 3386 | u->rst.ptr += 1; 3387 | } 3388 | break; 3389 | case 0xda: /* MULkr */ 3390 | __asm__("evaluxn_da_MULkr:"); 3391 | { 3392 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 3393 | u->rst.dat[u->rst.ptr] = b * a; 3394 | #ifndef NO_STACK_CHECKS 3395 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 3396 | u->rst.error = 1; 3397 | goto error; 3398 | } 3399 | if(__builtin_expect(u->rst.ptr > 254, 0)) { 3400 | u->rst.error = 2; 3401 | goto error; 3402 | } 3403 | #endif 3404 | u->rst.ptr += 1; 3405 | } 3406 | break; 3407 | case 0xdb: /* DIVkr */ 3408 | __asm__("evaluxn_db_DIVkr:"); 3409 | { 3410 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 3411 | if(a == 0) { 3412 | u->rst.error = 3; 3413 | #ifndef NO_STACK_CHECKS 3414 | goto error; 3415 | #endif 3416 | a = 1; 3417 | } 3418 | u->rst.dat[u->rst.ptr] = b / a; 3419 | #ifndef NO_STACK_CHECKS 3420 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 3421 | u->rst.error = 1; 3422 | goto error; 3423 | } 3424 | if(__builtin_expect(u->rst.ptr > 254, 0)) { 3425 | u->rst.error = 2; 3426 | goto error; 3427 | } 3428 | #endif 3429 | u->rst.ptr += 1; 3430 | } 3431 | break; 3432 | case 0xdc: /* ANDkr */ 3433 | __asm__("evaluxn_dc_ANDkr:"); 3434 | { 3435 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 3436 | u->rst.dat[u->rst.ptr] = b & a; 3437 | #ifndef NO_STACK_CHECKS 3438 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 3439 | u->rst.error = 1; 3440 | goto error; 3441 | } 3442 | if(__builtin_expect(u->rst.ptr > 254, 0)) { 3443 | u->rst.error = 2; 3444 | goto error; 3445 | } 3446 | #endif 3447 | u->rst.ptr += 1; 3448 | } 3449 | break; 3450 | case 0xdd: /* ORAkr */ 3451 | __asm__("evaluxn_dd_ORAkr:"); 3452 | { 3453 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 3454 | u->rst.dat[u->rst.ptr] = b | a; 3455 | #ifndef NO_STACK_CHECKS 3456 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 3457 | u->rst.error = 1; 3458 | goto error; 3459 | } 3460 | if(__builtin_expect(u->rst.ptr > 254, 0)) { 3461 | u->rst.error = 2; 3462 | goto error; 3463 | } 3464 | #endif 3465 | u->rst.ptr += 1; 3466 | } 3467 | break; 3468 | case 0xde: /* EORkr */ 3469 | __asm__("evaluxn_de_EORkr:"); 3470 | { 3471 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 3472 | u->rst.dat[u->rst.ptr] = b ^ a; 3473 | #ifndef NO_STACK_CHECKS 3474 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 3475 | u->rst.error = 1; 3476 | goto error; 3477 | } 3478 | if(__builtin_expect(u->rst.ptr > 254, 0)) { 3479 | u->rst.error = 2; 3480 | goto error; 3481 | } 3482 | #endif 3483 | u->rst.ptr += 1; 3484 | } 3485 | break; 3486 | case 0xdf: /* SFTkr */ 3487 | __asm__("evaluxn_df_SFTkr:"); 3488 | { 3489 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 3490 | u->rst.dat[u->rst.ptr] = b >> (a & 0x07) << ((a & 0x70) >> 4); 3491 | #ifndef NO_STACK_CHECKS 3492 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 3493 | u->rst.error = 1; 3494 | goto error; 3495 | } 3496 | if(__builtin_expect(u->rst.ptr > 254, 0)) { 3497 | u->rst.error = 2; 3498 | goto error; 3499 | } 3500 | #endif 3501 | u->rst.ptr += 1; 3502 | } 3503 | break; 3504 | case 0xe3: /* POP2kr */ 3505 | __asm__("evaluxn_e3_POP2kr:"); 3506 | { 3507 | (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)); 3508 | #ifndef NO_STACK_CHECKS 3509 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 3510 | u->rst.error = 1; 3511 | goto error; 3512 | } 3513 | #endif 3514 | } 3515 | break; 3516 | case 0xe4: /* DUP2kr */ 3517 | __asm__("evaluxn_e4_DUP2kr:"); 3518 | { 3519 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 3520 | u->rst.dat[u->rst.ptr] = b; 3521 | u->rst.dat[u->rst.ptr + 1] = a; 3522 | u->rst.dat[u->rst.ptr + 2] = b; 3523 | u->rst.dat[u->rst.ptr + 3] = a; 3524 | #ifndef NO_STACK_CHECKS 3525 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 3526 | u->rst.error = 1; 3527 | goto error; 3528 | } 3529 | if(__builtin_expect(u->rst.ptr > 251, 0)) { 3530 | u->rst.error = 2; 3531 | goto error; 3532 | } 3533 | #endif 3534 | u->rst.ptr += 4; 3535 | } 3536 | break; 3537 | case 0xe5: /* SWP2kr */ 3538 | __asm__("evaluxn_e5_SWP2kr:"); 3539 | { 3540 | Uint8 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]; 3541 | u->rst.dat[u->rst.ptr] = b; 3542 | u->rst.dat[u->rst.ptr + 1] = a; 3543 | u->rst.dat[u->rst.ptr + 2] = d; 3544 | u->rst.dat[u->rst.ptr + 3] = c; 3545 | #ifndef NO_STACK_CHECKS 3546 | if(__builtin_expect(u->rst.ptr < 4, 0)) { 3547 | u->rst.error = 1; 3548 | goto error; 3549 | } 3550 | if(__builtin_expect(u->rst.ptr > 251, 0)) { 3551 | u->rst.error = 2; 3552 | goto error; 3553 | } 3554 | #endif 3555 | u->rst.ptr += 4; 3556 | } 3557 | break; 3558 | case 0xe6: /* OVR2kr */ 3559 | __asm__("evaluxn_e6_OVR2kr:"); 3560 | { 3561 | Uint8 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]; 3562 | u->rst.dat[u->rst.ptr] = d; 3563 | u->rst.dat[u->rst.ptr + 1] = c; 3564 | u->rst.dat[u->rst.ptr + 2] = b; 3565 | u->rst.dat[u->rst.ptr + 3] = a; 3566 | u->rst.dat[u->rst.ptr + 4] = d; 3567 | u->rst.dat[u->rst.ptr + 5] = c; 3568 | #ifndef NO_STACK_CHECKS 3569 | if(__builtin_expect(u->rst.ptr < 4, 0)) { 3570 | u->rst.error = 1; 3571 | goto error; 3572 | } 3573 | if(__builtin_expect(u->rst.ptr > 249, 0)) { 3574 | u->rst.error = 2; 3575 | goto error; 3576 | } 3577 | #endif 3578 | u->rst.ptr += 6; 3579 | } 3580 | break; 3581 | case 0xe7: /* ROT2kr */ 3582 | __asm__("evaluxn_e7_ROT2kr:"); 3583 | { 3584 | Uint8 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]; 3585 | u->rst.dat[u->rst.ptr] = d; 3586 | u->rst.dat[u->rst.ptr + 1] = c; 3587 | u->rst.dat[u->rst.ptr + 2] = b; 3588 | u->rst.dat[u->rst.ptr + 3] = a; 3589 | u->rst.dat[u->rst.ptr + 4] = f; 3590 | u->rst.dat[u->rst.ptr + 5] = e; 3591 | #ifndef NO_STACK_CHECKS 3592 | if(__builtin_expect(u->rst.ptr < 6, 0)) { 3593 | u->rst.error = 1; 3594 | goto error; 3595 | } 3596 | if(__builtin_expect(u->rst.ptr > 249, 0)) { 3597 | u->rst.error = 2; 3598 | goto error; 3599 | } 3600 | #endif 3601 | u->rst.ptr += 6; 3602 | } 3603 | break; 3604 | case 0xe8: /* EQU2kr */ 3605 | __asm__("evaluxn_e8_EQU2kr:"); 3606 | { 3607 | Uint16 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)); 3608 | u->rst.dat[u->rst.ptr] = b == a; 3609 | #ifndef NO_STACK_CHECKS 3610 | if(__builtin_expect(u->rst.ptr < 4, 0)) { 3611 | u->rst.error = 1; 3612 | goto error; 3613 | } 3614 | if(__builtin_expect(u->rst.ptr > 254, 0)) { 3615 | u->rst.error = 2; 3616 | goto error; 3617 | } 3618 | #endif 3619 | u->rst.ptr += 1; 3620 | } 3621 | break; 3622 | case 0xe9: /* NEQ2kr */ 3623 | __asm__("evaluxn_e9_NEQ2kr:"); 3624 | { 3625 | Uint16 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)); 3626 | u->rst.dat[u->rst.ptr] = b != a; 3627 | #ifndef NO_STACK_CHECKS 3628 | if(__builtin_expect(u->rst.ptr < 4, 0)) { 3629 | u->rst.error = 1; 3630 | goto error; 3631 | } 3632 | if(__builtin_expect(u->rst.ptr > 254, 0)) { 3633 | u->rst.error = 2; 3634 | goto error; 3635 | } 3636 | #endif 3637 | u->rst.ptr += 1; 3638 | } 3639 | break; 3640 | case 0xea: /* GTH2kr */ 3641 | __asm__("evaluxn_ea_GTH2kr:"); 3642 | { 3643 | Uint16 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)); 3644 | u->rst.dat[u->rst.ptr] = b > a; 3645 | #ifndef NO_STACK_CHECKS 3646 | if(__builtin_expect(u->rst.ptr < 4, 0)) { 3647 | u->rst.error = 1; 3648 | goto error; 3649 | } 3650 | if(__builtin_expect(u->rst.ptr > 254, 0)) { 3651 | u->rst.error = 2; 3652 | goto error; 3653 | } 3654 | #endif 3655 | u->rst.ptr += 1; 3656 | } 3657 | break; 3658 | case 0xeb: /* LTH2kr */ 3659 | __asm__("evaluxn_eb_LTH2kr:"); 3660 | { 3661 | Uint16 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)); 3662 | u->rst.dat[u->rst.ptr] = b < a; 3663 | #ifndef NO_STACK_CHECKS 3664 | if(__builtin_expect(u->rst.ptr < 4, 0)) { 3665 | u->rst.error = 1; 3666 | goto error; 3667 | } 3668 | if(__builtin_expect(u->rst.ptr > 254, 0)) { 3669 | u->rst.error = 2; 3670 | goto error; 3671 | } 3672 | #endif 3673 | u->rst.ptr += 1; 3674 | } 3675 | break; 3676 | case 0xec: /* JMP2kr */ 3677 | __asm__("evaluxn_ec_JMP2kr:"); 3678 | { 3679 | u->ram.ptr = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)); 3680 | #ifndef NO_STACK_CHECKS 3681 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 3682 | u->rst.error = 1; 3683 | goto error; 3684 | } 3685 | #endif 3686 | } 3687 | break; 3688 | case 0xed: /* JCN2kr */ 3689 | __asm__("evaluxn_ed_JCN2kr:"); 3690 | { 3691 | Uint16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)); 3692 | if(u->rst.dat[u->rst.ptr - 3]) u->ram.ptr = a; 3693 | #ifndef NO_STACK_CHECKS 3694 | if(__builtin_expect(u->rst.ptr < 3, 0)) { 3695 | u->rst.error = 1; 3696 | goto error; 3697 | } 3698 | #endif 3699 | } 3700 | break; 3701 | case 0xee: /* JSR2kr */ 3702 | __asm__("evaluxn_ee_JSR2kr:"); 3703 | { 3704 | u->wst.dat[u->wst.ptr] = u->ram.ptr >> 8; 3705 | u->wst.dat[u->wst.ptr + 1] = u->ram.ptr & 0xff; 3706 | u->ram.ptr = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)); 3707 | #ifndef NO_STACK_CHECKS 3708 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 3709 | u->rst.error = 1; 3710 | goto error; 3711 | } 3712 | if(__builtin_expect(u->wst.ptr > 253, 0)) { 3713 | u->wst.error = 2; 3714 | goto error; 3715 | } 3716 | #endif 3717 | u->wst.ptr += 2; 3718 | } 3719 | break; 3720 | case 0xef: /* STH2kr */ 3721 | __asm__("evaluxn_ef_STH2kr:"); 3722 | { 3723 | Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 3724 | u->wst.dat[u->wst.ptr] = b; 3725 | u->wst.dat[u->wst.ptr + 1] = a; 3726 | #ifndef NO_STACK_CHECKS 3727 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 3728 | u->rst.error = 1; 3729 | goto error; 3730 | } 3731 | if(__builtin_expect(u->wst.ptr > 253, 0)) { 3732 | u->wst.error = 2; 3733 | goto error; 3734 | } 3735 | #endif 3736 | u->wst.ptr += 2; 3737 | } 3738 | break; 3739 | case 0xf0: /* LDZ2kr */ 3740 | __asm__("evaluxn_f0_LDZ2kr:"); 3741 | { 3742 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 3743 | u->rst.dat[u->rst.ptr] = mempeek8(u->ram.dat, a); 3744 | u->rst.dat[u->rst.ptr + 1] = mempeek8(u->ram.dat, a + 1); 3745 | #ifndef NO_STACK_CHECKS 3746 | if(__builtin_expect(u->rst.ptr < 1, 0)) { 3747 | u->rst.error = 1; 3748 | goto error; 3749 | } 3750 | if(__builtin_expect(u->rst.ptr > 253, 0)) { 3751 | u->rst.error = 2; 3752 | goto error; 3753 | } 3754 | #endif 3755 | u->rst.ptr += 2; 3756 | } 3757 | break; 3758 | case 0xf1: /* STZ2kr */ 3759 | __asm__("evaluxn_f1_STZ2kr:"); 3760 | { 3761 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 3762 | Uint16 b = (u->rst.dat[u->rst.ptr - 2] | (u->rst.dat[u->rst.ptr - 3] << 8)); 3763 | mempoke16(u->ram.dat, a, b); 3764 | #ifndef NO_STACK_CHECKS 3765 | if(__builtin_expect(u->rst.ptr < 3, 0)) { 3766 | u->rst.error = 1; 3767 | goto error; 3768 | } 3769 | #endif 3770 | } 3771 | break; 3772 | case 0xf2: /* LDR2kr */ 3773 | __asm__("evaluxn_f2_LDR2kr:"); 3774 | { 3775 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 3776 | u->rst.dat[u->rst.ptr] = mempeek8(u->ram.dat, u->ram.ptr + (Sint8)a); 3777 | u->rst.dat[u->rst.ptr + 1] = mempeek8(u->ram.dat, u->ram.ptr + (Sint8)a + 1); 3778 | #ifndef NO_STACK_CHECKS 3779 | if(__builtin_expect(u->rst.ptr < 1, 0)) { 3780 | u->rst.error = 1; 3781 | goto error; 3782 | } 3783 | if(__builtin_expect(u->rst.ptr > 253, 0)) { 3784 | u->rst.error = 2; 3785 | goto error; 3786 | } 3787 | #endif 3788 | u->rst.ptr += 2; 3789 | } 3790 | break; 3791 | case 0xf3: /* STR2kr */ 3792 | __asm__("evaluxn_f3_STR2kr:"); 3793 | { 3794 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 3795 | Uint16 b = (u->rst.dat[u->rst.ptr - 2] | (u->rst.dat[u->rst.ptr - 3] << 8)); 3796 | mempoke16(u->ram.dat, u->ram.ptr + (Sint8)a, b); 3797 | #ifndef NO_STACK_CHECKS 3798 | if(__builtin_expect(u->rst.ptr < 3, 0)) { 3799 | u->rst.error = 1; 3800 | goto error; 3801 | } 3802 | #endif 3803 | } 3804 | break; 3805 | case 0xf4: /* LDA2kr */ 3806 | __asm__("evaluxn_f4_LDA2kr:"); 3807 | { 3808 | Uint16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)); 3809 | u->rst.dat[u->rst.ptr] = mempeek8(u->ram.dat, a); 3810 | u->rst.dat[u->rst.ptr + 1] = mempeek8(u->ram.dat, a + 1); 3811 | #ifndef NO_STACK_CHECKS 3812 | if(__builtin_expect(u->rst.ptr < 2, 0)) { 3813 | u->rst.error = 1; 3814 | goto error; 3815 | } 3816 | if(__builtin_expect(u->rst.ptr > 253, 0)) { 3817 | u->rst.error = 2; 3818 | goto error; 3819 | } 3820 | #endif 3821 | u->rst.ptr += 2; 3822 | } 3823 | break; 3824 | case 0xf5: /* STA2kr */ 3825 | __asm__("evaluxn_f5_STA2kr:"); 3826 | { 3827 | Uint16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)); 3828 | Uint16 b = (u->rst.dat[u->rst.ptr - 3] | (u->rst.dat[u->rst.ptr - 4] << 8)); 3829 | mempoke16(u->ram.dat, a, b); 3830 | #ifndef NO_STACK_CHECKS 3831 | if(__builtin_expect(u->rst.ptr < 4, 0)) { 3832 | u->rst.error = 1; 3833 | goto error; 3834 | } 3835 | #endif 3836 | } 3837 | break; 3838 | case 0xf6: /* DEI2kr */ 3839 | __asm__("evaluxn_f6_DEI2kr:"); 3840 | { 3841 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 3842 | u->rst.dat[u->rst.ptr] = devpeek8(&u->dev[a >> 4], a); 3843 | u->rst.dat[u->rst.ptr + 1] = devpeek8(&u->dev[a >> 4], a + 1); 3844 | #ifndef NO_STACK_CHECKS 3845 | if(__builtin_expect(u->rst.ptr < 1, 0)) { 3846 | u->rst.error = 1; 3847 | goto error; 3848 | } 3849 | if(__builtin_expect(u->rst.ptr > 253, 0)) { 3850 | u->rst.error = 2; 3851 | goto error; 3852 | } 3853 | #endif 3854 | u->rst.ptr += 2; 3855 | } 3856 | break; 3857 | case 0xf7: /* DEO2kr */ 3858 | __asm__("evaluxn_f7_DEO2kr:"); 3859 | { 3860 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 3861 | Uint16 b = (u->rst.dat[u->rst.ptr - 2] | (u->rst.dat[u->rst.ptr - 3] << 8)); 3862 | devpoke16(&u->dev[a >> 4], a, b); 3863 | #ifndef NO_STACK_CHECKS 3864 | if(__builtin_expect(u->rst.ptr < 3, 0)) { 3865 | u->rst.error = 1; 3866 | goto error; 3867 | } 3868 | #endif 3869 | } 3870 | break; 3871 | case 0xf8: /* ADD2kr */ 3872 | __asm__("evaluxn_f8_ADD2kr:"); 3873 | { 3874 | Uint16 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)); 3875 | u->rst.dat[u->rst.ptr] = (b + a) >> 8; 3876 | u->rst.dat[u->rst.ptr + 1] = (b + a) & 0xff; 3877 | #ifndef NO_STACK_CHECKS 3878 | if(__builtin_expect(u->rst.ptr < 4, 0)) { 3879 | u->rst.error = 1; 3880 | goto error; 3881 | } 3882 | if(__builtin_expect(u->rst.ptr > 253, 0)) { 3883 | u->rst.error = 2; 3884 | goto error; 3885 | } 3886 | #endif 3887 | u->rst.ptr += 2; 3888 | } 3889 | break; 3890 | case 0xf9: /* SUB2kr */ 3891 | __asm__("evaluxn_f9_SUB2kr:"); 3892 | { 3893 | Uint16 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)); 3894 | u->rst.dat[u->rst.ptr] = (b - a) >> 8; 3895 | u->rst.dat[u->rst.ptr + 1] = (b - a) & 0xff; 3896 | #ifndef NO_STACK_CHECKS 3897 | if(__builtin_expect(u->rst.ptr < 4, 0)) { 3898 | u->rst.error = 1; 3899 | goto error; 3900 | } 3901 | if(__builtin_expect(u->rst.ptr > 253, 0)) { 3902 | u->rst.error = 2; 3903 | goto error; 3904 | } 3905 | #endif 3906 | u->rst.ptr += 2; 3907 | } 3908 | break; 3909 | case 0xfa: /* MUL2kr */ 3910 | __asm__("evaluxn_fa_MUL2kr:"); 3911 | { 3912 | Uint16 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)); 3913 | u->rst.dat[u->rst.ptr] = (b * a) >> 8; 3914 | u->rst.dat[u->rst.ptr + 1] = (b * a) & 0xff; 3915 | #ifndef NO_STACK_CHECKS 3916 | if(__builtin_expect(u->rst.ptr < 4, 0)) { 3917 | u->rst.error = 1; 3918 | goto error; 3919 | } 3920 | if(__builtin_expect(u->rst.ptr > 253, 0)) { 3921 | u->rst.error = 2; 3922 | goto error; 3923 | } 3924 | #endif 3925 | u->rst.ptr += 2; 3926 | } 3927 | break; 3928 | case 0xfb: /* DIV2kr */ 3929 | __asm__("evaluxn_fb_DIV2kr:"); 3930 | { 3931 | Uint16 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)); 3932 | if(a == 0) { 3933 | u->rst.error = 3; 3934 | #ifndef NO_STACK_CHECKS 3935 | goto error; 3936 | #endif 3937 | a = 1; 3938 | } 3939 | u->rst.dat[u->rst.ptr] = (b / a) >> 8; 3940 | u->rst.dat[u->rst.ptr + 1] = (b / a) & 0xff; 3941 | #ifndef NO_STACK_CHECKS 3942 | if(__builtin_expect(u->rst.ptr < 4, 0)) { 3943 | u->rst.error = 1; 3944 | goto error; 3945 | } 3946 | if(__builtin_expect(u->rst.ptr > 253, 0)) { 3947 | u->rst.error = 2; 3948 | goto error; 3949 | } 3950 | #endif 3951 | u->rst.ptr += 2; 3952 | } 3953 | break; 3954 | case 0xfc: /* AND2kr */ 3955 | __asm__("evaluxn_fc_AND2kr:"); 3956 | { 3957 | Uint8 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]; 3958 | u->rst.dat[u->rst.ptr] = d & b; 3959 | u->rst.dat[u->rst.ptr + 1] = c & a; 3960 | #ifndef NO_STACK_CHECKS 3961 | if(__builtin_expect(u->rst.ptr < 4, 0)) { 3962 | u->rst.error = 1; 3963 | goto error; 3964 | } 3965 | if(__builtin_expect(u->rst.ptr > 253, 0)) { 3966 | u->rst.error = 2; 3967 | goto error; 3968 | } 3969 | #endif 3970 | u->rst.ptr += 2; 3971 | } 3972 | break; 3973 | case 0xfd: /* ORA2kr */ 3974 | __asm__("evaluxn_fd_ORA2kr:"); 3975 | { 3976 | Uint8 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]; 3977 | u->rst.dat[u->rst.ptr] = d | b; 3978 | u->rst.dat[u->rst.ptr + 1] = c | a; 3979 | #ifndef NO_STACK_CHECKS 3980 | if(__builtin_expect(u->rst.ptr < 4, 0)) { 3981 | u->rst.error = 1; 3982 | goto error; 3983 | } 3984 | if(__builtin_expect(u->rst.ptr > 253, 0)) { 3985 | u->rst.error = 2; 3986 | goto error; 3987 | } 3988 | #endif 3989 | u->rst.ptr += 2; 3990 | } 3991 | break; 3992 | case 0xfe: /* EOR2kr */ 3993 | __asm__("evaluxn_fe_EOR2kr:"); 3994 | { 3995 | Uint8 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]; 3996 | u->rst.dat[u->rst.ptr] = d ^ b; 3997 | u->rst.dat[u->rst.ptr + 1] = c ^ a; 3998 | #ifndef NO_STACK_CHECKS 3999 | if(__builtin_expect(u->rst.ptr < 4, 0)) { 4000 | u->rst.error = 1; 4001 | goto error; 4002 | } 4003 | if(__builtin_expect(u->rst.ptr > 253, 0)) { 4004 | u->rst.error = 2; 4005 | goto error; 4006 | } 4007 | #endif 4008 | u->rst.ptr += 2; 4009 | } 4010 | break; 4011 | case 0xff: /* SFT2kr */ 4012 | __asm__("evaluxn_ff_SFT2kr:"); 4013 | { 4014 | Uint8 a = u->rst.dat[u->rst.ptr - 1]; 4015 | Uint16 b = (u->rst.dat[u->rst.ptr - 2] | (u->rst.dat[u->rst.ptr - 3] << 8)); 4016 | u->rst.dat[u->rst.ptr] = (b >> (a & 0x0f) << ((a & 0xf0) >> 4)) >> 8; 4017 | u->rst.dat[u->rst.ptr + 1] = (b >> (a & 0x0f) << ((a & 0xf0) >> 4)) & 0xff; 4018 | #ifndef NO_STACK_CHECKS 4019 | if(__builtin_expect(u->rst.ptr < 3, 0)) { 4020 | u->rst.error = 1; 4021 | goto error; 4022 | } 4023 | if(__builtin_expect(u->rst.ptr > 253, 0)) { 4024 | u->rst.error = 2; 4025 | goto error; 4026 | } 4027 | #endif 4028 | u->rst.ptr += 2; 4029 | } 4030 | break; 4031 | #pragma GCC diagnostic pop 4032 | } 4033 | } 4034 | return 1; 4035 | #ifndef NO_STACK_CHECKS 4036 | error: 4037 | if(u->wst.error) 4038 | return haltuxn(u, u->wst.error, "Working-stack", instr); 4039 | else 4040 | return haltuxn(u, u->rst.error, "Return-stack", instr); 4041 | #endif 4042 | } 4043 | 4044 | int 4045 | bootuxn(Uxn *u) 4046 | { 4047 | size_t i; 4048 | char *cptr = (char *)u; 4049 | for(i = 0; i < sizeof(*u); i++) 4050 | cptr[i] = 0; 4051 | return 1; 4052 | } 4053 | 4054 | int 4055 | loaduxn(Uxn *u, char *filepath) 4056 | { 4057 | FILE *f; 4058 | if(!(f = fopen(filepath, "rb"))) { 4059 | printf("Halted: Missing input rom.\n"); 4060 | return 0; 4061 | } 4062 | fread(u->ram.dat + PAGE_PROGRAM, sizeof(u->ram.dat) - PAGE_PROGRAM, 1, f); 4063 | printf("Uxn loaded[%s].\n", filepath); 4064 | return 1; 4065 | } 4066 | 4067 | Device * 4068 | portuxn(Uxn *u, Uint8 id, char *name, void (*talkfn)(Device *d, Uint8 b0, Uint8 w)) 4069 | { 4070 | Device *d = &u->dev[id]; 4071 | d->addr = id * 0x10; 4072 | d->u = u; 4073 | d->mem = u->ram.dat; 4074 | d->talk = talkfn; 4075 | printf("Device added #%02x: %s, at 0x%04x \n", id, name, d->addr); 4076 | return d; 4077 | } 4078 | -------------------------------------------------------------------------------- /src/uxn.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | Copyright (c) 2021 Devine Lu Linvega 5 | 6 | Permission to use, copy, modify, and distribute this software for any 7 | purpose with or without fee is hereby granted, provided that the above 8 | copyright notice and this permission notice appear in all copies. 9 | 10 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | WITH REGARD TO THIS SOFTWARE. 12 | */ 13 | 14 | typedef unsigned char Uint8; 15 | typedef signed char Sint8; 16 | typedef unsigned short Uint16; 17 | typedef signed short Sint16; 18 | 19 | #define PAGE_PROGRAM 0x0100 20 | 21 | typedef struct { 22 | Uint8 ptr, kptr, error; 23 | Uint8 dat[256]; 24 | } Stack; 25 | 26 | typedef struct { 27 | Uint16 ptr; 28 | Uint8 dat[65536]; 29 | } Memory; 30 | 31 | typedef struct Device { 32 | struct Uxn *u; 33 | Uint8 addr, dat[16], *mem; 34 | void (*talk)(struct Device *d, Uint8, Uint8); 35 | } Device; 36 | 37 | typedef struct Uxn { 38 | Stack wst, rst, *src, *dst; 39 | Memory ram; 40 | Device dev[16]; 41 | } Uxn; 42 | 43 | struct Uxn; 44 | 45 | void mempoke16(Uint8 *m, Uint16 a, Uint16 b); 46 | Uint16 mempeek16(Uint8 *m, Uint16 a); 47 | 48 | int loaduxn(Uxn *c, char *filepath); 49 | int bootuxn(Uxn *c); 50 | int evaluxn(Uxn *u, Uint16 vec); 51 | Device *portuxn(Uxn *u, Uint8 id, char *name, void (*talkfn)(Device *, Uint8, Uint8)); 52 | -------------------------------------------------------------------------------- /src/webuxn.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "uxn.h" 5 | #include "devices/ppu.h" 6 | #include "devices/apu.h" 7 | 8 | extern void printChar (const char c); 9 | extern void printStr (const char* str); 10 | extern void render (const Uint32* bg, const Uint32* fg); 11 | extern void getDateTime (const Uint8* ptr); 12 | 13 | typedef struct { 14 | Uxn uxn; 15 | Ppu ppu; 16 | Apu apu[POLYPHONY]; 17 | } VMState; 18 | 19 | VMState vm; 20 | Device *devscreen, *devmouse, *devctrl, *devmidi, *devaudio0; 21 | Uint8 reqdraw = 0; 22 | 23 | Uint32 toAbgr (Uint32 argb) { 24 | Uint8 b = (argb & 0x000000ff); 25 | Uint8 g = (argb & 0x0000ff00) >> 8; 26 | Uint8 r = (argb & 0x00ff0000) >> 16; 27 | Uint8 a = (argb & 0xff000000) >> 24; 28 | return (a << 24) | (b << 16) | (g << 8) | r; 29 | } 30 | 31 | void system_talk (Device* d, Uint8 b0, Uint8 w) { 32 | /* printStr("Called system_talk\n"); */ 33 | 34 | if(!w) { 35 | d->dat[0x2] = d->u->wst.ptr; 36 | d->dat[0x3] = d->u->rst.ptr; 37 | } else { 38 | putcolors(&vm.ppu, &d->dat[0x8]); 39 | reqdraw = 1; 40 | } 41 | (void)b0; 42 | } 43 | 44 | void 45 | console_talk(Device *d, Uint8 b0, Uint8 w) 46 | { 47 | if(!w) return; 48 | switch(b0) { 49 | case 0x8: printChar(d->dat[0x8]); break; 50 | // TODO(2021-06-10): Implement number printing 51 | /* case 0x9: printf("0x%02x", d->dat[0x9]); break; */ 52 | /* case 0xb: printf("0x%04x", mempeek16(d->dat, 0xa)); break; */ 53 | case 0xd: printStr(&d->mem[mempeek16(d->dat, 0xc)]); break; 54 | } 55 | } 56 | 57 | void 58 | screen_talk(Device *d, Uint8 b0, Uint8 w) 59 | { 60 | if(w && b0 == 0xe) { 61 | Uint16 x = mempeek16(d->dat, 0x8); 62 | Uint16 y = mempeek16(d->dat, 0xa); 63 | Uint8 *addr = &d->mem[mempeek16(d->dat, 0xc)]; 64 | Layer *layer = d->dat[0xe] >> 4 & 0x1 ? &vm.ppu.fg : &vm.ppu.bg; 65 | Uint8 mode = d->dat[0xe] >> 5; 66 | if(!mode) 67 | putpixel(&vm.ppu, layer, x, y, d->dat[0xe] & 0x3); 68 | else if(mode-- & 0x1) 69 | puticn(&vm.ppu, layer, x, y, addr, d->dat[0xe] & 0xf, mode & 0x2, mode & 0x4); 70 | else 71 | putchr(&vm.ppu, layer, x, y, addr, d->dat[0xe] & 0xf, mode & 0x2, mode & 0x4); 72 | reqdraw = 1; 73 | } 74 | } 75 | 76 | void audio_talk(Device *d, Uint8 b0, Uint8 w) 77 | { 78 | Apu *c = &vm.apu[d - devaudio0]; 79 | if(!w) { 80 | if(b0 == 0x2) 81 | mempoke16(d->dat, 0x2, c->i); 82 | else if(b0 == 0x4) 83 | d->dat[0x4] = apu_get_vu(c); 84 | } else if(b0 == 0xf) { 85 | c->len = mempeek16(d->dat, 0xa); 86 | c->addr = &d->mem[mempeek16(d->dat, 0xc)]; 87 | c->volume[0] = d->dat[0xe] >> 4; 88 | c->volume[1] = d->dat[0xe] & 0xf; 89 | c->repeat = !(d->dat[0xf] & 0x80); 90 | apu_start(c, mempeek16(d->dat, 0x8), d->dat[0xf] & 0x7f); 91 | } 92 | } 93 | 94 | void 95 | datetime_talk(Device *d, Uint8 b0, Uint8 w) 96 | { 97 | getDateTime(d->dat); 98 | (void)b0; 99 | (void)w; 100 | } 101 | 102 | void 103 | nil_talk(Device *d, Uint8 b0, Uint8 w) 104 | { 105 | (void)d; 106 | (void)b0; 107 | (void)w; 108 | } 109 | 110 | Uint8* EMSCRIPTEN_KEEPALIVE getRomPtr () { 111 | return vm.uxn.ram.dat + PAGE_PROGRAM; 112 | } 113 | 114 | void* EMSCRIPTEN_KEEPALIVE getStatePtr () { 115 | return &vm; 116 | } 117 | 118 | int EMSCRIPTEN_KEEPALIVE getStateSize () { 119 | return sizeof(vm); 120 | } 121 | 122 | float* EMSCRIPTEN_KEEPALIVE getAudioSamples () { 123 | // Should match chunkSize in webuxn.js, it would be nice to lower this to 512, but that seems to 124 | // introduce skipping 125 | const int chunkSize = 1024; 126 | 127 | Sint16 samples[2*chunkSize] = {0}; 128 | for (int ii = 0; ii < POLYPHONY; ++ii) { 129 | apu_render(&vm.apu[ii], samples, samples + 2*chunkSize); 130 | } 131 | 132 | // Convert interleaved Sint16 array to uninterleaved float32 array 133 | static float webAudioSamples[2*chunkSize]; 134 | for (int ii = 0; ii < chunkSize; ++ii) { 135 | webAudioSamples[ii] = (float)samples[2*ii] / 32767; 136 | webAudioSamples[ii+chunkSize] = (float)samples[2*ii+1] / 32767; 137 | } 138 | return webAudioSamples; 139 | } 140 | 141 | void EMSCRIPTEN_KEEPALIVE init () { 142 | // Reset state 143 | memset(&vm, 0, sizeof(vm)); 144 | 145 | // Statically allocate pixels to avoid depending on malloc 146 | vm.ppu.width = WIDTH; 147 | vm.ppu.height = HEIGHT; 148 | 149 | portuxn(&vm.uxn, 0x0, "system", system_talk); 150 | portuxn(&vm.uxn, 0x1, "console", console_talk); 151 | devscreen = portuxn(&vm.uxn, 0x2, "screen", screen_talk); 152 | devaudio0 = portuxn(&vm.uxn, 0x3, "audio0", audio_talk); 153 | portuxn(&vm.uxn, 0x4, "audio1", audio_talk); 154 | portuxn(&vm.uxn, 0x5, "audio2", audio_talk); 155 | portuxn(&vm.uxn, 0x6, "audio3", audio_talk); 156 | devmidi = portuxn(&vm.uxn, 0x7, "midi", nil_talk); 157 | devctrl = portuxn(&vm.uxn, 0x8, "controller", nil_talk); 158 | devmouse = portuxn(&vm.uxn, 0x9, "mouse", nil_talk); 159 | portuxn(&vm.uxn, 0xa, "file", nil_talk); 160 | portuxn(&vm.uxn, 0xb, "datetime", datetime_talk); 161 | portuxn(&vm.uxn, 0xc, "---", nil_talk); 162 | portuxn(&vm.uxn, 0xd, "---", nil_talk); 163 | portuxn(&vm.uxn, 0xe, "---", nil_talk); 164 | portuxn(&vm.uxn, 0xf, "---", nil_talk); 165 | 166 | // Write screen size to dev/screen 167 | mempoke16(devscreen->dat, 2, WIDTH); 168 | mempoke16(devscreen->dat, 4, HEIGHT); 169 | } 170 | 171 | void EMSCRIPTEN_KEEPALIVE runMain () { 172 | evaluxn(&vm.uxn, PAGE_PROGRAM); 173 | } 174 | 175 | void EMSCRIPTEN_KEEPALIVE onUpdate () { 176 | evaluxn(&vm.uxn, mempeek16(devscreen->dat, 0)); 177 | 178 | if (reqdraw) { 179 | reqdraw = 0; 180 | 181 | // TODO(2021-06-09): Do alpha compositing in software? 182 | int ll = WIDTH*HEIGHT; 183 | Uint32 bg_abgr[ll], fg_abgr[ll]; 184 | Uint32* bg = vm.ppu.bg.pixels; 185 | Uint32* fg = vm.ppu.fg.pixels; 186 | 187 | for (int ii = 0; ii < ll; ++ii) { 188 | bg_abgr[ii] = toAbgr(bg[ii]); 189 | fg_abgr[ii] = toAbgr(fg[ii]); 190 | } 191 | render(bg_abgr, fg_abgr); 192 | } 193 | } 194 | 195 | void EMSCRIPTEN_KEEPALIVE onPointerEvent (int x, int y, int buttons) { 196 | // FIXME(2021-06-10): Click and drag compatibility with uxnemu 197 | mempoke16(devmouse->dat, 0x2, x); 198 | mempoke16(devmouse->dat, 0x4, y); 199 | devmouse->dat[6] = buttons; 200 | 201 | evaluxn(&vm.uxn, mempeek16(devmouse->dat, 0)); 202 | } 203 | 204 | void EMSCRIPTEN_KEEPALIVE onWheelEvent (int y) { 205 | devmouse->dat[7] = y; 206 | evaluxn(&vm.uxn, mempeek16(devmouse->dat, 0)); 207 | devmouse->dat[7] = 0; 208 | } 209 | 210 | void EMSCRIPTEN_KEEPALIVE onKeyboardEvent (int buttons, int charCode) { 211 | devctrl->dat[2] = buttons; 212 | devctrl->dat[3] = charCode; 213 | 214 | evaluxn(&vm.uxn, mempeek16(devctrl->dat, 0)); 215 | devctrl->dat[3] = 0; 216 | } 217 | -------------------------------------------------------------------------------- /webuxn.js: -------------------------------------------------------------------------------- 1 | export async function run (wasmBuffer, romBuffer, bgCanvas) { 2 | // Main canvas 3 | const bgCtx = bgCanvas.getContext("2d"); 4 | const bgImageData = bgCtx.createImageData(bgCanvas.width, bgCanvas.height); 5 | 6 | // Overlay canvas 7 | const fgCanvas = document.createElement("canvas"); 8 | fgCanvas.width = bgCanvas.width; 9 | fgCanvas.height = bgCanvas.height; 10 | const fgCtx = fgCanvas.getContext("2d"); 11 | const fgImageData = fgCtx.createImageData(fgCanvas.width, fgCanvas.height); 12 | 13 | // Mutable state 14 | let lineBuffer = ""; 15 | let keys = 0; 16 | let vmState; 17 | 18 | const { instance: wasm } = await WebAssembly.instantiate(wasmBuffer, { 19 | env: { 20 | printChar, 21 | printStr, 22 | render, 23 | getDateTime, 24 | }, 25 | }); 26 | 27 | function printChar (c) { 28 | if (c == 10) { 29 | console.log(lineBuffer); 30 | lineBuffer = ""; 31 | } else { 32 | lineBuffer += String.fromCharCode(c); 33 | } 34 | } 35 | 36 | function printStr (ptr) { 37 | const memory = new Uint8Array(wasm.exports.memory.buffer); 38 | while (memory[ptr] != 0) { 39 | printChar(memory[ptr++]); 40 | } 41 | } 42 | 43 | function render (bgPtr, fgPtr) { 44 | const size = bgCanvas.width*bgCanvas.height*4; 45 | const bgPixels = new Uint8Array(wasm.exports.memory.buffer, bgPtr, size); 46 | const fgPixels = new Uint8Array(wasm.exports.memory.buffer, fgPtr, size); 47 | 48 | bgImageData.data.set(bgPixels); 49 | bgCtx.putImageData(bgImageData, 0, 0); 50 | 51 | fgImageData.data.set(fgPixels); 52 | fgCtx.putImageData(fgImageData, 0, 0); 53 | 54 | // Composite foreground with alpha blending 55 | bgCtx.drawImage(fgCanvas, 0, 0); 56 | } 57 | 58 | function getDateTime (datPtr) { 59 | const dat = new DataView(wasm.exports.memory.buffer, datPtr, 16); 60 | const now = new Date(); 61 | dat.setUint16(0x0, now.getFullYear()); 62 | dat.setUint8(0x2, now.getMonth()); 63 | dat.setUint8(0x3, now.getDay()); 64 | dat.setUint8(0x4, now.getHours()); 65 | dat.setUint8(0x5, now.getMinutes()); 66 | dat.setUint8(0x6, now.getSeconds()); 67 | dat.setUint8(0x7, now.getDay()); 68 | 69 | // TODO(2021-06-11): Implement day-of-year and DST flag 70 | dat.setUint16(0x08, 0); 71 | dat.setUint8(0xa, 0); 72 | } 73 | 74 | function onPointerEvent (event) { 75 | // Do certain things that require a user gesture 76 | if (event.type == "pointerdown") { 77 | if (document.fullscreenElement == null && event.pointerType == "touch") { 78 | // Go fullscreen on mobile 79 | bgCanvas.requestFullscreen({navigationUI: "hide"}); 80 | } 81 | if (audioCtx.state == "suspended") { 82 | // Try to resume audio 83 | audioCtx.resume(); 84 | } 85 | } 86 | 87 | // FIXME(2021-06-10): mouse coords incorrect when in fullscreen 88 | const bounds = bgCanvas.getBoundingClientRect(); 89 | const x = bgCanvas.width * (event.clientX - bounds.left) / bounds.width; 90 | const y = bgCanvas.height * (event.clientY - bounds.top) / bounds.height; 91 | wasm.exports.onPointerEvent(x, y, event.buttons); 92 | event.preventDefault(); 93 | } 94 | bgCanvas.addEventListener("pointermove", onPointerEvent); 95 | bgCanvas.addEventListener("pointerdown", onPointerEvent); 96 | bgCanvas.addEventListener("pointerup", onPointerEvent); 97 | 98 | bgCanvas.addEventListener("wheel", event => { 99 | wasm.exports.onWheelEvent(event.deltaY); 100 | event.preventDefault(); 101 | }); 102 | 103 | // Prevent right click context menu 104 | bgCanvas.addEventListener("contextmenu", event => { 105 | event.preventDefault(); 106 | }); 107 | 108 | function onKeyboardEvent (event) { 109 | event.preventDefault(); 110 | 111 | // Handle special emulator keys 112 | if (event.type == "keydown") { 113 | switch (event.keyCode) { 114 | case 113: // F2 115 | vmState = saveState(); 116 | return; 117 | case 115: // F4 118 | if (vmState != null) { 119 | loadState(vmState); 120 | } 121 | return; 122 | case 116: // F5 123 | boot(); 124 | return; 125 | case 120: // F9 126 | bgCanvas.toBlob(blob => { 127 | var url = URL.createObjectURL(blob); 128 | var anchor = document.createElement("a"); 129 | anchor.href = url; 130 | anchor.download = "webuxn.png"; 131 | anchor.click(); 132 | URL.revokeObjectURL(url); 133 | }); 134 | return; 135 | case 122: // F11 136 | if (document.fullscreenElement == null) { 137 | bgCanvas.requestFullscreen({navigationUI: "hide"}); 138 | } else { 139 | document.exitFullscreen(); 140 | } 141 | return; 142 | } 143 | } 144 | 145 | let mask = 0; 146 | switch (event.keyCode) { 147 | case 17: // Control 148 | mask = 0x01; 149 | break; 150 | case 18: // Alt 151 | mask = 0x02; 152 | break; 153 | case 16: // Shift 154 | mask = 0x04; 155 | break; 156 | case 27: // Escape 157 | mask = 0x08; 158 | break; 159 | case 38: // Up 160 | mask = 0x10; 161 | break; 162 | case 40: // Down 163 | mask = 0x20; 164 | break; 165 | case 37: // Left 166 | mask = 0x40; 167 | break; 168 | case 39: // Right 169 | mask = 0x80; 170 | break; 171 | } 172 | let charCode = 0; 173 | if (event.type == "keydown") { 174 | keys |= mask; 175 | if (event.key.length == 1) { 176 | charCode = event.key.charCodeAt(0); 177 | } else if (mask == 0 && event.keyCode < 20) { 178 | charCode = event.keyCode; 179 | } 180 | } else { 181 | keys &= ~mask; 182 | } 183 | wasm.exports.onKeyboardEvent(keys, charCode); 184 | } 185 | window.addEventListener("keydown", onKeyboardEvent); 186 | window.addEventListener("keyup", onKeyboardEvent); 187 | 188 | // Gamepad handling 189 | let gamepadIdx = -1; 190 | window.addEventListener("gamepadconnected", event => { 191 | const gamepad = event.gamepad; 192 | if (gamepad.mapping == "standard") { 193 | gamepadIdx = gamepad.index; 194 | } 195 | }); 196 | window.addEventListener("gamepaddisconnected", event => { 197 | gamepadIdx = -1; 198 | }); 199 | function updateGamepad () { 200 | if (gamepadIdx >= 0) { 201 | const gamepad = navigator.getGamepads()[gamepadIdx]; 202 | const buttons = gamepad.buttons; 203 | 204 | // https://w3c.github.io/gamepad/#remapping 205 | let gamepadKeys = 0; 206 | if (buttons[0].pressed) { 207 | gamepadKeys |= 0x01; // Control 208 | } 209 | if (buttons[1].pressed) { 210 | gamepadKeys |= 0x02; // Alt 211 | } 212 | if (buttons[2].pressed) { 213 | gamepadKeys |= 0x04; // Shift 214 | } 215 | if (buttons[8].pressed || buttons[9].pressed) { 216 | gamepadKeys |= 0x08; // Escape 217 | } 218 | if (buttons[12].pressed) { 219 | gamepadKeys |= 0x10; // Up 220 | } 221 | if (buttons[13].pressed) { 222 | gamepadKeys |= 0x20; // Down 223 | } 224 | if (buttons[14].pressed) { 225 | gamepadKeys |= 0x40; // Left 226 | } 227 | if (buttons[15].pressed) { 228 | gamepadKeys |= 0x80; // Right 229 | } 230 | 231 | if (keys != gamepadKeys) { 232 | keys = gamepadKeys; 233 | wasm.exports.onKeyboardEvent(keys, 0); 234 | } 235 | } 236 | } 237 | 238 | function boot () { 239 | // Initialize 240 | wasm.exports.init(); 241 | 242 | // Load the ROM 243 | const memory = new Uint8Array(wasm.exports.memory.buffer); 244 | const romBufferLength = Math.min(romBuffer.byteLength, 0x10000 - 0x0100); 245 | memory.set(new Uint8Array(romBuffer, 0, romBufferLength), wasm.exports.getRomPtr()); 246 | 247 | // Execute it 248 | wasm.exports.runMain(); 249 | if (lineBuffer) { 250 | printChar(10); 251 | } 252 | } 253 | boot(); 254 | 255 | // State saving and loading 256 | function saveState () { 257 | const memory = new Uint8Array(wasm.exports.memory.buffer); 258 | const ptr = wasm.exports.getStatePtr(); 259 | const size = wasm.exports.getStateSize(); 260 | return memory.slice(ptr, ptr+size); 261 | } 262 | function loadState (state) { 263 | const memory = new Uint8Array(wasm.exports.memory.buffer); 264 | const ptr = wasm.exports.getStatePtr(); 265 | memory.set(state, ptr); 266 | } 267 | 268 | // Audio handling 269 | const audioCtx = new AudioContext(); 270 | const chunkSize = 1024; 271 | const processor = audioCtx.createScriptProcessor(chunkSize, 0, 2); 272 | processor.onaudioprocess = event => { 273 | const samplesPtr = wasm.exports.getAudioSamples(); 274 | const samples = new Float32Array(wasm.exports.memory.buffer, samplesPtr, 2*chunkSize); 275 | const audioBuffer = event.outputBuffer; 276 | audioBuffer.copyToChannel(samples, 0); 277 | audioBuffer.copyToChannel(samples.subarray(chunkSize), 1); 278 | }; 279 | processor.connect(audioCtx.destination); 280 | 281 | // Update every frame 282 | function update () { 283 | updateGamepad(); 284 | wasm.exports.onUpdate(); 285 | requestAnimationFrame(update); 286 | } 287 | update(); 288 | } 289 | --------------------------------------------------------------------------------