diff options
author | Viktor Semykin <thesame.ml@gmail.com> | 2010-07-04 15:09:02 +0300 |
---|---|---|
committer | Viktor Semykin <thesame.ml@gmail.com> | 2010-07-04 15:09:02 +0300 |
commit | dbca894cb0a4872481e0026b81d2b3ae083d1485 (patch) | |
tree | c510fa549a27e761627195a2bca667bd6796e435 /plugins | |
parent | 05ae679fd8e6762f98d8582f75f05a09f9a7c71b (diff) | |
parent | 3793f58d388dd1e26e6edf7bd548ed17fc588ae1 (diff) |
merged with devel
Diffstat (limited to 'plugins')
132 files changed, 94316 insertions, 342 deletions
diff --git a/plugins/aac/Makefile.am b/plugins/aac/Makefile.am new file mode 100644 index 00000000..a10ff510 --- /dev/null +++ b/plugins/aac/Makefile.am @@ -0,0 +1,9 @@ +if HAVE_AAC +aacdir = $(libdir)/$(PACKAGE) +pkglib_LTLIBRARIES = aac.la +aac_la_SOURCES = aac.c aac_parser.c aac_parser.h +aac_la_LDFLAGS = -module + +aac_la_LIBADD = $(LDADD) $(FAAD2_LIBS) +AM_CFLAGS = $(CFLAGS) -std=c99 +endif diff --git a/plugins/aac/aac.c b/plugins/aac/aac.c new file mode 100644 index 00000000..f59c7308 --- /dev/null +++ b/plugins/aac/aac.c @@ -0,0 +1,725 @@ +/* + DeaDBeeF - ultimate music player for GNU/Linux systems with X11 + Copyright (C) 2009-2010 Alexey Yakovenko <waker@users.sourceforge.net> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <string.h> +#include <stdio.h> +#include <neaacdec.h> +#ifdef HAVE_CONFIG_H +#include "../../config.h" +#endif +#include <mp4ff.h> +#include <stdlib.h> +#include "../../deadbeef.h" +#include "aac_parser.h" + +#define min(x,y) ((x)<(y)?(x):(y)) +#define max(x,y) ((x)>(y)?(x):(y)) + +#define trace(...) { fprintf(stderr, __VA_ARGS__); } +//#define trace(fmt,...) + +static DB_decoder_t plugin; +static DB_functions_t *deadbeef; + +#define AAC_BUFFER_SIZE 8192 +#define OUT_BUFFER_SIZE 100000 + +typedef struct { + DB_fileinfo_t info; + NeAACDecHandle dec; + DB_FILE *file; + mp4ff_t *mp4file; + mp4ff_callback_t mp4reader; + int mp4track; + int mp4sample; + int mp4framesize; + int skipsamples; + int startsample; + int endsample; + int currentsample; + char buffer[AAC_BUFFER_SIZE]; + int remaining; + int faad_channels; + char out_buffer[OUT_BUFFER_SIZE]; + int out_remaining; +} aac_info_t; + +// allocate codec control structure +static DB_fileinfo_t * +aac_open (void) { + DB_fileinfo_t *_info = malloc (sizeof (aac_info_t)); + aac_info_t *info = (aac_info_t *)_info; + memset (info, 0, sizeof (aac_info_t)); + return _info; +} + +static uint32_t +aac_fs_read (void *user_data, void *buffer, uint32_t length) { +// trace ("aac_fs_read\n"); + DB_FILE *fp = (DB_FILE *)user_data; + return deadbeef->fread (buffer, 1, length, fp); +} + +static uint32_t +aac_fs_seek (void *user_data, uint64_t position) { +// trace ("aac_fs_seek\n"); + DB_FILE *fp = (DB_FILE *)user_data; + return deadbeef->fseek (fp, position, SEEK_SET); +} + +static int +parse_aac_stream(DB_FILE *fp, int *samplerate, int *channels, float *duration, int *totalsamples) +{ + int skip = deadbeef->junk_get_leading_size (fp); + if (skip >= 0) { + deadbeef->fseek (fp, skip, SEEK_SET); + } + int offs = deadbeef->ftell (fp); + int fsize = deadbeef->fgetlength (fp); + if (skip > 0) { + fsize -= skip; + } + + uint8_t buf[ADTS_HEADER_SIZE*8]; + + int nsamples = 0; + int stream_sr = 0; + int stream_ch = 0; + + int eof = 0; + int bufsize = 0; + int remaining = 0; + + int frame = 0; + + do { + int size = sizeof (buf) - bufsize; + if (deadbeef->fread (buf + bufsize, 1, size, fp) != size) { + trace ("parse_aac_stream: eof\n"); + break; + } + bufsize = sizeof (buf); + + int channels, samplerate, bitrate, samples; + size = aac_sync (buf, &channels, &samplerate, &bitrate, &samples); + if (size == 0) { + memmove (buf, buf+1, sizeof (buf)-1); + bufsize--; + continue; + } + else { + //trace ("aac: frame #%d sync: %d %d %d %d %d\n", frame, channels, samplerate, bitrate, samples, size); + frame++; + nsamples += samples; + if (!stream_sr) { + stream_sr = samplerate; + } + if (!stream_ch) { + stream_ch = channels; + } + if (deadbeef->fseek (fp, size-sizeof(buf), SEEK_CUR) == -1) { + trace ("parse_aac_stream: invalid seek %d\n", size-sizeof(buf)); + break; + } + bufsize = 0; + } + } while (totalsamples || frame < 1000); + + if (!frame || !stream_sr || !nsamples) { + return -1; + } + + *samplerate = stream_sr; + *channels = stream_ch; + + if (totalsamples) { + *totalsamples = nsamples; + *duration = nsamples / (float)stream_sr; + trace ("aac: duration=%f (%d samples @ %d Hz), fsize=%d, nframes=%d\n", *duration, *totalsamples, stream_sr, fsize, frame); + } + else { + int pos = deadbeef->ftell (fp); + int totalsamples = (double)fsize / (pos-offs) * nsamples; + *duration = totalsamples / (float)stream_sr; + trace ("aac: duration=%f (%d samples @ %d Hz), fsize=%d\n", *duration, totalsamples, stream_sr, fsize); + } + + return 0; +} + +// returns -1 for error, 0 for mp4, 1 for aac +int +aac_probe (DB_FILE *fp, float *duration, int *samplerate, int *channels, int *totalsamples, int *mp4track) { + // try mp4 + + mp4ff_callback_t cb = { + .read = aac_fs_read, + .write = NULL, + .seek = aac_fs_seek, + .truncate = NULL, + .user_data = fp + }; + + *duration = -1; + mp4ff_t *mp4 = mp4ff_open_read (&cb); + if (!mp4) { + trace ("not an mp4 file\n"); + return -1; + } + int ntracks = mp4ff_total_tracks (mp4); + if (ntracks > 0) { + trace ("m4a container detected, ntracks=%d\n", ntracks); + int i = -1; + trace ("looking for mp4 data...\n"); + for (i = 0; i < ntracks; i++) { + unsigned char* buff = 0; + unsigned int buff_size = 0; + mp4AudioSpecificConfig mp4ASC; + mp4ff_get_decoder_config(mp4, i, &buff, &buff_size); + if(buff){ + int rc = AudioSpecificConfig(buff, buff_size, &mp4ASC); + free(buff); + if(rc < 0) + continue; + break; + } + } + + if (i != ntracks) + { + trace ("mp4 track: %d\n", i); + *samplerate = mp4ff_get_sample_rate (mp4, i); + *channels = mp4ff_get_channel_count (mp4, i); + int samples = mp4ff_num_samples(mp4, i); + trace ("mp4 nsamples=%d, samplerate=%d\n", samples * 1024, *samplerate); + *duration = (float)samples * 1024 / (*samplerate); + + if (totalsamples) { + *totalsamples = samples; + } + if (mp4track) { + *mp4track = i; + } + return 0; + } + } + mp4ff_close (mp4); + trace ("mp4 track not found, looking for aac stream...\n"); + + // not an mp4, try raw aac + deadbeef->rewind (fp); + if (parse_aac_stream (fp, samplerate, channels, duration, totalsamples) == -1) { + trace ("aac stream not found\n"); + return -1; + } + trace ("found aac stream\n"); + return 1; +} + + +static int +aac_init (DB_fileinfo_t *_info, DB_playItem_t *it) { + aac_info_t *info = (aac_info_t *)_info; + + info->file = deadbeef->fopen (it->fname); + if (!info->file) { + return -1; + } + + // probe + float duration = -1; + int samplerate = -1; + int channels = -1; + int totalsamples = -1; + + int skip = deadbeef->junk_get_leading_size (info->file); + if (skip >= 0) { + deadbeef->fseek (info->file, skip, SEEK_SET); + } + int offs = deadbeef->ftell (info->file); + + info->mp4track = -1; +// int res = aac_probe (info->file, &duration, &samplerate, &channels, &totalsamples, &mp4track); +// if (res == -1) { +// return -1; +// } + info->mp4reader.read = aac_fs_read; + info->mp4reader.write = NULL; + info->mp4reader.seek = aac_fs_seek; + info->mp4reader.truncate = NULL; + info->mp4reader.user_data = info->file; + + info->mp4file = mp4ff_open_read (&info->mp4reader); + if (info->mp4file) { + int ntracks = mp4ff_total_tracks (info->mp4file); + if (ntracks > 0) { + trace ("m4a container detected, ntracks=%d\n", ntracks); + int i = -1; + trace ("looking for mp4 data...\n"); + unsigned char* buff = 0; + unsigned int buff_size = 0; + for (i = 0; i < ntracks; i++) { + mp4AudioSpecificConfig mp4ASC; + mp4ff_get_decoder_config (info->mp4file, i, &buff, &buff_size); + if(buff){ + int rc = AudioSpecificConfig(buff, buff_size, &mp4ASC); + if(rc < 0) + continue; + break; + } + } + + if (i != ntracks && buff) + { + trace ("mp4 track: %d\n", i); + samplerate = mp4ff_get_sample_rate (info->mp4file, i); + channels = mp4ff_get_channel_count (info->mp4file, i); + int samples = mp4ff_num_samples(info->mp4file, i); + trace ("mp4 nsamples=%d, samplerate=%d\n", samples * 1024, samplerate); + duration = (float)samples * 1024 / samplerate; + totalsamples = samples * 1024; + info->mp4track = i; + + // init mp4 decoding + info->dec = NeAACDecOpen (); + unsigned long srate; + unsigned char ch; + if (NeAACDecInit2(info->dec, buff, buff_size, &srate, &ch) < 0) { + trace ("NeAACDecInit2 returned error\n"); + return -1; + } + info->faad_channels = ch; + mp4AudioSpecificConfig mp4ASC; + if (NeAACDecAudioSpecificConfig(buff, buff_size, &mp4ASC) >= 0) + { + info->mp4framesize = 1024; + if (mp4ASC.frameLengthFlag == 1) { + info->mp4framesize = 960; + } + if (mp4ASC.sbr_present_flag == 1) { + info->mp4framesize *= 2; + } + } + free (buff); + } + else { + mp4ff_close (info->mp4file); + info->mp4file = NULL; + } + } + else { + mp4ff_close (info->mp4file); + info->mp4file = NULL; + } + } + if (!info->mp4file) { + trace ("mp4 track not found, looking for aac stream...\n"); + + // not an mp4, try raw aac + deadbeef->rewind (info->file); + if (parse_aac_stream (info->file, &samplerate, &channels, &duration, &totalsamples) == -1) { + trace ("aac stream not found\n"); + return -1; + } + trace ("found aac stream\n"); + } + +// duration = (float)totalsamples / samplerate; +// deadbeef->pl_set_item_duration (it, duration); + + _info->bps = 16; + _info->channels = channels; + _info->samplerate = samplerate; + _info->plugin = &plugin; + + deadbeef->fseek (info->file, offs, SEEK_SET); + + if (!info->mp4file) { + info->dec = NeAACDecOpen (); + + info->remaining = deadbeef->fread (info->buffer, 1, AAC_BUFFER_SIZE, info->file); + + NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration (info->dec); + conf->dontUpSampleImplicitSBR = 1; + NeAACDecSetConfiguration (info->dec, conf); + unsigned long srate; + unsigned char ch; + int consumed = NeAACDecInit (info->dec, info->buffer, info->remaining, &srate, &ch); + if (consumed < 0) { + trace ("NeAACDecInit returned %d\n", consumed); + return -1; + } + if (consumed > info->remaining) { + trace ("NeAACDecInit consumed more than available! wtf?\n"); + return -1; + } + if (consumed == info->remaining) { + info->remaining = 0; + } + else if (consumed > 0) { + memmove (info->buffer, info->buffer + consumed, info->remaining - consumed); + info->remaining -= consumed; + } + info->faad_channels = ch; + } + + if (it->endsample > 0) { + info->startsample = it->startsample; + info->endsample = it->endsample; + plugin.seek_sample (_info, 0); + } + else { + info->startsample = 0; + info->endsample = totalsamples-1; + } + + +// _info->samplerate = srate; + + // recalculate duration +// trace ("duration=%f, totalsamples = %d\n", duration, totalsamples); +// trace ("NeAACDecInit returned samplerate=%d, channels=%d\n", (int)srate, (int)ch); + + return 0; +} + +static void +aac_free (DB_fileinfo_t *_info) { + aac_info_t *info = (aac_info_t *)_info; + if (info) { + if (info->file) { + deadbeef->fclose (info->file); + } + if (info->mp4file) { + mp4ff_close (info->mp4file); + } + if (info->dec) { + NeAACDecClose (info->dec); + } + free (info); + } +} + +static int +aac_read_int16 (DB_fileinfo_t *_info, char *bytes, int size) { + aac_info_t *info = (aac_info_t *)_info; + if (info->currentsample + size / (2 * _info->channels) > info->endsample) { + size = (info->endsample - info->currentsample + 1) * 2 * _info->channels; + if (size <= 0) { + return 0; + } + } + + int initsize = size; + int eof = 0; + int ch = min (_info->channels, 2); + int sample_size = ch * (_info->bps >> 3); + + while (size > 0) { + if (info->skipsamples > 0 && info->out_remaining > 0) { + int skip = min (info->out_remaining, info->skipsamples); + if (skip < info->out_remaining) { + memmove (info->out_buffer, info->out_buffer + skip * 2 * info->faad_channels, (info->out_remaining - skip) * 2 * info->faad_channels); + } + info->out_remaining -= skip; + info->skipsamples -= skip; + } + if (info->out_remaining > 0) { + int n = size / sample_size; + n = min (info->out_remaining, n); + + char *src = info->out_buffer; + for (int i = 0; i < n; i++) { + memcpy (bytes, src, sample_size); + bytes += sample_size; + src += info->faad_channels * 2; + } + + size -= n * sample_size; + if (n == info->out_remaining) { + info->out_remaining = 0; + } + else { + memmove (info->out_buffer, src, (info->out_remaining - n) * info->faad_channels * 2); + info->out_remaining -= n; + } + continue; + } + + char *samples = NULL; + NeAACDecFrameInfo frame_info; + + if (info->mp4file) { + unsigned char *buffer = NULL; + int buffer_size = 0; + int rc = mp4ff_read_sample (info->mp4file, info->mp4track, info->mp4sample, &buffer, &buffer_size); + if (rc == 0) { + break; + } + info->mp4sample++; + samples = NeAACDecDecode(info->dec, &frame_info, buffer, buffer_size); + free (buffer); + if (!samples) { + break; + } + } + else { + if (info->remaining < AAC_BUFFER_SIZE) { + size_t res = deadbeef->fread (info->buffer + info->remaining, 1, AAC_BUFFER_SIZE-info->remaining, info->file); + if (res == 0) { + eof = 1; + } + info->remaining += res; + } + + //trace ("NeAACDecDecode %d bytes %d offs\n", info->remaining, deadbeef->ftell (info->file)); + samples = NeAACDecDecode (info->dec, &frame_info, info->buffer, info->remaining); + if (!samples) { + trace ("NeAACDecDecode failed\n"); + break; + } + int consumed = frame_info.bytesconsumed; + if (consumed > info->remaining) { + trace ("NeAACDecDecode consumed more than available! wtf?\n"); + break; + } + if (consumed == info->remaining) { + info->remaining = 0; + } + else if (consumed > 0) { + memmove (info->buffer, info->buffer + consumed, info->remaining - consumed); + info->remaining -= consumed; + } + } + + if (frame_info.samples > 0) { + memcpy (info->out_buffer, samples, frame_info.samples * 2); + info->out_remaining = frame_info.samples / frame_info.channels; + } + } + + info->currentsample += (initsize-size) / sample_size; + if (size != 0) { + trace ("aac_read_int16 eof\n"); + } + return initsize-size; +} + +// returns -1 on error, 0 on success +int +seek_raw_aac (aac_info_t *info, int sample) { + deadbeef->rewind (info->file); + int skip = deadbeef->junk_get_leading_size (info->file); + if (skip >= 0) { + deadbeef->fseek (info->file, skip, SEEK_SET); + } + + int offs = deadbeef->ftell (info->file); + uint8_t buf[ADTS_HEADER_SIZE*8]; + + int nsamples = 0; + int stream_sr = 0; + int stream_ch = 0; + + int eof = 0; + int bufsize = 0; + int remaining = 0; + + int frame = 0; + + int frame_samples = 0; + int curr_sample = 0; + + do { + curr_sample += frame_samples; + int size = sizeof (buf) - bufsize; + if (deadbeef->fread (buf + bufsize, 1, size, info->file) != size) { + trace ("seek_raw_aac: eof\n"); + break; + } + bufsize = sizeof (buf); + + int channels, samplerate, bitrate; + size = aac_sync (buf, &channels, &samplerate, &bitrate, &frame_samples); + if (size == 0) { + memmove (buf, buf+1, sizeof (buf)-1); + bufsize--; + continue; + } + else { + //trace ("aac: frame #%d sync: %d %d %d %d %d\n", frame, channels, samplerate, bitrate, samples, size); + frame++; + if (deadbeef->fseek (info->file, size-sizeof(buf), SEEK_CUR) == -1) { + trace ("seek_raw_aac: invalid seek %d\n", size-sizeof(buf)); + break; + } + bufsize = 0; + } + } while (curr_sample + frame_samples < sample); + + if (curr_sample + frame_samples < sample) { + return -1; + } + + return sample - curr_sample; +} + +static int +aac_seek_sample (DB_fileinfo_t *_info, int sample) { + aac_info_t *info = (aac_info_t *)_info; + + sample += info->startsample; + if (info->mp4file) { + info->mp4sample = sample / (info->mp4framesize-1); + info->skipsamples = sample - info->mp4sample * (info->mp4framesize-1); + } + else { + int res = seek_raw_aac (info, sample); + if (res < 0) { + return -1; + } + info->skipsamples = res; + } + info->remaining = 0; + info->out_remaining = 0; + info->currentsample = sample; + _info->readpos = (float)(info->currentsample - info->startsample) / _info->samplerate; + return 0; +} + +static int +aac_seek (DB_fileinfo_t *_info, float t) { + return aac_seek_sample (_info, t * _info->samplerate); +} + +static DB_playItem_t * +aac_insert (DB_playItem_t *after, const char *fname) { + trace ("adding %s\n", fname); + DB_FILE *fp = deadbeef->fopen (fname); + if (!fp) { + trace ("not found\n"); + return NULL; + } + if (fp->vfs->streaming) { + trace ("no streaming aac yet (%s)\n", fname); + deadbeef->fclose (fp); + return NULL; + } + + int skip = deadbeef->junk_get_leading_size (fp); + if (skip >= 0) { + deadbeef->fseek (fp, skip, SEEK_SET); + } + + const char *ftype = NULL; + float duration; + int samplerate; + int channels; + int totalsamples; + + // slowwww! + int res = aac_probe (fp, &duration, &samplerate, &channels, &totalsamples, NULL); + if (res == -1) { + deadbeef->fclose (fp); + return NULL; + } + else if (res == 0) { + ftype = plugin.filetypes[1]; + } + else if (res == 1) { + ftype = plugin.filetypes[0]; + } + + DB_playItem_t *it = deadbeef->pl_item_alloc (); + it->decoder_id = deadbeef->plug_get_decoder_id (plugin.plugin.id); + it->fname = strdup (fname); + it->filetype = ftype; + deadbeef->pl_set_item_duration (it, duration); +// trace ("duration: %f sec\n", duration); + + // read tags + if (ftype == "aac") { + int apeerr = deadbeef->junk_apev2_read (it, fp); + int v2err = deadbeef->junk_id3v2_read (it, fp); + int v1err = deadbeef->junk_id3v1_read (it, fp); + } + + deadbeef->fclose (fp); + + // embedded cue + deadbeef->pl_lock (); + const char *cuesheet = deadbeef->pl_find_meta (it, "cuesheet"); + DB_playItem_t *cue = NULL; + + if (cuesheet) { + cue = deadbeef->pl_insert_cue_from_buffer (after, it, cuesheet, strlen (cuesheet), totalsamples, samplerate); + if (cue) { + deadbeef->pl_item_unref (it); + deadbeef->pl_item_unref (cue); + deadbeef->pl_unlock (); + return cue; + } + } + deadbeef->pl_unlock (); + + cue = deadbeef->pl_insert_cue (after, it, totalsamples, samplerate); + if (cue) { + deadbeef->pl_item_unref (it); + deadbeef->pl_item_unref (cue); + return cue; + } + + deadbeef->pl_add_meta (it, "title", NULL); + + after = deadbeef->pl_insert_item (after, it); + deadbeef->pl_item_unref (it); + return after; +} + +static const char * exts[] = { "aac", "mp4", "m4a", NULL }; +static const char *filetypes[] = { "RAW AAC", "MP4 AAC", NULL }; + +// define plugin interface +static DB_decoder_t plugin = { + DB_PLUGIN_SET_API_VERSION + .plugin.version_major = 0, + .plugin.version_minor = 1, + .plugin.type = DB_PLUGIN_DECODER, + .plugin.id = "aac", + .plugin.name = "AAC decoder based on FAAD2", + .plugin.descr = "aac (m4a, mp4, ...) player", + .plugin.author = "Alexey Yakovenko", + .plugin.email = "waker@users.sourceforge.net", + .plugin.website = "http://deadbeef.sf.net", + .open = aac_open, + .init = aac_init, + .free = aac_free, + .read_int16 = aac_read_int16, + .seek = aac_seek, + .seek_sample = aac_seek_sample, + .insert = aac_insert, + .exts = exts, + .filetypes = filetypes +}; + +DB_plugin_t * +aac_load (DB_functions_t *api) { + deadbeef = api; + return DB_PLUGIN (&plugin); +} diff --git a/plugins/aac/aac_parser.c b/plugins/aac/aac_parser.c new file mode 100644 index 00000000..32571aff --- /dev/null +++ b/plugins/aac/aac_parser.c @@ -0,0 +1,100 @@ +/* + DeaDBeeF - ultimate music player for GNU/Linux systems with X11 + Copyright (C) 2009-2010 Alexey Yakovenko <waker@users.sourceforge.net> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#include <stdio.h> +#include "aac_parser.h" + +#define min(x,y) ((x)<(y)?(x):(y)) +#define max(x,y) ((x)>(y)?(x):(y)) + +#define trace(...) { fprintf(stderr, __VA_ARGS__); } +//#define trace(fmt,...) + +static const int aac_sample_rates[16] = { + 96000, 88200, 64000, 48000, 44100, 32000, + 24000, 22050, 16000, 12000, 11025, 8000, 7350 +}; + +static const int aac_channels[8] = { + 0, 1, 2, 3, 4, 5, 6, 8 +}; + +int +aac_sync(const uint8_t *buf, int *channels, int *sample_rate, int *bit_rate, int *samples) +{ + int size, rdb; + + // 12 sync bits + if (buf[0] != 0xff || (buf[1]&0xf0) != 0xf0) { + //trace ("unsync\n"); + return 0; + } + + int id = (buf[1] & 0x08) >> 7; + + int version = id == 0 ? 4 : 2; + + int layer = (buf[1] & 0x06) >> 5; + int protection_abs = (buf[1] & 0x01); + + int header_size = protection_abs > 0 ? 7 : 9; + + int profile_objecttype = (buf[2] & 0xC0) >> 6; + + //const char *profiles[4] = { + // "0 Main profile AAC MAIN", + // "1 Low Complexity profile (LC)AAC LC", + // "2 Scalable Sample Rate profile (SSR)AAC SSR", + // "3 (reserved)AAC LTP" + //}; + //trace ("profile: %s\n", profiles[profile_objecttype]); + + int sample_freq_index = (buf[2] & 0x3C) >> 2; + if (!aac_sample_rates[sample_freq_index]) { + //trace ("invalid samplerate\n"); + return 0; + } + //trace ("samplerate %d (#%d)\n", aac_sample_rates[sample_freq_index], sample_freq_index); + int private_bit = (buf[2] & 0x02) >> 1; + + int channel_conf = ((buf[2] & 0x01) << 2) | ((buf[3] & 0xC0) >> 6); + if (!aac_channels[channel_conf]) { + //trace ("invalid channels\n"); + return 0; + } + //trace ("channels %d\n", aac_channels[channel_conf]); + int orig_copy = (buf[3] & 0x20) >> 5; + int home = (buf[3] & 0x10) >> 4; + int copyright_ident_bit = (buf[3] & 0x08) >> 3; + int copyright_ident_start = (buf[3] & 0x04) >> 2; + size = ((buf[3] & 0x03) << 11) | (buf[4] << 3) | ((buf[5] & 0xE0) >> 5); + if(size < ADTS_HEADER_SIZE) { + //trace ("invalid size\n"); + return 0; + } + int adts_buffer_fullness = ((buf[5] & 0x1F) << 3) | ((buf[6] & 0xFC) >> 2); + rdb = buf[7] & 0x03; + + *channels = aac_channels[channel_conf]; + *sample_rate = aac_sample_rates[sample_freq_index]; + *samples = rdb * 1024; + *bit_rate = size * 8 * *sample_rate / *samples; + + return size; +} + diff --git a/plugins/aac/aac_parser.h b/plugins/aac/aac_parser.h new file mode 100644 index 00000000..53e7916d --- /dev/null +++ b/plugins/aac/aac_parser.h @@ -0,0 +1,32 @@ +/* + DeaDBeeF - ultimate music player for GNU/Linux systems with X11 + Copyright (C) 2009-2010 Alexey Yakovenko <waker@users.sourceforge.net> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __AAC_PARSER_H +#define __AAC_PARSER_H + +#include <stdint.h> + +#define ADTS_HEADER_SIZE 7 + +// buf size must be at least ADTS_HEADER_SIZE*8 +// returns frame size +int +aac_sync(const uint8_t *buf, int *channels, int *sample_rate, int *bit_rate, int *samples); + +#endif diff --git a/plugins/ao/Makefile.am b/plugins/ao/Makefile.am new file mode 100644 index 00000000..c332adf4 --- /dev/null +++ b/plugins/ao/Makefile.am @@ -0,0 +1,25 @@ +if HAVE_AO +aodir = $(libdir)/$(PACKAGE) +pkglib_LTLIBRARIES = ao.la +ao_la_SOURCES = plugin.c main.c corlett.c\ +eng_dsf/eng_dsf.c eng_dsf/dc_hw.c eng_dsf/aica.c eng_dsf/aicadsp.c eng_dsf/arm7.c eng_dsf/arm7i.c\ +eng_ssf/m68kcpu.c eng_ssf/m68kopac.c eng_ssf/m68kopdm.c eng_ssf/m68kopnz.c eng_ssf/m68kops.c \ +eng_ssf/scsp.c eng_ssf/scspdsp.c eng_ssf/sat_hw.c eng_ssf/eng_ssf.c\ +eng_qsf/eng_qsf.c eng_qsf/kabuki.c eng_qsf/qsound.c eng_qsf/z80.c eng_qsf/z80dasm.c\ +eng_psf/eng_psf.c eng_psf/psx.c eng_psf/psx_hw.c eng_psf/peops/spu.c \ +eng_psf/eng_psf2.c eng_psf/peops2/spu2.c eng_psf/peops2/dma2.c eng_psf/peops2/registers2.c\ +eng_psf/eng_spu.c\ +ao.h corlett.h cpuintrf.h eng_protos.h mem.h osd_cpu.h\ +eng_dsf/aicadsp.h eng_dsf/aica.h eng_dsf/arm7.h eng_dsf/arm7i.h eng_dsf/arm7thumb.h eng_dsf/dc_hw.h\ +eng_ssf/m68kconf.h eng_ssf/m68kcpu.h eng_ssf/m68k.h eng_ssf/m68kmame.h eng_ssf/m68kops.h eng_ssf/sat_hw.h eng_ssf/scspdsp.h eng_ssf/scsp.h \ +eng_qsf/qsound.h eng_qsf/z80dasm.h eng_qsf/z80.h\ +eng_psf/cpuintrf.h eng_psf/mamemem.h eng_psf/psx.h\ +eng_psf/peops/adsr.h eng_psf/peops/dma.h eng_psf/peops/externals.h eng_psf/peops/gauss_i.h eng_psf/peops/registers.h eng_psf/peops/regs.h eng_psf/peops/spu.h eng_psf/peops/stdafx.h\ +eng_psf/peops2/adsr.h eng_psf/peops2/dma.h eng_psf/peops2/externals.h eng_psf/peops2/gauss_i.h eng_psf/peops2/psemuxa.h eng_psf/peops2/registers.h eng_psf/peops2/regs.h eng_psf/peops2/reverb.h eng_psf/peops2/spu.h eng_psf/peops2/stdafx.h + +ao_la_LDFLAGS = -module -fPIC + +ao_la_LIBADD = $(LDADD) +AM_CFLAGS = $(CFLAGS) -Wall -DPATH_MAX=1024 -DHAS_PSXCPU=1 -I.. -Ieng_ssf -Ieng_qsf -Ieng_dsf -lm $(ZLIB_LIBS) +endif + diff --git a/plugins/ao/ao.h b/plugins/ao/ao.h new file mode 100755 index 00000000..87a1b00c --- /dev/null +++ b/plugins/ao/ao.h @@ -0,0 +1,229 @@ +// +// Audio Overload SDK +// +// Fake ao.h to set up the general Audio Overload style environment +// + +#ifndef __AO_H +#define __AO_H + +#ifdef HAVE_CONFIG_H +#include "../../config.h" +#endif + +#define AO_SUCCESS 1 +#define AO_FAIL 0 +#define AO_FAIL_DECOMPRESSION -1 + +#define MAX_DISP_INFO_LENGTH 256 +#define AUDIO_RATE (44100) + +enum +{ + COMMAND_NONE = 0, + COMMAND_PREV, + COMMAND_NEXT, + COMMAND_RESTART, + COMMAND_HAS_PREV, + COMMAND_HAS_NEXT, + COMMAND_GET_MIN, + COMMAND_GET_MAX, + COMMAND_JUMP +}; + +#if 0 +/* Compiler defines for Xcode */ +#ifdef __BIG_ENDIAN__ + #undef LSB_FIRST +#endif + +#ifdef __LITTLE_ENDIAN__ + #define LSB_FIRST 1 +#endif +#endif + +#ifdef WORDS_BIGENDIAN + #undef LSB_FIRST +#else + #define LSB_FIRST 1 +#endif + +typedef unsigned char ao_bool; + +#ifdef __GNUC__ +#include <stddef.h> // get NULL +#include <stdbool.h> + +#ifndef nil +#define nil NULL +#endif + +#ifndef TRUE +#define TRUE (1) +#endif +#ifndef FALSE +#define FALSE (0) +#endif + +#define xmalloc(a) malloc(a) + +#endif + +#ifdef _MSC_VER +#include <stddef.h> // get NULL +#include <wchar.h> // for off_t + +#ifndef nil +#define nil NULL +#endif + +#ifndef TRUE +#define TRUE (1) +#endif +#ifndef FALSE +#define FALSE (0) +#endif + +#define true (1) +#define false (0) + +#define xmalloc(a) malloc(a) + +#define strcasecmp _strcmpi + +#endif + +#ifndef PATH_MAX +#define PATH_MAX 2048 +#endif + +typedef struct +{ + char title[9][MAX_DISP_INFO_LENGTH]; + char info[9][MAX_DISP_INFO_LENGTH]; +} ao_display_info; + +typedef unsigned char uint8; +typedef unsigned char UINT8; +typedef signed char int8; +typedef signed char INT8; +typedef unsigned short uint16; +typedef unsigned short UINT16; +typedef signed short int16; +typedef signed short INT16; +typedef signed int int32; +typedef unsigned int uint32; +#ifdef LONG_IS_64BIT +typedef signed long int64; +typedef unsigned long uint64; +#else +typedef signed long long int64; +typedef unsigned long long uint64; +#endif + +typedef int8 s8; +typedef int16 s16; +typedef int32 s32; +typedef int64 s64; + +typedef uint8 u8; +typedef uint16 u16; +typedef uint32 u32; +typedef uint64 u64; + +#ifndef INLINE +#if defined(_MSC_VER) +#define INLINE __forceinline +#elif defined(__GNUC__) +#define INLINE __inline__ +#elif defined(_MWERKS_) +#define INLINE inline +#elif defined(__powerc) +#define INLINE inline +#else +#define INLINE +#endif +#endif + +#if LSB_FIRST +static INLINE u16 BFLIP16(u16 x) +{ + return x; +} +#else +static INLINE u16 BFLIP16(u16 x) +{ + return( ((x>>8)&0xFF)| ((x&0xFF)<<8) ); +} +#endif + +#ifdef WIN32 +#ifndef _BASETSD_H +typedef signed int INT32; +typedef unsigned int UINT32; +typedef signed long long INT64; +typedef unsigned long long UINT64; +#endif +#else +typedef signed int INT32; +typedef unsigned int UINT32; +#ifdef LONG_IS_64BIT +typedef signed long INT64; +typedef unsigned long UINT64; +#else +typedef signed long long INT64; +typedef unsigned long long UINT64; +#endif +#endif + +#if LSB_FIRST +#define LE16(x) (x) +#define LE32(x) (x) + +#ifndef __ENDIAN__ /* Mac OS X Endian header has this function in it */ +static unsigned long INLINE Endian32_Swap(unsigned long addr) +{ + unsigned long res = (((addr&0xff000000)>>24) | + ((addr&0x00ff0000)>>8) | + ((addr&0x0000ff00)<<8) | + ((addr&0x000000ff)<<24)); + + return res; +} +#endif + +#else + +static unsigned short INLINE LE16(unsigned short x) +{ + unsigned short res = (((x & 0xFF00) >> 8) | ((x & 0xFF) << 8)); + return res; +} + +static unsigned long INLINE LE32(unsigned long addr) +{ + unsigned long res = (((addr&0xff000000)>>24) | + ((addr&0x00ff0000)>>8) | + ((addr&0x0000ff00)<<8) | + ((addr&0x000000ff)<<24)); + + return res; +} + +#endif + +int ao_get_lib(char *filename, uint8 **buffer, uint64 *length); + +int ao_identify (char *buffer); + +void *ao_start (uint32 type, const char *name, uint8 *buffer, uint32 size); + +int ao_stop (uint32 type, void *handle); + +int ao_get_info (uint32 type, void *handle, ao_display_info *info); + +int ao_decode (uint32 type, void *handle, int16 *buffer, uint32 size); + +int ao_command (uint32 type, void *handle, int32 command, int32 param); + +#endif // AO_H diff --git a/plugins/ao/corlett.c b/plugins/ao/corlett.c new file mode 100644 index 00000000..653efc1f --- /dev/null +++ b/plugins/ao/corlett.c @@ -0,0 +1,376 @@ +/* + + Audio Overload SDK + + Copyright (c) 2007-2008, R. Belmont and Richard Bannister. + + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +// corlett.c + +// Decodes file format designed by Neill Corlett (PSF, QSF, ...) + +/* + - First 3 bytes: ASCII signature: "PSF" (case sensitive) + +- Next 1 byte: Version byte + The version byte is used to determine the type of PSF file. It does NOT + affect the basic structure of the file in any way. + + Currently accepted version bytes are: + 0x01: Playstation (PSF1) + 0x02: Playstation 2 (PSF2) + 0x11: Saturn (SSF) [TENTATIVE] + 0x12: Dreamcast (DSF) [TENTATIVE] + 0x21: Nintendo 64 (USF) [RESERVED] + 0x41: Capcom QSound (QSF) + +- Next 4 bytes: Size of reserved area (R), little-endian unsigned long + +- Next 4 bytes: Compressed program length (N), little-endian unsigned long + This is the length of the program data _after_ compression. + +- Next 4 bytes: Compressed program CRC-32, little-endian unsigned long + This is the CRC-32 of the program data _after_ compression. Filling in + this value is mandatory, as a PSF file may be regarded as corrupt if it + does not match. + +- Next R bytes: Reserved area. + May be empty if R is 0 bytes. + +- Next N bytes: Compressed program, in zlib compress() format. + May be empty if N is 0 bytes. + +The following data is optional and may be omitted: + +- Next 5 bytes: ASCII signature: "[TAG]" (case sensitive) + If these 5 bytes do not match, then the remainder of the file may be + regarded as invalid and discarded. + +- Remainder of file: Uncompressed ASCII tag data. +*/ + +#include <assert.h> +#include <string.h> +#include <stdlib.h> + +#include "ao.h" +#include "corlett.h" + +#include <zlib.h> +#include <stdlib.h> + +#define DECOMP_MAX_SIZE ((32 * 1024 * 1024) + 12) + +int corlett_decode(uint8 *input, uint32 input_len, uint8 **output, uint64 *size, corlett_t **c) +{ + uint32 *buf; + uint32 res_area, comp_crc, actual_crc; + uint8 *decomp_dat, *tag_dec; + uLongf decomp_length, comp_length; + + // 32-bit pointer to data + buf = (uint32 *)input; + + // Check we have a PSF format file. + if ((input[0] != 'P') || (input[1] != 'S') || (input[2] != 'F')) + { + return AO_FAIL; + } + + // Get our values + res_area = LE32(buf[1]); + comp_length = LE32(buf[2]); + comp_crc = LE32(buf[3]); + + if (comp_length > 0) + { + // Check length + if (input_len < comp_length + 16) + return AO_FAIL; + + // Check CRC is correct + actual_crc = crc32(0, (unsigned char *)&buf[4+(res_area/4)], comp_length); + if (actual_crc != comp_crc) + return AO_FAIL; + + // Decompress data if any + decomp_dat = malloc(DECOMP_MAX_SIZE); + decomp_length = DECOMP_MAX_SIZE; + if (uncompress(decomp_dat, &decomp_length, (unsigned char *)&buf[4+(res_area/4)], comp_length) != Z_OK) + { + free(decomp_dat); + return AO_FAIL; + } + + // Resize memory buffer to what we actually need + decomp_dat = realloc(decomp_dat, (size_t)decomp_length + 1); + } + else + { + decomp_dat = NULL; + decomp_length = 0; + } + + // Make structure + *c = malloc(sizeof(corlett_t)); + if (!(*c)) + { + free(decomp_dat); + return AO_FAIL; + } + memset(*c, 0, sizeof(corlett_t)); + strcpy((*c)->inf_title, "n/a"); + strcpy((*c)->inf_copy, "n/a"); + strcpy((*c)->inf_artist, "n/a"); + strcpy((*c)->inf_game, "n/a"); + strcpy((*c)->inf_year, "n/a"); + strcpy((*c)->inf_length, "n/a"); + strcpy((*c)->inf_fade, "n/a"); + + // set reserved section pointer + (*c)->res_section = &buf[4]; + (*c)->res_size = res_area; + + // Return it + *output = decomp_dat; + *size = decomp_length; + + // Next check for tags + input_len -= (comp_length + 16 + res_area); + if (input_len < 5) + return AO_SUCCESS; + +// printf("\n\nNew corlett: input len %d\n", input_len); + + tag_dec = input + (comp_length + res_area + 16); + if ((tag_dec[0] == '[') && (tag_dec[1] == 'T') && (tag_dec[2] == 'A') && (tag_dec[3] == 'G') && (tag_dec[4] == ']')) + { + int tag, l, num_tags, data; + + // Tags found! + tag_dec += 5; + input_len -= 5; + + tag = 0; + data = false; + num_tags = 0; + l = 0; + while (input_len && (num_tags < MAX_UNKNOWN_TAGS)) + { + if (data) + { + if ((*tag_dec == 0xA) || (*tag_dec == 0x00)) + { + (*c)->tag_data[num_tags][l] = 0; + data = false; + num_tags++; + l = 0; + } + else + { + (*c)->tag_data[num_tags][l++] = *tag_dec; + } + } + else + { + if (*tag_dec == '=') + { + (*c)->tag_name[num_tags][l] = 0; + l = 0; + data = true; + } + else + { + (*c)->tag_name[num_tags][l++] = *tag_dec; + } + } + + tag_dec++; + input_len--; + } + + + // Now, process that tag array into what we expect + for (num_tags = 0; num_tags < MAX_UNKNOWN_TAGS; num_tags++) + { + // See if tag belongs in one of the special fields we have + if (!strcasecmp((*c)->tag_name[num_tags], "_lib")) + { + strcpy((*c)->lib, (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "_lib2", 5)) + { + strcpy((*c)->libaux[0], (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "_lib3", 5)) + { + strcpy((*c)->libaux[1], (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "_lib4", 5)) + { + strcpy((*c)->libaux[2], (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "_lib5", 5)) + { + strcpy((*c)->libaux[3], (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "_lib6", 5)) + { + strcpy((*c)->libaux[4], (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "_lib7", 5)) + { + strcpy((*c)->libaux[5], (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "_lib8", 5)) + { + strcpy((*c)->libaux[6], (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "_lib9", 5)) + { + strcpy((*c)->libaux[7], (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "_refresh", 8)) + { + strcpy((*c)->inf_refresh, (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "title", 5)) + { + strcpy((*c)->inf_title, (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "copyright", 9)) + { + strcpy((*c)->inf_copy, (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "artist", 6)) + { + strcpy((*c)->inf_artist, (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "game", 4)) + { + strcpy((*c)->inf_game, (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "year", 4)) + { + strcpy((*c)->inf_year, (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "length", 6)) + { + strcpy((*c)->inf_length, (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "fade", 4)) + { + strcpy((*c)->inf_fade, (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + } + } + + // Bingo + return AO_SUCCESS; +} + +uint32 psfTimeToMS(char *str) +{ + int x, c=0; + uint32 acc=0; + char s[100]; + + strncpy(s,str,100); + s[99]=0; + + for (x=strlen(s); x>=0; x--) + { + if (s[x]=='.' || s[x]==',') + { + acc=atoi(s+x+1); + s[x]=0; + } + else if (s[x]==':') + { + if(c==0) + { + acc+=atoi(s+x+1)*10; + } + else if(c==1) + { + acc+=atoi(s+x+(x?1:0))*10*60; + } + + c++; + s[x]=0; + } + else if (x==0) + { + if(c==0) + { + acc+=atoi(s+x)*10; + } + else if(c==1) + { + acc+=atoi(s+x)*10*60; + } + else if(c==2) + { + acc+=atoi(s+x)*10*60*60; + } + } + } + + acc*=100; + return(acc); +} + diff --git a/plugins/ao/corlett.h b/plugins/ao/corlett.h new file mode 100644 index 00000000..a9b1ed16 --- /dev/null +++ b/plugins/ao/corlett.h @@ -0,0 +1,35 @@ +// +// Audio Overload +// Emulated music player +// +// (C) 2000-2008 Richard F. Bannister +// + +// corlett.h + +#define MAX_UNKNOWN_TAGS 32 + +typedef struct { + char lib[256]; + char libaux[8][256]; + + char inf_title[256]; + char inf_copy[256]; + char inf_artist[256]; + char inf_game[256]; + char inf_year[256]; + char inf_length[256]; + char inf_fade[256]; + + char inf_refresh[256]; + + char tag_name[MAX_UNKNOWN_TAGS][256]; + char tag_data[MAX_UNKNOWN_TAGS][256]; + + uint32 *res_section; + uint32 res_size; +} corlett_t; + +int corlett_decode(uint8 *input, uint32 input_len, uint8 **output, uint64 *size, corlett_t **c); +uint32 psfTimeToMS(char *str); + diff --git a/plugins/ao/cpuintrf.h b/plugins/ao/cpuintrf.h new file mode 100644 index 00000000..fa7d7f98 --- /dev/null +++ b/plugins/ao/cpuintrf.h @@ -0,0 +1,668 @@ +#ifndef CPUINTRF_H +#define CPUINTRF_H + +#include "osd_cpu.h" + +/* The old system is obsolete and no longer supported by the core */ +#define NEW_INTERRUPT_SYSTEM 1 + +#define MAX_IRQ_LINES 8 /* maximum number of IRQ lines per CPU */ + +#define CLEAR_LINE 0 /* clear (a fired, held or pulsed) line */ +#define ASSERT_LINE 1 /* assert an interrupt immediately */ +#define HOLD_LINE 2 /* hold interrupt line until enable is true */ +#define PULSE_LINE 3 /* pulse interrupt line for one instruction */ + +#define MAX_REGS 64 /* maximum number of register of any CPU */ + +#define IRQ_LINE_NMI 10 +/* Values passed to the cpu_info function of a core to retrieve information */ +enum { + CPU_INFO_REG, + CPU_INFO_FLAGS=MAX_REGS, + CPU_INFO_NAME, + CPU_INFO_FAMILY, + CPU_INFO_VERSION, + CPU_INFO_FILE, + CPU_INFO_CREDITS, + CPU_INFO_REG_LAYOUT, + CPU_INFO_WIN_LAYOUT +}; + +#define CPU_IS_LE 0 /* emulated CPU is little endian */ +#define CPU_IS_BE 1 /* emulated CPU is big endian */ + +/* + * This value is passed to cpu_get_reg to retrieve the previous + * program counter value, ie. before a CPU emulation started + * to fetch opcodes and arguments for the current instrution. + */ +#define REG_PREVIOUSPC -1 + +/* + * This value is passed to cpu_get_reg/cpu_set_reg, instead of one of + * the names from the enum a CPU core defines for it's registers, + * to get or set the contents of the memory pointed to by a stack pointer. + * You can specify the n'th element on the stack by (REG_SP_CONTENTS-n), + * ie. lower negative values. The actual element size (UINT16 or UINT32) + * depends on the CPU core. + * This is also used to replace the cpu_geturnpc() function. + */ +#define REG_SP_CONTENTS -2 + +/* + * These flags can be defined in the makefile (or project) to + * exclude (zero) or include (non zero) specific CPU cores + */ +#ifndef HAS_GENSYNC +#define HAS_GENSYNC 0 +#endif +#ifndef HAS_Z80 +#define HAS_Z80 0 +#endif +#ifndef HAS_Z80_VM +#define HAS_Z80_VM 0 +#endif +#ifndef HAS_8080 +#define HAS_8080 0 +#endif +#ifndef HAS_8085A +#define HAS_8085A 0 +#endif +#ifndef HAS_M6502 +#define HAS_M6502 0 +#endif +#ifndef HAS_M65C02 +#define HAS_M65C02 0 +#endif +#ifndef HAS_M65SC02 +#define HAS_M65SC02 0 +#endif +#ifndef HAS_M65CE02 +#define HAS_M65CE02 0 +#endif +#ifndef HAS_M6509 +#define HAS_M6509 0 +#endif +#ifndef HAS_M6510 +#define HAS_M6510 0 +#endif +#ifndef HAS_N2A03 +#define HAS_N2A03 0 +#endif +#ifndef HAS_H6280 +#define HAS_H6280 0 +#endif +#ifndef HAS_I86 +#define HAS_I86 0 +#endif +#ifndef HAS_V20 +#define HAS_V20 0 +#endif +#ifndef HAS_V30 +#define HAS_V30 0 +#endif +#ifndef HAS_V33 +#define HAS_V33 0 +#endif +#ifndef HAS_I8035 +#define HAS_I8035 0 +#endif +#ifndef HAS_I8039 +#define HAS_I8039 0 +#endif +#ifndef HAS_I8048 +#define HAS_I8048 0 +#endif +#ifndef HAS_N7751 +#define HAS_N7751 0 +#endif +#ifndef HAS_M6800 +#define HAS_M6800 0 +#endif +#ifndef HAS_M6801 +#define HAS_M6801 0 +#endif +#ifndef HAS_M6802 +#define HAS_M6802 0 +#endif +#ifndef HAS_M6803 +#define HAS_M6803 0 +#endif +#ifndef HAS_M6808 +#define HAS_M6808 0 +#endif +#ifndef HAS_HD63701 +#define HAS_HD63701 0 +#endif +#ifndef HAS_M6805 +#define HAS_M6805 0 +#endif +#ifndef HAS_M68705 +#define HAS_M68705 0 +#endif +#ifndef HAS_HD63705 +#define HAS_HD63705 0 +#endif +#ifndef HAS_HD6309 +#define HAS_HD6309 0 +#endif +#ifndef HAS_M6809 +#define HAS_M6809 0 +#endif +#ifndef HAS_KONAMI +#define HAS_KONAMI 0 +#endif +#ifndef HAS_M68000 +#define HAS_M68000 0 +#endif +#ifndef HAS_M68010 +#define HAS_M68010 0 +#endif +#ifndef HAS_M68020 +#define HAS_M68020 0 +#endif +#ifndef HAS_T11 +#define HAS_T11 0 +#endif +#ifndef HAS_S2650 +#define HAS_S2650 0 +#endif +#ifndef HAS_TMS34010 +#define HAS_TMS34010 0 +#endif +#ifndef HAS_TMS9900 +#define HAS_TMS9900 0 +#endif +#ifndef HAS_TMS9940 +#define HAS_TMS9940 0 +#endif +#ifndef HAS_TMS9980 +#define HAS_TMS9980 0 +#endif +#ifndef HAS_TMS9985 +#define HAS_TMS9985 0 +#endif +#ifndef HAS_TMS9989 +#define HAS_TMS9989 0 +#endif +#ifndef HAS_TMS9995 +#define HAS_TMS9995 0 +#endif +#ifndef HAS_TMS99105A +#define HAS_TMS99105A 0 +#endif +#ifndef HAS_TMS99110A +#define HAS_TMS99110A 0 +#endif +#ifndef HAS_Z8000 +#define HAS_Z8000 0 +#endif +#ifndef HAS_TMS320C10 +#define HAS_TMS320C10 0 +#endif +#ifndef HAS_CCPU +#define HAS_CCPU 0 +#endif +#ifndef HAS_PDP1 +#define HAS_PDP1 0 +#endif +#ifndef HAS_ADSP2100 +#define HAS_ADSP2100 0 +#endif + +/* ASG 971222 -- added this generic structure */ +struct cpu_interface +{ + unsigned cpu_num; + void (*reset)(void *param); + void (*exit)(void); + int (*execute)(int cycles); + void (*burn)(int cycles); + unsigned (*get_context)(void *reg); + void (*set_context)(void *reg); + unsigned (*get_pc)(void); + void (*set_pc)(unsigned val); + unsigned (*get_sp)(void); + void (*set_sp)(unsigned val); + unsigned (*get_reg)(int regnum); + void (*set_reg)(int regnum, unsigned val); + void (*set_nmi_line)(int linestate); + void (*set_irq_line)(int irqline, int linestate); + void (*set_irq_callback)(int(*callback)(int irqline)); + void (*internal_interrupt)(int type); + void (*cpu_state_save)(void *file); + void (*cpu_state_load)(void *file); + const char* (*cpu_info)(void *context,int regnum); + unsigned (*cpu_dasm)(char *buffer,unsigned pc); + unsigned num_irqs; + int default_vector; + int *icount; + double overclock; + int no_int, irq_int, nmi_int; + int (*memory_read)(int offset); + void (*memory_write)(int offset, int data); + void (*set_op_base)(int pc); + int address_shift; + unsigned address_bits, endianess, align_unit, max_inst_len; + unsigned abits1, abits2, abitsmin; +}; + +extern struct cpu_interface cpuintf[]; + +void cpu_init(void); +void cpu_run(void); + +/* optional watchdog */ +void watchdog_reset_w(int offset,int data); +int watchdog_reset_r(int offset); +/* Use this function to reset the machine */ +void machine_reset(void); +/* Use this function to reset a single CPU */ +void cpu_set_reset_line(int cpu,int state); +/* Use this function to halt a single CPU */ +void cpu_set_halt_line(int cpu,int state); + +/* This function returns CPUNUM current status (running or halted) */ +int cpu_getstatus(int cpunum); +int cpu_gettotalcpu(void); +int cpu_getactivecpu(void); +void cpu_setactivecpu(int cpunum); + +/* Returns the current program counter */ +unsigned cpu_get_pc(void); +/* Set the current program counter */ +void cpu_set_pc(unsigned val); + +/* Returns the current stack pointer */ +unsigned cpu_get_sp(void); +/* Set the current stack pointer */ +void cpu_set_sp(unsigned val); + +/* Get the active CPUs context and return it's size */ +unsigned cpu_get_context(void *context); +/* Set the active CPUs context */ +void cpu_set_context(void *context); + +/* Returns a specific register value (mamedbg) */ +unsigned cpu_get_reg(int regnum); +/* Sets a specific register value (mamedbg) */ +void cpu_set_reg(int regnum, unsigned val); + +/* Returns previous pc (start of opcode causing read/write) */ +/* int cpu_getpreviouspc(void); */ +#define cpu_getpreviouspc() cpu_get_reg(REG_PREVIOUSPC) + +/* Returns the return address from the top of the stack (Z80 only) */ +/* int cpu_getreturnpc(void); */ +/* This can now be handled with a generic function */ +#define cpu_geturnpc() cpu_get_reg(REG_SP_CONTENTS) + +int cycles_currently_ran(void); +int cycles_left_to_run(void); + +/* Returns the number of CPU cycles which take place in one video frame */ +int cpu_gettotalcycles(void); +/* Returns the number of CPU cycles before the next interrupt handler call */ +int cpu_geticount(void); +/* Returns the number of CPU cycles before the end of the current video frame */ +int cpu_getfcount(void); +/* Returns the number of CPU cycles in one video frame */ +int cpu_getfperiod(void); +/* Scales a given value by the ratio of fcount / fperiod */ +int cpu_scalebyfcount(int value); +/* Returns the current scanline number */ +int cpu_getscanline(void); +/* Returns the amount of time until a given scanline */ +double cpu_getscanlinetime(int scanline); +/* Returns the duration of a single scanline */ +double cpu_getscanlineperiod(void); +/* Returns the duration of a single scanline in cycles */ +int cpu_getscanlinecycles(void); +/* Returns the number of cycles since the beginning of this frame */ +int cpu_getcurrentcycles(void); +/* Returns the current horizontal beam position in pixels */ +int cpu_gethorzbeampos(void); +/* + Returns the number of times the interrupt handler will be called before + the end of the current video frame. This is can be useful to interrupt + handlers to synchronize their operation. If you call this from outside + an interrupt handler, add 1 to the result, i.e. if it returns 0, it means + that the interrupt handler will be called once. +*/ +int cpu_getiloops(void); + +/* Returns the current VBLANK state */ +int cpu_getvblank(void); + +/* Returns the number of the video frame we are currently playing */ +int cpu_getcurrentframe(void); + + +/* generate a trigger after a specific period of time */ +void cpu_triggertime (double duration, int trigger); +/* generate a trigger now */ +void cpu_trigger (int trigger); + +/* burn CPU cycles until a timer trigger */ +void cpu_spinuntil_trigger (int trigger); +/* burn CPU cycles until the next interrupt */ +void cpu_spinuntil_int (void); +/* burn CPU cycles until our timeslice is up */ +void cpu_spin (void); +/* burn CPU cycles for a specific period of time */ +void cpu_spinuntil_time (double duration); + +/* yield our timeslice for a specific period of time */ +void cpu_yielduntil_trigger (int trigger); +/* yield our timeslice until the next interrupt */ +void cpu_yielduntil_int (void); +/* yield our current timeslice */ +void cpu_yield (void); +/* yield our timeslice for a specific period of time */ +void cpu_yielduntil_time (double duration); + +/* set the NMI line state for a CPU, normally use PULSE_LINE */ +void cpu_set_nmi_line(int cpunum, int state); +/* set the IRQ line state for a specific irq line of a CPU */ +/* normally use state HOLD_LINE, irqline 0 for first IRQ type of a cpu */ +void cpu_set_irq_line(int cpunum, int irqline, int state); +/* this is to be called by CPU cores only! */ +void cpu_generate_internal_interrupt(int cpunum, int type); +/* set the vector to be returned during a CPU's interrupt acknowledge cycle */ +void cpu_irq_line_vector_w(int cpunum, int irqline, int vector); + +/* use these in your write memory/port handles to set an IRQ vector */ +/* offset corresponds to the irq line number here */ +void cpu_0_irq_line_vector_w(int offset, int data); +void cpu_1_irq_line_vector_w(int offset, int data); +void cpu_2_irq_line_vector_w(int offset, int data); +void cpu_3_irq_line_vector_w(int offset, int data); +void cpu_4_irq_line_vector_w(int offset, int data); +void cpu_5_irq_line_vector_w(int offset, int data); +void cpu_6_irq_line_vector_w(int offset, int data); +void cpu_7_irq_line_vector_w(int offset, int data); + +/* Obsolete functions: avoid to use them in new drivers if possible. */ + +/* cause an interrupt on a CPU */ +void cpu_cause_interrupt(int cpu,int type); +void cpu_clear_pending_interrupts(int cpu); +void interrupt_enable_w(int offset,int data); +void interrupt_vector_w(int offset,int data); +int interrupt(void); +int nmi_interrupt(void); +int m68_level1_irq(void); +int m68_level2_irq(void); +int m68_level3_irq(void); +int m68_level4_irq(void); +int m68_level5_irq(void); +int m68_level6_irq(void); +int m68_level7_irq(void); +int ignore_interrupt(void); + +/* CPU context access */ +void* cpu_getcontext (int _activecpu); +int cpu_is_saving_context(int _activecpu); + +/*************************************************************************** + * Get information for the currently active CPU + * cputype is a value from the CPU enum in driver.h + ***************************************************************************/ +/* Return number of address bits */ +unsigned cpu_address_bits(void); +/* Return address mask */ +unsigned cpu_address_mask(void); +/* Return address shift factor (TMS34010 bit addressing mode) */ +int cpu_address_shift(void); +/* Return endianess of the emulated CPU (CPU_IS_LE or CPU_IS_BE) */ +unsigned cpu_endianess(void); +/* Return opcode align unit (1 byte, 2 word, 4 dword) */ +unsigned cpu_align_unit(void); +/* Return maximum instruction length */ +unsigned cpu_max_inst_len(void); + +/* Return name of the active CPU */ +const char *cpu_name(void); +/* Return family name of the active CPU */ +const char *cpu_core_family(void); +/* Return core version of the active CPU */ +const char *cpu_core_version(void); +/* Return core filename of the active CPU */ +const char *cpu_core_file(void); +/* Return credits info for of the active CPU */ +const char *cpu_core_credits(void); +/* Return register layout definition for the active CPU */ +const char *cpu_reg_layout(void); +/* Return (debugger) window layout definition for the active CPU */ +const char *cpu_win_layout(void); + +/* Disassemble an instruction at PC into the given buffer */ +unsigned cpu_dasm(char *buffer, unsigned pc); +/* Return a string describing the currently set flag (status) bits of the active CPU */ +const char *cpu_flags(void); +/* Return a string with a register name and hex value for the active CPU */ +/* regnum is a value defined in the CPU cores header files */ +const char *cpu_dump_reg(int regnum); +/* Return a string describing the active CPUs current state */ +const char *cpu_dump_state(void); + +/*************************************************************************** + * Get information for a specific CPU type + * cputype is a value from the CPU enum in driver.h + ***************************************************************************/ +/* Return address shift factor */ +/* TMS320C10 -1: word addressing mode, TMS34010 3: bit addressing mode */ +int cputype_address_shift(int cputype); +/* Return number of address bits */ +unsigned cputype_address_bits(int cputype); +/* Return address mask */ +unsigned cputype_address_mask(int cputype); +/* Return endianess of the emulated CPU (CPU_IS_LE or CPU_IS_BE) */ +unsigned cputype_endianess(int cputype); +/* Return opcode align unit (1 byte, 2 word, 4 dword) */ +unsigned cputype_align_unit(int cputype); +/* Return maximum instruction length */ +unsigned cputype_max_inst_len(int cputype); + +/* Return name of the CPU */ +const char *cputype_name(int cputype); +/* Return family name of the CPU */ +const char *cputype_core_family(int cputype); +/* Return core version number of the CPU */ +const char *cputype_core_version(int cputype); +/* Return core filename of the CPU */ +const char *cputype_core_file(int cputype); +/* Return credits for the CPU core */ +const char *cputype_core_credits(int cputype); +/* Return register layout definition for the CPU core */ +const char *cputype_reg_layout(int cputype); +/* Return (debugger) window layout definition for the CPU core */ +const char *cputype_win_layout(int cputype); + +/*************************************************************************** + * Get (or set) information for a numbered CPU of the running machine + * cpunum is a value between 0 and cpu_gettotalcpu() - 1 + ***************************************************************************/ +/* Return number of address bits */ +unsigned cpunum_address_bits(int cputype); +/* Return address mask */ +unsigned cpunum_address_mask(int cputype); +/* Return endianess of the emulated CPU (CPU_LSB_FIRST or CPU_MSB_FIRST) */ +unsigned cpunum_endianess(int cputype); +/* Return opcode align unit (1 byte, 2 word, 4 dword) */ +unsigned cpunum_align_unit(int cputype); +/* Return maximum instruction length */ +unsigned cpunum_max_inst_len(int cputype); + +/* Get a register value for the specified CPU number of the running machine */ +unsigned cpunum_get_reg(int cpunum, int regnum); +/* Set a register value for the specified CPU number of the running machine */ +void cpunum_set_reg(int cpunum, int regnum, unsigned val); + +/* Return (debugger) register layout definition for the CPU core */ +const char *cpunum_reg_layout(int cpunum); +/* Return (debugger) window layout definition for the CPU core */ +const char *cpunum_win_layout(int cpunum); + +unsigned cpunum_dasm(int cpunum,char *buffer,unsigned pc); +/* Return a string describing the currently set flag (status) bits of the CPU */ +const char *cpunum_flags(int cpunum); +/* Return a string with a register name and value */ +/* regnum is a value defined in the CPU cores header files */ +const char *cpunum_dump_reg(int cpunum, int regnum); +/* Return a string describing the CPUs current state */ +const char *cpunum_dump_state(int cpunum); +/* Return a name for the specified cpu number */ +const char *cpunum_name(int cpunum); +/* Return a family name for the specified cpu number */ +const char *cpunum_core_family(int cpunum); +/* Return a version for the specified cpu number */ +const char *cpunum_core_version(int cpunum); +/* Return a the source filename for the specified cpu number */ +const char *cpunum_core_file(int cpunum); +/* Return a the credits for the specified cpu number */ +const char *cpunum_core_credits(int cpunum); + +/* Dump all of the running machines CPUs state to stderr */ +void cpu_dump_states(void); + +/* daisy-chain link */ +typedef struct { + void (*reset)(int); /* reset callback */ + int (*interrupt_entry)(int); /* entry callback */ + void (*interrupt_reti)(int); /* reti callback */ + int irq_param; /* callback paramater */ +} Z80_DaisyChain; + +#define Z80_MAXDAISY 4 /* maximum of daisy chan device */ + +#define Z80_INT_REQ 0x01 /* interrupt request mask */ +#define Z80_INT_IEO 0x02 /* interrupt disable mask(IEO) */ + +#define Z80_VECTOR(device,state) (((device)<<8)|(state)) + +#ifndef INLINE +#define INLINE inline +#endif + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +#define cpu_readmem16 memory_read +#define cpu_readport16 memory_readport +#define cpu_writeport16 memory_writeport +#define cpu_writemem16 memory_write +#define cpu_readop memory_readop +#define cpu_readop_arg memory_read +#define logerror(x, ...) +#define change_pc16(x) +#define CALL_MAME_DEBUG + +#define ADDRESS_SPACES 3 /* maximum number of address spaces */ +#define ADDRESS_SPACE_PROGRAM 0 /* program address space */ +#define ADDRESS_SPACE_DATA 1 /* data address space */ +#define ADDRESS_SPACE_IO 2 /* I/O address space */ + +enum +{ + /* internal flags (not for use by drivers!) */ + INTERNAL_CLEAR_LINE = 100 + CLEAR_LINE, + INTERNAL_ASSERT_LINE = 100 + ASSERT_LINE, + + /* input lines */ + MAX_INPUT_LINES = 32+3, + INPUT_LINE_IRQ0 = 0, + INPUT_LINE_IRQ1 = 1, + INPUT_LINE_IRQ2 = 2, + INPUT_LINE_IRQ3 = 3, + INPUT_LINE_IRQ4 = 4, + INPUT_LINE_IRQ5 = 5, + INPUT_LINE_IRQ6 = 6, + INPUT_LINE_IRQ7 = 7, + INPUT_LINE_IRQ8 = 8, + INPUT_LINE_IRQ9 = 9, + INPUT_LINE_NMI = MAX_INPUT_LINES - 3, + + /* special input lines that are implemented in the core */ + INPUT_LINE_RESET = MAX_INPUT_LINES - 2, + INPUT_LINE_HALT = MAX_INPUT_LINES - 1, + + /* output lines */ + MAX_OUTPUT_LINES = 32 +}; + +enum +{ + /* --- the following bits of info are returned as 64-bit signed integers --- */ + CPUINFO_INT_FIRST = 0x00000, + + CPUINFO_INT_CONTEXT_SIZE = CPUINFO_INT_FIRST, /* R/O: size of CPU context in bytes */ + CPUINFO_INT_INPUT_LINES, /* R/O: number of input lines */ + CPUINFO_INT_OUTPUT_LINES, /* R/O: number of output lines */ + CPUINFO_INT_DEFAULT_IRQ_VECTOR, /* R/O: default IRQ vector */ + CPUINFO_INT_ENDIANNESS, /* R/O: either CPU_IS_BE or CPU_IS_LE */ + CPUINFO_INT_CLOCK_DIVIDER, /* R/O: internal clock divider */ + CPUINFO_INT_MIN_INSTRUCTION_BYTES, /* R/O: minimum bytes per instruction */ + CPUINFO_INT_MAX_INSTRUCTION_BYTES, /* R/O: maximum bytes per instruction */ + CPUINFO_INT_MIN_CYCLES, /* R/O: minimum cycles for a single instruction */ + CPUINFO_INT_MAX_CYCLES, /* R/O: maximum cycles for a single instruction */ + + CPUINFO_INT_DATABUS_WIDTH, /* R/O: data bus size for each address space (8,16,32,64) */ + CPUINFO_INT_DATABUS_WIDTH_LAST = CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACES - 1, + CPUINFO_INT_ADDRBUS_WIDTH, /* R/O: address bus size for each address space (12-32) */ + CPUINFO_INT_ADDRBUS_WIDTH_LAST = CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACES - 1, + CPUINFO_INT_ADDRBUS_SHIFT, /* R/O: shift applied to addresses each address space (+3 means >>3, -1 means <<1) */ + CPUINFO_INT_ADDRBUS_SHIFT_LAST = CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACES - 1, + + CPUINFO_INT_SP, /* R/W: the current stack pointer value */ + CPUINFO_INT_PC, /* R/W: the current PC value */ + CPUINFO_INT_PREVIOUSPC, /* R/W: the previous PC value */ + CPUINFO_INT_INPUT_STATE, /* R/W: states for each input line */ + CPUINFO_INT_INPUT_STATE_LAST = CPUINFO_INT_INPUT_STATE + MAX_INPUT_LINES - 1, + CPUINFO_INT_OUTPUT_STATE, /* R/W: states for each output line */ + CPUINFO_INT_OUTPUT_STATE_LAST = CPUINFO_INT_OUTPUT_STATE + MAX_OUTPUT_LINES - 1, + CPUINFO_INT_REGISTER, /* R/W: values of up to MAX_REGs registers */ + CPUINFO_INT_REGISTER_LAST = CPUINFO_INT_REGISTER + MAX_REGS - 1, + + CPUINFO_INT_CPU_SPECIFIC = 0x08000, /* R/W: CPU-specific values start here */ + + /* --- the following bits of info are returned as pointers to data or functions --- */ + CPUINFO_PTR_FIRST = 0x10000, + + CPUINFO_PTR_SET_INFO = CPUINFO_PTR_FIRST, /* R/O: void (*set_info)(UINT32 state, INT64 data, void *ptr) */ + CPUINFO_PTR_GET_CONTEXT_, /* R/O: void (*get_context)(void *buffer) */ + CPUINFO_PTR_SET_CONTEXT_, /* R/O: void (*set_context)(void *buffer) */ + CPUINFO_PTR_INIT, /* R/O: void (*init)(void) */ + CPUINFO_PTR_RESET, /* R/O: void (*reset)(void *param) */ + CPUINFO_PTR_EXIT, /* R/O: void (*exit)(void) */ + CPUINFO_PTR_EXECUTE, /* R/O: int (*execute)(int cycles) */ + CPUINFO_PTR_BURN, /* R/O: void (*burn)(int cycles) */ + CPUINFO_PTR_DISASSEMBLE, /* R/O: void (*disassemble)(char *buffer, offs_t pc) */ + CPUINFO_PTR_IRQ_CALLBACK, /* R/W: int (*irqcallback)(int state) */ + CPUINFO_PTR_INSTRUCTION_COUNTER, /* R/O: int *icount */ + CPUINFO_PTR_REGISTER_LAYOUT, /* R/O: struct debug_register_layout *layout */ + CPUINFO_PTR_WINDOW_LAYOUT, /* R/O: struct debug_window_layout *layout */ + CPUINFO_PTR_INTERNAL_MEMORY_MAP, /* R/O: construct_map_t map */ + CPUINFO_PTR_INTERNAL_MEMORY_MAP_LAST = CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACES - 1, + CPUINFO_PTR_DEBUG_REGISTER_LIST, /* R/O: int *list: list of registers for NEW_DEBUGGER */ + + CPUINFO_PTR_CPU_SPECIFIC = 0x18000, /* R/W: CPU-specific values start here */ + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + CPUINFO_STR_FIRST = 0x20000, + + CPUINFO_STR_NAME = CPUINFO_STR_FIRST, /* R/O: name of the CPU */ + CPUINFO_STR_CORE_FAMILY, /* R/O: family of the CPU */ + CPUINFO_STR_CORE_VERSION, /* R/O: version of the CPU core */ + CPUINFO_STR_CORE_FILE, /* R/O: file containing the CPU core */ + CPUINFO_STR_CORE_CREDITS, /* R/O: credits for the CPU core */ + CPUINFO_STR_FLAGS, /* R/O: string representation of the main flags value */ + CPUINFO_STR_REGISTER, /* R/O: string representation of up to MAX_REGs registers */ + CPUINFO_STR_REGISTER_LAST = CPUINFO_STR_REGISTER + MAX_REGS - 1, + + CPUINFO_STR_CPU_SPECIFIC = 0x28000 /* R/W: CPU-specific values start here */ +}; + +#endif /* CPUINTRF_H */ diff --git a/plugins/ao/eng_dsf/aica.c b/plugins/ao/eng_dsf/aica.c new file mode 100644 index 00000000..09855a04 --- /dev/null +++ b/plugins/ao/eng_dsf/aica.c @@ -0,0 +1,1282 @@ +/* + Sega/Yamaha AICA emulation + By ElSemi, kingshriek, and R. Belmont + + This is effectively a 64-voice SCSP, with the following differences: + - No FM mode + - A third sample format (ADPCM) has been added + - Some minor other tweeks +*/ + +#include <math.h> +#include <string.h> +#include "ao.h" +#include "cpuintrf.h" +#include "aica.h" +#include "aicadsp.h" +#include "dc_hw.h" + +#define ICLIP16(x) (x<-32768)?-32768:((x>32767)?32767:x) + +#define SHIFT 12 +#define FIX(v) ((UINT32) ((float) (1<<SHIFT)*(v))) + + +#define EG_SHIFT 16 + +#define USEDSP + +// include the LFO handling code +#include "aicalfo.c" + +/* + AICA features 64 programmable slots + that can generate PCM and ADPCM (from ROM/RAM) sound +*/ + +//SLOT PARAMETERS +#define KEYONEX(slot) ((slot->udata.data[0x0]>>0x0)&0x8000) +#define KEYONB(slot) ((slot->udata.data[0x0]>>0x0)&0x4000) +#define SSCTL(slot) ((slot->udata.data[0x0]>>0xA)&0x0001) +#define LPCTL(slot) ((slot->udata.data[0x0]>>0x9)&0x0001) +#define PCMS(slot) ((slot->udata.data[0x0]>>0x7)&0x0003) + +#define SA(slot) (((slot->udata.data[0x0]&0x7F)<<16)|(slot->udata.data[0x4/2])) + +#define LSA(slot) (slot->udata.data[0x8/2]) + +#define LEA(slot) (slot->udata.data[0xc/2]) + +#define D2R(slot) ((slot->udata.data[0x10/2]>>0xB)&0x001F) +#define D1R(slot) ((slot->udata.data[0x10/2]>>0x6)&0x001F) +#define AR(slot) ((slot->udata.data[0x10/2]>>0x0)&0x001F) + +#define LPSLNK(slot) ((slot->udata.data[0x14/2]>>0x0)&0x4000) +#define KRS(slot) ((slot->udata.data[0x14/2]>>0xA)&0x000F) +#define DL(slot) ((slot->udata.data[0x14/2]>>0x5)&0x001F) +#define RR(slot) ((slot->udata.data[0x14/2]>>0x0)&0x001F) + +#define TL(slot) ((slot->udata.data[0x28/2]>>0x8)&0x00FF) + +#define OCT(slot) ((slot->udata.data[0x18/2]>>0xB)&0x000F) +#define FNS(slot) ((slot->udata.data[0x18/2]>>0x0)&0x03FF) + +#define LFORE(slot) ((slot->udata.data[0x1c/2]>>0x0)&0x8000) +#define LFOF(slot) ((slot->udata.data[0x1c/2]>>0xA)&0x001F) +#define PLFOWS(slot) ((slot->udata.data[0x1c/2]>>0x8)&0x0003) +#define PLFOS(slot) ((slot->udata.data[0x1c/2]>>0x5)&0x0007) +#define ALFOWS(slot) ((slot->udata.data[0x1c/2]>>0x3)&0x0003) +#define ALFOS(slot) ((slot->udata.data[0x1c/2]>>0x0)&0x0007) + +#define ISEL(slot) ((slot->udata.data[0x20/2]>>0x0)&0x000F) +#define IMXL(slot) ((slot->udata.data[0x20/2]>>0x4)&0x000F) + +#define DISDL(slot) ((slot->udata.data[0x24/2]>>0x8)&0x000F) +#define DIPAN(slot) ((slot->udata.data[0x24/2]>>0x0)&0x001F) + +#define EFSDL(slot) ((AICA->EFSPAN[slot*4]>>8)&0x000f) +#define EFPAN(slot) ((AICA->EFSPAN[slot*4]>>0)&0x001f) + +//Envelope times in ms +static const double ARTimes[64]={100000/*infinity*/,100000/*infinity*/,8100.0,6900.0,6000.0,4800.0,4000.0,3400.0,3000.0,2400.0,2000.0,1700.0,1500.0, + 1200.0,1000.0,860.0,760.0,600.0,500.0,430.0,380.0,300.0,250.0,220.0,190.0,150.0,130.0,110.0,95.0, + 76.0,63.0,55.0,47.0,38.0,31.0,27.0,24.0,19.0,15.0,13.0,12.0,9.4,7.9,6.8,6.0,4.7,3.8,3.4,3.0,2.4, + 2.0,1.8,1.6,1.3,1.1,0.93,0.85,0.65,0.53,0.44,0.40,0.35,0.0,0.0}; +static const double DRTimes[64]={100000/*infinity*/,100000/*infinity*/,118200.0,101300.0,88600.0,70900.0,59100.0,50700.0,44300.0,35500.0,29600.0,25300.0,22200.0,17700.0, + 14800.0,12700.0,11100.0,8900.0,7400.0,6300.0,5500.0,4400.0,3700.0,3200.0,2800.0,2200.0,1800.0,1600.0,1400.0,1100.0, + 920.0,790.0,690.0,550.0,460.0,390.0,340.0,270.0,230.0,200.0,170.0,140.0,110.0,98.0,85.0,68.0,57.0,49.0,43.0,34.0, + 28.0,25.0,22.0,18.0,14.0,12.0,11.0,8.5,7.1,6.1,5.4,4.3,3.6,3.1}; +static UINT32 FNS_Table[0x400]; +static INT32 EG_TABLE[0x400]; + +typedef enum {ATTACK,DECAY1,DECAY2,RELEASE} _STATE; +struct _EG +{ + int volume; // + _STATE state; + int step; + //step vals + int AR; //Attack + int D1R; //Decay1 + int D2R; //Decay2 + int RR; //Release + + int DL; //Decay level + UINT8 LPLINK; +}; + +struct _SLOT +{ + union + { + UINT16 data[0x40]; //only 0x1a bytes used + UINT8 datab[0x80]; + } udata; + UINT8 active; //this slot is currently playing + UINT8 *base; //samples base address + UINT32 prv_addr; // previous play address (for ADPCM) + UINT32 cur_addr; //current play address (24.8) + UINT32 nxt_addr; //next play address + UINT32 step; //pitch step (24.8) + UINT8 Backwards; //the wave is playing backwards + struct _EG EG; //Envelope + struct _EG FEG; //filter envelope + struct _LFO PLFO; //Phase LFO + struct _LFO ALFO; //Amplitude LFO + int slot; + int cur_sample; //current ADPCM sample + int cur_quant; //current ADPCM step + int curstep; + int cur_lpquant, cur_lpsample, cur_lpstep; + UINT8 *adbase, *adlpbase; + UINT8 mslc; // monitored? +}; + + +#define MEM4B(aica) ((aica->udata.data[0]>>0x0)&0x0200) +#define DAC18B(aica) ((aica->udata.data[0]>>0x0)&0x0100) +#define MVOL(aica) ((aica->udata.data[0]>>0x0)&0x000F) +#define RBL(aica) ((aica->udata.data[2]>>0xD)&0x0003) +#define RBP(aica) ((aica->udata.data[2]>>0x0)&0x0fff) +#define MOFULL(aica) ((aica->udata.data[4]>>0x0)&0x1000) +#define MOEMPTY(aica) ((aica->udata.data[4]>>0x0)&0x0800) +#define MIOVF(aica) ((aica->udata.data[4]>>0x0)&0x0400) +#define MIFULL(aica) ((aica->udata.data[4]>>0x0)&0x0200) +#define MIEMPTY(aica) ((aica->udata.data[4]>>0x0)&0x0100) + +#define AFSEL(aica) ((aica->udata.data[6]>>0x0)&0x4000) +#define MSLC(aica) ((aica->udata.data[6]>>0x8)&0x3F) + +#define SCILV0(aica) ((aica->udata.data[0xa8/2]>>0x0)&0xff) +#define SCILV1(aica) ((aica->udata.data[0xac/2]>>0x0)&0xff) +#define SCILV2(aica) ((aica->udata.data[0xb0/2]>>0x0)&0xff) + +#define SCIEX0 0 +#define SCIEX1 1 +#define SCIEX2 2 +#define SCIMID 3 +#define SCIDMA 4 +#define SCIIRQ 5 +#define SCITMA 6 +#define SCITMB 7 + +struct _AICA +{ + union + { + UINT16 data[0xc0/2]; + UINT8 datab[0xc0]; + } udata; + UINT16 IRQL, IRQR; + UINT16 EFSPAN[0x48]; + struct _SLOT Slots[64]; + signed short RINGBUF[64]; + unsigned char BUFPTR; + unsigned char *AICARAM; + UINT32 AICARAM_LENGTH; + char Master; + void (*IntARMCB)(struct sARM7 *cpu, int irq); + + INT32 *buffertmpl, *buffertmpr; + + UINT32 IrqTimA; + UINT32 IrqTimBC; + UINT32 IrqMidi; + + UINT8 MidiOutW,MidiOutR; + UINT8 MidiStack[16]; + UINT8 MidiW,MidiR; + + int LPANTABLE[0x20000]; + int RPANTABLE[0x20000]; + + int TimPris[3]; + int TimCnt[3]; + + // DMA stuff + UINT32 aica_dmea; + UINT16 aica_drga; + UINT16 aica_dtlg; + + int ARTABLE[64], DRTABLE[64]; + + struct _AICADSP DSP; + + struct sARM7 *cpu; + + INT16 *bufferl; + INT16 *bufferr; + + int length; + + signed short *RBUFDST; //this points to where the sample will be stored in the RingBuf +}; + +//static struct _AICA *AllocedAICA; + +static const float SDLT[16]={-1000000.0,-42.0,-39.0,-36.0,-33.0,-30.0,-27.0,-24.0,-21.0,-18.0,-15.0,-12.0,-9.0,-6.0,-3.0,0.0}; + +static unsigned char DecodeSCI(struct _AICA *AICA, unsigned char irq) +{ + unsigned char SCI=0; + unsigned char v; + v=(SCILV0((AICA))&(1<<irq))?1:0; + SCI|=v; + v=(SCILV1((AICA))&(1<<irq))?1:0; + SCI|=v<<1; + v=(SCILV2((AICA))&(1<<irq))?1:0; + SCI|=v<<2; + return SCI; +} + +static void ResetInterrupts(struct _AICA *AICA) +{ +#if 0 + UINT32 reset = AICA->udata.data[0xa4/2]; + if (reset & 0x40) + AICA->IntARMCB(-AICA->IrqTimA); + if (reset & 0x180) + AICA->IntARMCB(-AICA->IrqTimBC); +#endif +} + +static void CheckPendingIRQ(struct _AICA *AICA) +{ + UINT32 pend=AICA->udata.data[0xa0/2]; + UINT32 en=AICA->udata.data[0x9c/2]; + if(AICA->MidiW!=AICA->MidiR) + { + AICA->IRQL = AICA->IrqMidi; + AICA->IntARMCB(AICA->cpu, 1); + return; + } + if(!pend) + return; + if(pend&0x40) + if(en&0x40) + { + AICA->IRQL = AICA->IrqTimA; + AICA->IntARMCB(AICA->cpu, 1); + return; + } + if(pend&0x80) + if(en&0x80) + { + AICA->IRQL = AICA->IrqTimBC; + AICA->IntARMCB(AICA->cpu, 1); + return; + } + if(pend&0x100) + if(en&0x100) + { + AICA->IRQL = AICA->IrqTimBC; + AICA->IntARMCB(AICA->cpu, 1); + return; + } +} + +static int Get_AR(struct _AICA *AICA,int base,int R) +{ + int Rate=base+(R<<1); + if(Rate>63) Rate=63; + if(Rate<0) Rate=0; + return AICA->ARTABLE[Rate]; +} + +static int Get_DR(struct _AICA *AICA,int base,int R) +{ + int Rate=base+(R<<1); + if(Rate>63) Rate=63; + if(Rate<0) Rate=0; + return AICA->DRTABLE[Rate]; +} + +static int Get_RR(struct _AICA *AICA,int base,int R) +{ + int Rate=base+(R<<1); + if(Rate>63) Rate=63; + if(Rate<0) Rate=0; + return AICA->DRTABLE[Rate]; +} + +static void Compute_EG(struct _AICA *AICA,struct _SLOT *slot) +{ + int octave=OCT(slot); + int rate; + if(octave&8) octave=octave-16; + if(KRS(slot)!=0xf) + rate=octave+2*KRS(slot)+((FNS(slot)>>9)&1); + else + rate=0; //rate=((FNS(slot)>>9)&1); + + slot->EG.volume=0x17f<<EG_SHIFT; + slot->EG.AR=Get_AR(AICA,rate,AR(slot)); + slot->EG.D1R=Get_DR(AICA,rate,D1R(slot)); + slot->EG.D2R=Get_DR(AICA,rate,D2R(slot)); + slot->EG.RR=Get_RR(AICA,rate,RR(slot)); + slot->EG.DL=0x1f-DL(slot); +} + +static void AICA_StopSlot(struct _SLOT *slot,int keyoff); + +static int EG_Update(struct _SLOT *slot) +{ + switch(slot->EG.state) + { + case ATTACK: + slot->EG.volume+=slot->EG.AR; + if(slot->EG.volume>=(0x3ff<<EG_SHIFT)) + { + if (!LPSLNK(slot)) + { + slot->EG.state=DECAY1; + if(slot->EG.D1R>=(1024<<EG_SHIFT)) //Skip DECAY1, go directly to DECAY2 + slot->EG.state=DECAY2; + } + slot->EG.volume=0x3ff<<EG_SHIFT; + } + break; + case DECAY1: + slot->EG.volume-=slot->EG.D1R; + if(slot->EG.volume<=0) + slot->EG.volume=0; + if(slot->EG.volume>>(EG_SHIFT+5)<slot->EG.DL) + slot->EG.state=DECAY2; + break; + case DECAY2: + if(D2R(slot)==0) + return (slot->EG.volume>>EG_SHIFT)<<(SHIFT-10); + slot->EG.volume-=slot->EG.D2R; + if(slot->EG.volume<=0) + slot->EG.volume=0; + + break; + case RELEASE: + slot->EG.volume-=slot->EG.RR; + if(slot->EG.volume<=0) + { + slot->EG.volume=0; + AICA_StopSlot(slot,0); +// slot->EG.volume=0x17f<<EG_SHIFT; +// slot->EG.state=ATTACK; + } + break; + default: + return 1<<SHIFT; + } + return (slot->EG.volume>>EG_SHIFT)<<(SHIFT-10); +} + +static UINT32 AICA_Step(struct _SLOT *slot) +{ + int octave=OCT(slot); + UINT32 Fn; + + Fn=(FNS_Table[FNS(slot)]); //24.8 + if(octave&8) + Fn>>=(16-octave); + else + Fn<<=octave; + + return Fn/(44100); +} + + +static void Compute_LFO(struct _SLOT *slot) +{ + if(PLFOS(slot)!=0) + AICALFO_ComputeStep(&(slot->PLFO),LFOF(slot),PLFOWS(slot),PLFOS(slot),0); + if(ALFOS(slot)!=0) + AICALFO_ComputeStep(&(slot->ALFO),LFOF(slot),ALFOWS(slot),ALFOS(slot),1); +} + +#define ADPCMSHIFT 8 +#define ADFIX(f) (int) ((float) f*(float) (1<<ADPCMSHIFT)) + +const int TableQuant[8]={ADFIX(0.8984375),ADFIX(0.8984375),ADFIX(0.8984375),ADFIX(0.8984375),ADFIX(1.19921875),ADFIX(1.59765625),ADFIX(2.0),ADFIX(2.3984375)}; +const int quant_mul[16]= { 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15}; + +void InitADPCM(int *PrevSignal, int *PrevQuant) +{ + *PrevSignal=0; + *PrevQuant=0x7f; +} + +INLINE signed short DecodeADPCM(int *PrevSignal, unsigned char Delta, int *PrevQuant) +{ + int x = *PrevQuant * quant_mul [Delta & 15]; + x = *PrevSignal + ((int)(x + ((UINT32)x >> 29)) >> 3); + *PrevSignal=ICLIP16(x); + *PrevQuant=(*PrevQuant*TableQuant[Delta&7])>>ADPCMSHIFT; + *PrevQuant=(*PrevQuant<0x7f)?0x7f:((*PrevQuant>0x6000)?0x6000:*PrevQuant); + return *PrevSignal; +} + +static void AICA_StartSlot(struct _AICA *AICA, struct _SLOT *slot) +{ + UINT64 start_offset; + + slot->active=1; + slot->Backwards=0; + slot->cur_addr=0; slot->nxt_addr=1<<SHIFT; slot->prv_addr=-1; + start_offset = SA(slot); // AICA can play 16-bit samples from any boundry + slot->base=&AICA->AICARAM[start_offset]; + slot->step=AICA_Step(slot); + Compute_EG(AICA,slot); + slot->EG.state=ATTACK; + slot->EG.volume=0x17f<<EG_SHIFT; + Compute_LFO(slot); + + if (PCMS(slot) >= 2) + { + UINT8 *base; + UINT32 curstep, steps_to_go; + + slot->curstep = 0; + slot->adbase = (unsigned char *) (AICA->AICARAM+((SA(slot))&0x7fffff)); + InitADPCM(&(slot->cur_sample), &(slot->cur_quant)); + InitADPCM(&(slot->cur_lpsample), &(slot->cur_lpquant)); + + // walk to the ADPCM state at LSA + curstep = 0; + base = slot->adbase; + steps_to_go = LSA(slot); + + while (curstep < steps_to_go) + { + int shift1, delta1; + shift1 = 4*((curstep&1)); + delta1 = (*base>>shift1)&0xf; + DecodeADPCM(&(slot->cur_lpsample),delta1,&(slot->cur_lpquant)); + curstep++; + if (!(curstep & 1)) + { + base++; + } + } + + slot->cur_lpstep = curstep; + slot->adlpbase = base; + + // on real hardware this creates undefined behavior. + if (LSA(slot) > LEA(slot)) + { + slot->udata.data[0xc/2] = 0xffff; + } + } +} + +static void AICA_StopSlot(struct _SLOT *slot,int keyoff) +{ + if(keyoff /*&& slot->EG.state!=RELEASE*/) + { + slot->EG.state=RELEASE; + } + else + { + slot->active=0; + } + slot->udata.data[0]&=~0x4000; + +} + +#define log_base_2(n) (log((float) n)/log((float) 2)) + +static void AICA_Init(struct _AICA *AICA, const struct AICAinterface *intf) +{ + printf ("AICA_Init(cpu=%p)\n", intf->cpu); + int i=0; + + AICA->IrqTimA = AICA->IrqTimBC = AICA->IrqMidi = 0; + AICA->MidiR=AICA->MidiW=0; + AICA->MidiOutR=AICA->MidiOutW=0; + + // get AICA RAM + { + memset(AICA,0,sizeof(*AICA)); + + if (!i) + { + AICA->Master=1; + } + else + { + AICA->Master=0; + } + + if (intf->region) + { + AICA->AICARAM = &intf->cpu->dc_ram[0]; + AICA->AICARAM_LENGTH = 2*1024*1024; + AICA->DSP.AICARAM = (UINT16 *)AICA->AICARAM; + AICA->DSP.AICARAM_LENGTH = (2*1024*1024)/2; + AICA->cpu = intf->cpu; + } + } + + for(i=0;i<0x400;++i) + { + float fcent=(double) 1200.0*log_base_2((double)(((double) 1024.0+(double)i)/(double)1024.0)); + fcent=(double) 44100.0*pow(2.0,fcent/1200.0); + FNS_Table[i]=(float) (1<<SHIFT) *fcent; + } + + for(i=0;i<0x400;++i) + { + float envDB=((float)(3*(i-0x3ff)))/32.0; + float scale=(float)(1<<SHIFT); + EG_TABLE[i]=(INT32)(pow(10.0,envDB/20.0)*scale); + } + + for(i=0;i<0x20000;++i) + { + int iTL =(i>>0x0)&0xff; + int iPAN=(i>>0x8)&0x1f; + int iSDL=(i>>0xD)&0x0F; + float TL=1.0; + float SegaDB=0; + float fSDL=1.0; + float PAN=1.0; + float LPAN,RPAN; + + if(iTL&0x01) SegaDB-=0.4; + if(iTL&0x02) SegaDB-=0.8; + if(iTL&0x04) SegaDB-=1.5; + if(iTL&0x08) SegaDB-=3; + if(iTL&0x10) SegaDB-=6; + if(iTL&0x20) SegaDB-=12; + if(iTL&0x40) SegaDB-=24; + if(iTL&0x80) SegaDB-=48; + + TL=pow(10.0,SegaDB/20.0); + + SegaDB=0; + if(iPAN&0x1) SegaDB-=3; + if(iPAN&0x2) SegaDB-=6; + if(iPAN&0x4) SegaDB-=12; + if(iPAN&0x8) SegaDB-=24; + + if((iPAN&0xf)==0xf) PAN=0.0; + else PAN=pow(10.0,SegaDB/20.0); + + if(iPAN<0x10) + { + LPAN=PAN; + RPAN=1.0; + } + else + { + RPAN=PAN; + LPAN=1.0; + } + + if(iSDL) + fSDL=pow(10.0,(SDLT[iSDL])/20.0); + else + fSDL=0.0; + + AICA->LPANTABLE[i]=FIX((4.0*LPAN*TL*fSDL)); + AICA->RPANTABLE[i]=FIX((4.0*RPAN*TL*fSDL)); + } + + AICA->ARTABLE[0]=AICA->DRTABLE[0]=0; //Infinite time + AICA->ARTABLE[1]=AICA->DRTABLE[1]=0; //Infinite time + for(i=2;i<64;++i) + { + double t,step,scale; + t=ARTimes[i]; //In ms + if(t!=0.0) + { + step=(1023*1000.0)/((float) 44100.0f*t); + scale=(double) (1<<EG_SHIFT); + AICA->ARTABLE[i]=(int) (step*scale); + } + else + AICA->ARTABLE[i]=1024<<EG_SHIFT; + + t=DRTimes[i]; //In ms + step=(1023*1000.0)/((float) 44100.0f*t); + scale=(double) (1<<EG_SHIFT); + AICA->DRTABLE[i]=(int) (step*scale); + } + + // make sure all the slots are off + for(i=0;i<64;++i) + { + AICA->Slots[i].slot=i; + AICA->Slots[i].active=0; + AICA->Slots[i].base=NULL; + AICA->Slots[i].EG.state=RELEASE; + AICA->Slots[i].mslc=0; + } + + AICALFO_Init(); + AICA->buffertmpl=(signed int*) malloc(44100*sizeof(signed int)); + AICA->buffertmpr=(signed int*) malloc(44100*sizeof(signed int)); + memset(AICA->buffertmpl,0,44100*sizeof(signed int)); + memset(AICA->buffertmpr,0,44100*sizeof(signed int)); + + // no "pend" + AICA[0].udata.data[0xa0/2] = 0; + //AICA[1].udata.data[0x20/2] = 0; + AICA->TimCnt[0] = 0xffff; + AICA->TimCnt[1] = 0xffff; + AICA->TimCnt[2] = 0xffff; +} + +static void AICA_UpdateSlotReg(struct _AICA *AICA,int s,int r) +{ + struct _SLOT *slot=AICA->Slots+s; + int sl; + switch(r&0x7f) + { + case 0: + case 1: + if(KEYONEX(slot)) + { + for(sl=0;sl<64;++sl) + { + struct _SLOT *s2=AICA->Slots+sl; + { + if(KEYONB(s2) && s2->EG.state==RELEASE/*&& !s2->active*/) + { + if(s2->mslc) AICA->udata.data[0x10] &= 0x7FFF; // reset LP at KEY_ON + AICA_StartSlot(AICA, s2); + + #if 0 + printf("StartSlot[%02X]: SSCTL %01X SA %06X LSA %04X LEA %04X PCMS %01X LPCTL %01X\n",sl,SSCTL(s2),SA(s2),LSA(s2),LEA(s2),PCMS(s2),LPCTL(s2)); + printf(" AR %02X D1R %02X D2R %02X RR %02X DL %02X KRS %01X LPSLNK %01X\n",AR(s2),D1R(s2),D2R(s2),RR(s2),DL(s2),KRS(s2),LPSLNK(s2)>>14); + printf(" TL %02X OCT %01X FNS %03X\n",TL(s2),OCT(s2),FNS(s2)); + printf(" LFORE %01X LFOF %02X ALFOWS %01X ALFOS %01X PLFOWS %01X PLFOS %01X\n",LFORE(s2),LFOF(s2),ALFOWS(s2),ALFOS(s2),PLFOWS(s2),PLFOS(s2)); + printf(" IMXL %01X ISEL %01X DISDL %01X DIPAN %02X\n",IMXL(s2),ISEL(s2),DISDL(s2),DIPAN(s2)); + printf("\n"); + fflush(stdout); + #endif + } + if(!KEYONB(s2) /*&& s2->active*/) + { + AICA_StopSlot(s2,1); + } + } + } + slot->udata.data[0]&=~0x8000; + } + break; + case 0x18: + case 0x19: + slot->step=AICA_Step(slot); + break; + case 0x14: + case 0x15: + slot->EG.RR=Get_RR(AICA,0,RR(slot)); + slot->EG.DL=0x1f-DL(slot); + break; + case 0x1c: + case 0x1d: + Compute_LFO(slot); + break; + case 0x24: +// printf("[%02d]: %x to DISDL/DIPAN (PC=%x)\n", s, slot->udata.data[0x24/2], arm7_get_register(15)); + break; + } +} + +static void AICA_UpdateReg(struct _AICA *AICA, int reg) +{ + switch(reg&0xff) + { + case 0x4: + case 0x5: + { + unsigned int v=RBL(AICA); + AICA->DSP.RBP=RBP(AICA); + if(v==0) + AICA->DSP.RBL=8*1024; + else if(v==1) + AICA->DSP.RBL=16*1024; + else if(v==2) + AICA->DSP.RBL=32*1024; + else if(v==3) + AICA->DSP.RBL=64*1024; + } + break; + case 0x8: + case 0x9: + AICA_MidiIn(AICA, 0, AICA->udata.data[0x8/2]&0xff, 0); + break; + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + break; + case 0x90: + case 0x91: + if(AICA->Master) + { + AICA->TimPris[0]=1<<((AICA->udata.data[0x90/2]>>8)&0x7); + AICA->TimCnt[0]=(AICA->udata.data[0x90/2]&0xff)<<8; + } + break; + case 0x94: + case 0x95: + if(AICA->Master) + { + AICA->TimPris[1]=1<<((AICA->udata.data[0x94/2]>>8)&0x7); + AICA->TimCnt[1]=(AICA->udata.data[0x94/2]&0xff)<<8; + } + break; + case 0x98: + case 0x99: + if(AICA->Master) + { + AICA->TimPris[2]=1<<((AICA->udata.data[0x98/2]>>8)&0x7); + AICA->TimCnt[2]=(AICA->udata.data[0x98/2]&0xff)<<8; + } + break; + case 0xa4: //SCIRE + case 0xa5: + + if(AICA->Master) + { + AICA->udata.data[0xa0/2] &= ~AICA->udata.data[0xa4/2]; + ResetInterrupts(AICA); + + // behavior from real hardware (SCSP, assumed to carry over): if you SCIRE a timer that's expired, + // it'll immediately pop up again + if (AICA->TimCnt[0] >= 0xff00) + { + AICA->udata.data[0xa0/2] |= 0x40; + } + if (AICA->TimCnt[1] >= 0xff00) + { + AICA->udata.data[0xa0/2] |= 0x80; + } + if (AICA->TimCnt[2] >= 0xff00) + { + AICA->udata.data[0xa0/2] |= 0x100; + } + } + break; + case 0xa8: + case 0xa9: + case 0xac: + case 0xad: + case 0xb0: + case 0xb1: + if(AICA->Master) + { + AICA->IrqTimA=DecodeSCI(AICA,SCITMA); + AICA->IrqTimBC=DecodeSCI(AICA,SCITMB); + AICA->IrqMidi=DecodeSCI(AICA,SCIMID); + } + break; + } +} + +static void AICA_UpdateSlotRegR(struct _AICA *AICA, int slot,int reg) +{ + +} + +static void AICA_UpdateRegR(struct _AICA *AICA, int reg) +{ + switch(reg&0xff) + { + case 8: + case 9: + { + unsigned short v=AICA->udata.data[0x8/2]; + v&=0xff00; + v|=AICA->MidiStack[AICA->MidiR]; + AICA->IntARMCB(AICA->cpu, 0); // cancel the IRQ + if(AICA->MidiR!=AICA->MidiW) + { + ++AICA->MidiR; + AICA->MidiR&=15; + } + AICA->udata.data[0x8/2]=v; + } + break; + + case 0x10: // LP check + case 0x11: + { + //int MSLC = (AICA->udata.data[0xc/2]>>8) & 0x3f; // which slot are we monitoring? + } + break; + + case 0x14: // CA (slot address) + case 0x15: + { + int MSLC = (AICA->udata.data[0xc/2]>>8) & 0x3f; // which slot are we monitoring? + unsigned int CA = AICA->Slots[MSLC].cur_addr>>(SHIFT+12); + + AICA->udata.data[0x14/2] = CA; + } + break; + } +} + +static void AICA_w16(struct _AICA *AICA,unsigned int addr,unsigned short val) +{ + addr&=0xffff; + if(addr<0x2000) + { + int slot=addr/0x80; + addr&=0x7f; +// printf("%x to slot %d offset %x\n", val, slot, addr); + *((unsigned short *) (AICA->Slots[slot].udata.datab+(addr))) = val; + AICA_UpdateSlotReg(AICA,slot,addr&0x7f); + } + else if (addr < 0x2800) + { + if (addr <= 0x2044) + { +// printf("%x to EFSxx slot %d (addr %x)\n", val, (addr-0x2000)/4, addr&0x7f); + AICA->EFSPAN[addr&0x7f] = val; + } + } + else if(addr<0x3000) + { + if (addr < 0x28be) + { +// printf("%x to AICA global @ %x\n", val, addr & 0xff); + *((unsigned short *) (AICA->udata.datab+((addr&0xff)))) = val; + AICA_UpdateReg(AICA, addr&0xff); + } + else if (addr == 0x2d00) + { + AICA->IRQL = val; + } + else if (addr == 0x2d04) + { + AICA->IRQR = val; + + if (val) + { + AICA->IntARMCB(AICA->cpu, 0); + } + } + } + else + { + //DSP + if(addr<0x3200) //COEF + *((unsigned short *) (AICA->DSP.COEF+(addr-0x3000)/2))=val; + else if(addr<0x3400) + *((unsigned short *) (AICA->DSP.MADRS+(addr-0x3200)/2))=val; + else if(addr<0x3c00) + { + *((unsigned short *) (AICA->DSP.MPRO+(addr-0x3400)/2))=val; + + if (addr == 0x3bfe) + { + AICADSP_Start(&AICA->DSP); + } + } + } +} + +static unsigned short AICA_r16(struct _AICA *AICA, unsigned int addr) +{ + unsigned short v=0; + addr&=0xffff; + if(addr<0x2000) + { + int slot=addr/0x80; + addr&=0x7f; + AICA_UpdateSlotRegR(AICA, slot,addr&0x7f); + v=*((unsigned short *) (AICA->Slots[slot].udata.datab+(addr))); + } + else if(addr<0x3000) + { + if (addr <= 0x2044) + { + v = AICA->EFSPAN[addr&0x7f]; + } + else if (addr < 0x28be) + { + AICA_UpdateRegR(AICA, addr&0xff); + v= *((unsigned short *) (AICA->udata.datab+((addr&0xff)))); + if((addr&0xfe)==0x10) AICA->udata.data[0x10/2] &= 0x7FFF; // reset LP on read + } + else if (addr == 0x2d00) + { + return AICA->IRQL; + } + else if (addr == 0x2d04) + { + return AICA->IRQR; + } + } +// else if (addr<0x700) +// v=AICA->RINGBUF[(addr-0x600)/2]; + return v; +} + + +#define REVSIGN(v) ((~v)+1) + +void AICA_TimersAddTicks(struct _AICA *AICA, int ticks) +{ + if(AICA->TimCnt[0]<=0xff00) + { + AICA->TimCnt[0] += ticks << (8-((AICA->udata.data[0x90/2]>>8)&0x7)); + if (AICA->TimCnt[0] >= 0xFF00) + { + AICA->TimCnt[0] = 0xFFFF; + AICA->udata.data[0xa0/2]|=0x40; + } + AICA->udata.data[0x90/2]&=0xff00; + AICA->udata.data[0x90/2]|=AICA->TimCnt[0]>>8; + } + + if(AICA->TimCnt[1]<=0xff00) + { + AICA->TimCnt[1] += ticks << (8-((AICA->udata.data[0x94/2]>>8)&0x7)); + if (AICA->TimCnt[1] >= 0xFF00) + { + AICA->TimCnt[1] = 0xFFFF; + AICA->udata.data[0xa0/2]|=0x80; + } + AICA->udata.data[0x94/2]&=0xff00; + AICA->udata.data[0x94/2]|=AICA->TimCnt[1]>>8; + } + + if(AICA->TimCnt[2]<=0xff00) + { + AICA->TimCnt[2] += ticks << (8-((AICA->udata.data[0x98/2]>>8)&0x7)); + if (AICA->TimCnt[2] >= 0xFF00) + { + AICA->TimCnt[2] = 0xFFFF; + AICA->udata.data[0xa0/2]|=0x100; + } + AICA->udata.data[0x98/2]&=0xff00; + AICA->udata.data[0x98/2]|=AICA->TimCnt[2]>>8; + } +} + +INLINE INT32 AICA_UpdateSlot(struct _AICA *AICA, struct _SLOT *slot) +{ + INT32 sample, fpart; + int cur_sample; //current sample + int nxt_sample; //next sample + int step=slot->step; + UINT32 addr1,addr2; // current and next sample addresses + + if(SSCTL(slot)!=0) //no FM or noise yet + return 0; + + if(PLFOS(slot)!=0) + { + step=step*AICAPLFO_Step(&(slot->PLFO)); + step>>=SHIFT; + } + + if(PCMS(slot) == 0) + { + addr1=(slot->cur_addr>>(SHIFT-1))&0x7ffffe; + addr2=(slot->nxt_addr>>(SHIFT-1))&0x7ffffe; + } + else + { + addr1=slot->cur_addr>>SHIFT; + addr2=slot->nxt_addr>>SHIFT; + } + + if(PCMS(slot) == 1) // 8-bit signed + { + INT8 *p1=(signed char *) (AICA->AICARAM+(((SA(slot)+addr1))&0x7fffff)); + INT8 *p2=(signed char *) (AICA->AICARAM+(((SA(slot)+addr2))&0x7fffff)); + cur_sample = p1[0] << 8; + nxt_sample = p2[0] << 8; + } + else if (PCMS(slot) == 0) //16 bit signed + { + INT16 *p1=(signed short *) (AICA->AICARAM+((SA(slot)+addr1)&0x7fffff)); + INT16 *p2=(signed short *) (AICA->AICARAM+((SA(slot)+addr2)&0x7fffff)); + cur_sample = LE16(p1[0]); + nxt_sample = LE16(p2[0]); + } + else // 4-bit ADPCM + { + UINT8 *base= slot->adbase; + UINT32 steps_to_go = addr2, curstep = slot->curstep; + + if (base) + { + cur_sample = slot->cur_sample; // may already contains current decoded sample + + // seek to the interpolation sample + while (curstep < steps_to_go) + { + int shift1, delta1; + shift1 = 4*((curstep&1)); + delta1 = (*base>>shift1)&0xf; + DecodeADPCM(&(slot->cur_sample),delta1,&(slot->cur_quant)); + curstep++; + if (!(curstep & 1)) + { + base++; + } + if (curstep == addr1) + cur_sample = slot->cur_sample; + } + nxt_sample = slot->cur_sample; + + slot->adbase = base; + slot->curstep = curstep; + } + else + { + cur_sample = nxt_sample = 0; + } + } + fpart = slot->cur_addr & ((1<<SHIFT)-1); + sample=cur_sample*((1<<SHIFT)-fpart)+nxt_sample*fpart; + sample>>=SHIFT; + + slot->prv_addr=slot->cur_addr; + slot->cur_addr+=step; + slot->nxt_addr=slot->cur_addr+(1<<SHIFT); + + addr1=slot->cur_addr>>SHIFT; + addr2=slot->nxt_addr>>SHIFT; + + if(addr1>=LSA(slot)) + { + if(LPSLNK(slot) && slot->EG.state==ATTACK) + slot->EG.state = DECAY1; + } + + switch(LPCTL(slot)) + { + case 0: //no loop + if(addr2>=LSA(slot) && addr2>=LEA(slot)) // if next sample exceed then current must exceed too + { + //slot->active=0; + if(slot->mslc) AICA->udata.data[8] |= 0x8000; + AICA_StopSlot(slot,0); + } + break; + case 1: //normal loop + if(addr2>=LEA(slot)) + { + INT32 rem_addr; + if(slot->mslc) AICA->udata.data[8] |= 0x8000; + rem_addr = slot->nxt_addr - (LEA(slot)<<SHIFT); + slot->nxt_addr = (LSA(slot)<<SHIFT) + rem_addr; + if(addr1>=LEA(slot)) + { + rem_addr = slot->cur_addr - (LEA(slot)<<SHIFT); + slot->cur_addr = (LSA(slot)<<SHIFT) + rem_addr; + } + + if(PCMS(slot)>=2) + { + // restore the state @ LSA - the sampler will naturally walk to (LSA + remainder) + slot->adbase = &AICA->AICARAM[SA(slot)+(LSA(slot)/2)]; + slot->curstep = LSA(slot); + if (PCMS(slot) == 2) + { + slot->cur_sample = slot->cur_lpsample; + slot->cur_quant = slot->cur_lpquant; + } +//printf("Looping: slot_addr %x LSA %x LEA %x step %x base %x\n", slot->cur_addr>>SHIFT, LSA(slot), LEA(slot), slot->curstep, slot->adbase); + } + } + break; + } + + if(ALFOS(slot)!=0) + { + sample=sample*AICAALFO_Step(&(slot->ALFO)); + sample>>=SHIFT; + } + + if(slot->EG.state==ATTACK) + sample=(sample*EG_Update(slot))>>SHIFT; + else + sample=(sample*EG_TABLE[EG_Update(slot)>>(SHIFT-10)])>>SHIFT; + + if(slot->mslc) + { + AICA->udata.data[0x14/2] = addr1; + if (!(AFSEL(AICA))) + { + UINT16 res; + + AICA->udata.data[0x10/2] |= slot->EG.state<<13; + + res = 0x3FF - (slot->EG.volume>>EG_SHIFT); + + res *= 959; + res /= 1024; + + if (res > 959) res = 959; + + AICA->udata.data[0x10/2] = res; + + //AICA->udata.data[0x10/2] |= 0x3FF - (slot->EG.volume>>EG_SHIFT); + } + } + + return sample; +} + +static void AICA_DoMasterSamples(struct _AICA *AICA, int nsamples) +{ + INT16 *bufr,*bufl; + int sl, s, i; + + bufr=AICA->bufferr; + bufl=AICA->bufferl; + + for(s=0;s<nsamples;++s) + { + INT32 smpl, smpr; + + smpl = smpr = 0; + + // mix slots' direct output + for(sl=0;sl<64;++sl) + { + struct _SLOT *slot=AICA->Slots+sl; + slot->mslc = (MSLC(AICA)==sl); + AICA->RBUFDST=AICA->RINGBUF+AICA->BUFPTR; + if(AICA->Slots[sl].active) + { + unsigned int Enc; + signed int sample; + + sample=AICA_UpdateSlot(AICA, slot); + + Enc=((TL(slot))<<0x0)|((IMXL(slot))<<0xd); + AICADSP_SetSample(&AICA->DSP,(sample*AICA->LPANTABLE[Enc])>>(SHIFT-2),ISEL(slot),IMXL(slot)); + Enc=((TL(slot))<<0x0)|((DIPAN(slot))<<0x8)|((DISDL(slot))<<0xd); + { + smpl+=(sample*AICA->LPANTABLE[Enc])>>SHIFT; + smpr+=(sample*AICA->RPANTABLE[Enc])>>SHIFT; + } + } + + AICA->BUFPTR&=63; + } + + // process the DSP + AICADSP_Step(&AICA->DSP); + + // mix DSP output + for(i=0;i<16;++i) + { + if(EFSDL(i)) + { + unsigned int Enc=((EFPAN(i))<<0x8)|((EFSDL(i))<<0xd); + smpl+=(AICA->DSP.EFREG[i]*AICA->LPANTABLE[Enc])>>SHIFT; + smpr+=(AICA->DSP.EFREG[i]*AICA->RPANTABLE[Enc])>>SHIFT; + } + } + + *bufl++ = ICLIP16(smpl>>3); + *bufr++ = ICLIP16(smpr>>3); + + AICA_TimersAddTicks(AICA, 1); + CheckPendingIRQ(AICA); + } +} + +int AICA_IRQCB(void *param) +{ + CheckPendingIRQ(param); + return -1; +} + +void AICA_Update(struct _AICA *AICA, void *param, INT16 **inputs, INT16 **buf, int samples) +{ + AICA->bufferl = buf[0]; + AICA->bufferr = buf[1]; + AICA->length = samples; + AICA_DoMasterSamples(AICA, samples); +} + +void *aica_start(const void *config) +{ + const struct AICAinterface *intf; + + struct _AICA *AICA; + + AICA = malloc(sizeof(*AICA)); + memset(AICA, 0, sizeof(*AICA)); + + intf = config; + + // init the emulation + AICA_Init(AICA, intf); + + // set up the IRQ callbacks + { + AICA->IntARMCB = intf->irq_callback[0]; + +// AICA->stream = stream_create(0, 2, 44100, AICA, AICA_Update); + } + + return AICA; +} + +void aica_stop(struct _AICA *AICA) +{ + if (AICA->buffertmpl) { + free (AICA->buffertmpl); + } + if (AICA->buffertmpr) { + free (AICA->buffertmpr); + } + free(AICA); +} + +void AICA_set_ram_base(struct _AICA *AICA, int which, void *base) +{ + if (AICA) + { + AICA->AICARAM = base; + AICA->DSP.AICARAM = base; + } +} + +READ16_HANDLER( AICA_0_r ) +{ + UINT16 res = AICA_r16(AICA, offset*2); + +// printf("Read AICA @ %x => %x (PC=%x, R5=%x)\n", offset*2, res, arm7_get_register(15), arm7_get_register(5)); + + return res; +} + +extern UINT32* stv_scu; + +WRITE16_HANDLER( AICA_0_w ) +{ + UINT16 tmp; + + tmp = AICA_r16(AICA, offset*2); + COMBINE_DATA(&tmp); + AICA_w16(AICA,offset*2, tmp); +} + +WRITE16_HANDLER( AICA_MidiIn ) +{ + AICA->MidiStack[AICA->MidiW++]=data; + AICA->MidiW &= 15; +} + +READ16_HANDLER( AICA_MidiOutR ) +{ + unsigned char val; + + val=AICA->MidiStack[AICA->MidiR++]; + AICA->MidiR&=7; + return val; +} + diff --git a/plugins/ao/eng_dsf/aica.h b/plugins/ao/eng_dsf/aica.h new file mode 100644 index 00000000..f441064f --- /dev/null +++ b/plugins/ao/eng_dsf/aica.h @@ -0,0 +1,52 @@ +/* + + Sega/Yamaha AICA emulation +*/ + +#ifndef _AICA_H_ +#define _AICA_H_ + +#define MAX_AICA (2) + +#define COMBINE_DATA(varptr) (*(varptr) = (*(varptr) & mem_mask) | (data & ~mem_mask)) + +// convert AO types +typedef int8 data8_t; +typedef int16 data16_t; +typedef int32 data32_t; +typedef int offs_t; +struct sARM7; + +struct AICAinterface +{ + int num; + struct sARM7 *cpu; + void *region[MAX_AICA]; + int mixing_level[MAX_AICA]; /* volume */
+ void (*irq_callback[MAX_AICA])(struct sARM7 *cpu, int state); /* irq callback */ +}; + +struct _AICA; + +int AICA_sh_start(struct AICAinterface *intf); +void AICA_sh_stop(void); +void scsp_stop(void); + +#define READ16_HANDLER(name) data16_t name(struct _AICA *AICA, offs_t offset, data16_t mem_mask) +#define WRITE16_HANDLER(name) void name(struct _AICA *AICA, offs_t offset, data16_t data, data16_t mem_mask) + +// AICA register access +READ16_HANDLER( AICA_0_r ); +WRITE16_HANDLER( AICA_0_w ); +READ16_HANDLER( AICA_1_r ); +WRITE16_HANDLER( AICA_1_w ); + +// MIDI I/O access (used for comms on Model 2/3) +WRITE16_HANDLER( AICA_MidiIn ); +READ16_HANDLER( AICA_MidiOutR ); + +void *aica_start(const void *config); +void aica_stop(struct _AICA *AICA); +void AICA_Update(struct _AICA *AICA, void *param, INT16 **inputs, INT16 **buf, int samples); + +#endif diff --git a/plugins/ao/eng_dsf/aicadsp.c b/plugins/ao/eng_dsf/aicadsp.c new file mode 100644 index 00000000..b2fb5223 --- /dev/null +++ b/plugins/ao/eng_dsf/aicadsp.c @@ -0,0 +1,349 @@ +#include <assert.h> +#include <math.h> +#include "ao.h" +#include "cpuintrf.h" +#include "aica.h" +#include "aicadsp.h" + +static UINT16 PACK(INT32 val) +{ + UINT32 temp; + int sign,exponent,k; + + sign = (val >> 23) & 0x1; + temp = (val ^ (val << 1)) & 0xFFFFFF; + exponent = 0; + for (k=0; k<12; k++) + { + if (temp & 0x800000) + break; + temp <<= 1; + exponent += 1; + } + if (exponent < 12) + val = (val << exponent) & 0x3FFFFF; + else + val <<= 11; + val >>= 11; + val |= sign << 15; + val |= exponent << 11; + + return (UINT16)val; +} + +static INT32 UNPACK(UINT16 val) +{ + int sign,exponent,mantissa; + INT32 uval; + + sign = (val >> 15) & 0x1; + exponent = (val >> 11) & 0xF; + mantissa = val & 0x7FF; + uval = mantissa << 11; + if (exponent > 11) + exponent = 11; + else + uval |= (sign ^ 1) << 22; + uval |= sign << 23; + uval <<= 8; + uval >>= 8; + uval >>= exponent; + + return uval; +} + +void AICADSP_Init(struct _AICADSP *DSP) +{ + memset(DSP,0,sizeof(struct _AICADSP)); + DSP->RBL=0x8000; + DSP->Stopped=1; +} + +void AICADSP_Step(struct _AICADSP *DSP) +{ + INT32 ACC=0; //26 bit + INT32 SHIFTED=0; //24 bit + INT32 X=0; //24 bit + INT32 Y=0; //13 bit + INT32 B=0; //26 bit + INT32 INPUTS=0; //24 bit + INT32 MEMVAL=0; + INT32 FRC_REG=0; //13 bit + INT32 Y_REG=0; //24 bit + UINT32 ADDR=0; + UINT32 ADRS_REG=0; //13 bit + int step; + + if(DSP->Stopped) + return; + + memset(DSP->EFREG,0,2*16); +#if 0 + int dump=0; + FILE *f=NULL; + if(dump) + f=fopen("dsp.txt","wt"); +#endif + for(step=0;step</*128*/DSP->LastStep;++step) + { + UINT16 *IPtr=DSP->MPRO+step*8; + +// if(IPtr[0]==0 && IPtr[1]==0 && IPtr[2]==0 && IPtr[3]==0) +// break; + + UINT32 TRA=(IPtr[0]>>9)&0x7F; + UINT32 TWT=(IPtr[0]>>8)&0x01; + UINT32 TWA=(IPtr[0]>>1)&0x7F; + + UINT32 XSEL=(IPtr[2]>>15)&0x01; + UINT32 YSEL=(IPtr[2]>>13)&0x03; + UINT32 IRA=(IPtr[2]>>7)&0x3F; + UINT32 IWT=(IPtr[2]>>6)&0x01; + UINT32 IWA=(IPtr[2]>>1)&0x1F; + + UINT32 TABLE=(IPtr[4]>>15)&0x01; + UINT32 MWT=(IPtr[4]>>14)&0x01; + UINT32 MRD=(IPtr[4]>>13)&0x01; + UINT32 EWT=(IPtr[4]>>12)&0x01; + UINT32 EWA=(IPtr[4]>>8)&0x0F; + UINT32 ADRL=(IPtr[4]>>7)&0x01; + UINT32 FRCL=(IPtr[4]>>6)&0x01; + UINT32 SHIFT=(IPtr[4]>>4)&0x03; + UINT32 YRL=(IPtr[4]>>3)&0x01; + UINT32 NEGB=(IPtr[4]>>2)&0x01; + UINT32 ZERO=(IPtr[4]>>1)&0x01; + UINT32 BSEL=(IPtr[4]>>0)&0x01; + + UINT32 NOFL=(IPtr[6]>>15)&1; //???? + UINT32 COEF=step; + + UINT32 MASA=(IPtr[6]>>9)&0x3f; //??? + UINT32 ADREB=(IPtr[6]>>8)&0x1; + UINT32 NXADR=(IPtr[6]>>7)&0x1; + + INT64 v; + + //operations are done at 24 bit precision +#if 0 + if(MASA) + int a=1; + if(NOFL) + int a=1; + +// int dump=0; + + if(f) + { +#define DUMP(v) fprintf(f," " #v ": %04X",v); + + fprintf(f,"%d: ",step); + DUMP(ACC); + DUMP(SHIFTED); + DUMP(X); + DUMP(Y); + DUMP(B); + DUMP(INPUTS); + DUMP(MEMVAL); + DUMP(FRC_REG); + DUMP(Y_REG); + DUMP(ADDR); + DUMP(ADRS_REG); + fprintf(f,"\n"); + } +#endif + //INPUTS RW + assert(IRA<0x32); + if(IRA<=0x1f) + INPUTS=DSP->MEMS[IRA]; + else if(IRA<=0x2F) + INPUTS=DSP->MIXS[IRA-0x20]<<4; //MIXS is 20 bit + else if(IRA<=0x31) + INPUTS=0; + + INPUTS<<=8; + INPUTS>>=8; + //if(INPUTS&0x00800000) + // INPUTS|=0xFF000000; + + if(IWT) + { + DSP->MEMS[IWA]=MEMVAL; //MEMVAL was selected in previous MRD + if(IRA==IWA) + INPUTS=MEMVAL; + } + + //Operand sel + //B + if(!ZERO) + { + if(BSEL) + B=ACC; + else + { + B=DSP->TEMP[(TRA+DSP->DEC)&0x7F]; + B<<=8; + B>>=8; + //if(B&0x00800000) + // B|=0xFF000000; //Sign extend + } + if(NEGB) + B=0-B; + } + else + B=0; + + //X + if(XSEL) + X=INPUTS; + else + { + X=DSP->TEMP[(TRA+DSP->DEC)&0x7F]; + X<<=8; + X>>=8; + //if(X&0x00800000) + // X|=0xFF000000; + } + + //Y + if(YSEL==0) + Y=FRC_REG; + else if(YSEL==1) + Y=DSP->COEF[COEF<<1]>>3; //COEF is 16 bits + else if(YSEL==2) + Y=(Y_REG>>11)&0x1FFF; + else if(YSEL==3) + Y=(Y_REG>>4)&0x0FFF; + + if(YRL) + Y_REG=INPUTS; + + //Shifter + if(SHIFT==0) + { + SHIFTED=ACC; + if(SHIFTED>0x007FFFFF) + SHIFTED=0x007FFFFF; + if(SHIFTED<(-0x00800000)) + SHIFTED=-0x00800000; + } + else if(SHIFT==1) + { + SHIFTED=ACC*2; + if(SHIFTED>0x007FFFFF) + SHIFTED=0x007FFFFF; + if(SHIFTED<(-0x00800000)) + SHIFTED=-0x00800000; + } + else if(SHIFT==2) + { + SHIFTED=ACC*2; + SHIFTED<<=8; + SHIFTED>>=8; + //SHIFTED&=0x00FFFFFF; + //if(SHIFTED&0x00800000) + // SHIFTED|=0xFF000000; + } + else if(SHIFT==3) + { + SHIFTED=ACC; + SHIFTED<<=8; + SHIFTED>>=8; + //SHIFTED&=0x00FFFFFF; + //if(SHIFTED&0x00800000) + // SHIFTED|=0xFF000000; + } + + //ACCUM + Y<<=19; + Y>>=19; + //if(Y&0x1000) + // Y|=0xFFFFF000; + + v=(((INT64) X*(INT64) Y)>>12); + ACC=(int) v+B; + + if(TWT) + DSP->TEMP[(TWA+DSP->DEC)&0x7F]=SHIFTED; + + if(FRCL) + { + if(SHIFT==3) + FRC_REG=SHIFTED&0x0FFF; + else + FRC_REG=(SHIFTED>>11)&0x1FFF; + } + + if(MRD || MWT) + //if(0) + { + ADDR=DSP->MADRS[MASA<<1]; + if(!TABLE) + ADDR+=DSP->DEC; + if(ADREB) + ADDR+=ADRS_REG&0x0FFF; + if(NXADR) + ADDR++; + if(!TABLE) + ADDR&=DSP->RBL-1; + else + ADDR&=0xFFFF; + //ADDR<<=1; + //ADDR+=DSP->RBP<<13; + //MEMVAL=DSP->AICARAM[ADDR>>1]; + ADDR+=DSP->RBP<<10; + if(MRD && (step&1)) //memory only allowed on odd? DoA inserts NOPs on even + { + if(NOFL) + MEMVAL=DSP->AICARAM[ADDR]<<8; + else + MEMVAL=UNPACK(DSP->AICARAM[ADDR]); + } + if(MWT && (step&1)) + { + if(NOFL) + DSP->AICARAM[ADDR]=SHIFTED>>8; + else + DSP->AICARAM[ADDR]=PACK(SHIFTED); + } + } + + if(ADRL) + { + if(SHIFT==3) + ADRS_REG=(SHIFTED>>12)&0xFFF; + else + ADRS_REG=(INPUTS>>16); + } + + if(EWT) + DSP->EFREG[EWA]+=SHIFTED>>8; + + } + --DSP->DEC; + memset(DSP->MIXS,0,4*16); +// if(f) +// fclose(f); +} + +void AICADSP_SetSample(struct _AICADSP *DSP,INT32 sample,int SEL,int MXL) +{ + //DSP->MIXS[SEL]+=sample<<(MXL+1)/*7*/; + DSP->MIXS[SEL]+=sample; +// if(MXL) +// int a=1; +} + +void AICADSP_Start(struct _AICADSP *DSP) +{ + int i; + DSP->Stopped=0; + for(i=127;i>=0;--i) + { + UINT16 *IPtr=DSP->MPRO+i*8; + + if(IPtr[0]!=0 || IPtr[2]!=0 || IPtr[4]!=0 || IPtr[6]!=0) + break; + } + DSP->LastStep=i+1; + +} diff --git a/plugins/ao/eng_dsf/aicadsp.h b/plugins/ao/eng_dsf/aicadsp.h new file mode 100644 index 00000000..b10accff --- /dev/null +++ b/plugins/ao/eng_dsf/aicadsp.h @@ -0,0 +1,37 @@ +#ifndef AICADSP_H +#define AICADSP_H + +//the DSP Context +struct _AICADSP +{ +//Config + UINT16 *AICARAM; + UINT32 AICARAM_LENGTH; + UINT32 RBP; //Ring buf pointer + UINT32 RBL; //Delay ram (Ring buffer) size in words + +//context + + INT16 COEF[128*2]; //16 bit signed + UINT16 MADRS[64*2]; //offsets (in words), 16 bit + UINT16 MPRO[128*4*2*2]; //128 steps 64 bit + INT32 TEMP[128]; //TEMP regs,24 bit signed + INT32 MEMS[32]; //MEMS regs,24 bit signed + UINT32 DEC; + +//input + INT32 MIXS[16]; //MIXS, 24 bit signed + INT16 EXTS[2]; //External inputs (CDDA) 16 bit signed + +//output + INT16 EFREG[16]; //EFREG, 16 bit signed + + int Stopped; + int LastStep; +}; + +void AICADSP_Init(struct _AICADSP *DSP); +void AICADSP_SetSample(struct _AICADSP *DSP, INT32 sample, INT32 SEL, INT32 MXL); +void AICADSP_Step(struct _AICADSP *DSP); +void AICADSP_Start(struct _AICADSP *DSP); +#endif diff --git a/plugins/ao/eng_dsf/aicalfo.c b/plugins/ao/eng_dsf/aicalfo.c new file mode 100644 index 00000000..9af2ae54 --- /dev/null +++ b/plugins/ao/eng_dsf/aicalfo.c @@ -0,0 +1,159 @@ +/* + AICA LFO handling + + Part of the AICA emulator package. + (not compiled directly, #included from aica.c) + + By ElSemi, kingshriek, and R. Belmont +*/ + +#define LFO_SHIFT 8 + +struct _LFO +{ + unsigned short phase; + UINT32 phase_step; + int *table; + int *scale; +}; + +#define LFIX(v) ((unsigned int) ((float) (1<<LFO_SHIFT)*(v))) + +//Convert DB to multiply amplitude +#define DB(v) LFIX(pow(10.0,v/20.0)) + +//Convert cents to step increment +#define CENTS(v) LFIX(pow(2.0,v/1200.0)) + +static int PLFO_TRI[256],PLFO_SQR[256],PLFO_SAW[256],PLFO_NOI[256]; +static int ALFO_TRI[256],ALFO_SQR[256],ALFO_SAW[256],ALFO_NOI[256]; +static float LFOFreq[32]={0.17,0.19,0.23,0.27,0.34,0.39,0.45,0.55,0.68,0.78,0.92,1.10,1.39,1.60,1.87,2.27, + 2.87,3.31,3.92,4.79,6.15,7.18,8.60,10.8,14.4,17.2,21.5,28.7,43.1,57.4,86.1,172.3}; +static float ASCALE[8]={0.0,0.4,0.8,1.5,3.0,6.0,12.0,24.0}; +static float PSCALE[8]={0.0,7.0,13.5,27.0,55.0,112.0,230.0,494}; +static int PSCALES[8][256]; +static int ASCALES[8][256]; + +void AICALFO_Init(void) +{ + int i,s; + for(i=0;i<256;++i) + { + int a,p; +// float TL; + //Saw + a=255-i; + if(i<128) + p=i; + else + p=i-256; + ALFO_SAW[i]=a; + PLFO_SAW[i]=p; + + //Square + if(i<128) + { + a=255; + p=127; + } + else + { + a=0; + p=-128; + } + ALFO_SQR[i]=a; + PLFO_SQR[i]=p; + + //Tri + if(i<128) + a=255-(i*2); + else + a=(i*2)-256; + if(i<64) + p=i*2; + else if(i<128) + p=255-i*2; + else if(i<192) + p=256-i*2; + else + p=i*2-511; + ALFO_TRI[i]=a; + PLFO_TRI[i]=p; + + //noise + //a=lfo_noise[i]; + a=rand()&0xff; + p=128-a; + ALFO_NOI[i]=a; + PLFO_NOI[i]=p; + } + + for(s=0;s<8;++s) + { + float limit=PSCALE[s]; + for(i=-128;i<128;++i) + { + PSCALES[s][i+128]=CENTS(((limit*(float) i)/128.0)); + } + limit=-ASCALE[s]; + for(i=0;i<256;++i) + { + ASCALES[s][i]=DB(((limit*(float) i)/256.0)); + } + } +} + +signed int INLINE AICAPLFO_Step(struct _LFO *LFO) +{ + int p; + + LFO->phase+=LFO->phase_step; +#if LFO_SHIFT!=8 + LFO->phase&=(1<<(LFO_SHIFT+8))-1; +#endif + p=LFO->table[LFO->phase>>LFO_SHIFT]; + p=LFO->scale[p+128]; + return p<<(SHIFT-LFO_SHIFT); +} + +signed int INLINE AICAALFO_Step(struct _LFO *LFO) +{ + int p; + LFO->phase+=LFO->phase_step; +#if LFO_SHIFT!=8 + LFO->phase&=(1<<(LFO_SHIFT+8))-1; +#endif + p=LFO->table[LFO->phase>>LFO_SHIFT]; + p=LFO->scale[p]; + return p<<(SHIFT-LFO_SHIFT); +} + +void AICALFO_ComputeStep(struct _LFO *LFO,UINT32 LFOF,UINT32 LFOWS,UINT32 LFOS,int ALFO) +{ + float step=(float) LFOFreq[LFOF]*256.0/(float)44100.0; + LFO->phase_step=(unsigned int) ((float) (1<<LFO_SHIFT)*step); + if(ALFO) + { + switch(LFOWS) + { + case 0: LFO->table=ALFO_SAW; break; + case 1: LFO->table=ALFO_SQR; break; + case 2: LFO->table=ALFO_TRI; break; + case 3: LFO->table=ALFO_NOI; break; + default: printf("Unknown ALFO %d\n", LFOWS); + } + LFO->scale=ASCALES[LFOS]; + } + else + { + switch(LFOWS) + { + case 0: LFO->table=PLFO_SAW; break; + case 1: LFO->table=PLFO_SQR; break; + case 2: LFO->table=PLFO_TRI; break; + case 3: LFO->table=PLFO_NOI; break; + default: printf("Unknown PLFO %d\n", LFOWS); + } + LFO->scale=PSCALES[LFOS]; + } +} diff --git a/plugins/ao/eng_dsf/arm7.c b/plugins/ao/eng_dsf/arm7.c new file mode 100644 index 00000000..0bc35705 --- /dev/null +++ b/plugins/ao/eng_dsf/arm7.c @@ -0,0 +1,274 @@ +// +// ARM7 processor emulator +// version 1.6 / 2008-02-16 +// (c) Radoslaw Balcewicz +// + +#include "arm7.h" +#include "arm7i.h" + +#ifdef ARM7_THUMB +#include "arm7thumb.h" +#endif + + //-------------------------------------------------------------------------- + // definitions and macros + + /** Macro for accessing banked registers. */ +#define RX_BANK(t,r) (cpu->Rx_bank [t][r - 8]) + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + // private functions + + /** CPU Reset. */ +static void Reset (struct sARM7 *cpu); + //-------------------------------------------------------------------------- + + // private variables + + /** Table for decoding bit-coded mode to zero based index. */ +static const int s_tabTryb [32] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, ARM7_MODE_usr, ARM7_MODE_fiq, ARM7_MODE_irq, + ARM7_MODE_svc, -1, -1, -1, ARM7_MODE_abt, -1, -1, -1, ARM7_MODE_und, + -1, -1, -1, ARM7_MODE_sys}; + //-------------------------------------------------------------------------- + + + // public functions + +struct sARM7* ARM7_Alloc () +{ + struct sARM7 *cpu = malloc (sizeof (struct sARM7)); + memset (cpu, 0, sizeof (struct sARM7)); + return cpu; +} + + //-------------------------------------------------------------------------- + /** ARM7 emulator init. */ +void ARM7_Init (struct sARM7 *cpu) + { + // sane startup values + cpu->fiq = 0; + cpu->irq = 0; + cpu->carry = 0; + cpu->overflow = 0; + cpu->flagi = FALSE; + cpu->cykle = 0; + + // reset will do the rest + ARM7_HardReset (cpu); + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Power-ON reset. */ +void ARM7_HardReset (struct sARM7 *cpu) + { + // CPSR that makes sense + cpu->Rx [ARM7_CPSR] = ARM7_CPSR_I | ARM7_CPSR_F | ARM7_CPSR_M_svc; + Reset (cpu); + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Hardware reset via /RESET line. */ +void ARM7_SoftReset (struct sARM7 *cpu) + { + Reset (cpu); + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** CPSR update, possibly changing operating mode. */ +void ARM7_SetCPSR (struct sARM7 *cpu, ARM7_REG sr) + { + int stary, nowy; + + stary = s_tabTryb [ARM7_CPSR_M (cpu->Rx [ARM7_CPSR])]; + nowy = s_tabTryb [ARM7_CPSR_M (sr)]; + // do we have to change modes? + if (nowy != stary) + { + // save this mode registers + RX_BANK (stary, ARM7_SP) = cpu->Rx [ARM7_SP], + RX_BANK (stary, ARM7_LR) = cpu->Rx [ARM7_LR], + RX_BANK (stary, ARM7_SPSR) = cpu->Rx [ARM7_SPSR]; + if (stary == ARM7_MODE_fiq) + { + // copy R8-R12 + RX_BANK (ARM7_MODE_fiq, 8) = cpu->Rx [8], + RX_BANK (ARM7_MODE_fiq, 9) = cpu->Rx [9], + RX_BANK (ARM7_MODE_fiq, 10) = cpu->Rx [10], + RX_BANK (ARM7_MODE_fiq, 11) = cpu->Rx [11], + RX_BANK (ARM7_MODE_fiq, 12) = cpu->Rx [12]; + cpu->Rx [8] = RX_BANK (ARM7_MODE_usr, 8), + cpu->Rx [9] = RX_BANK (ARM7_MODE_usr, 9), + cpu->Rx [10] = RX_BANK (ARM7_MODE_usr, 10), + cpu->Rx [11] = RX_BANK (ARM7_MODE_usr, 11), + cpu->Rx [12] = RX_BANK (ARM7_MODE_usr, 12); + } + + // fetch new mode registers + cpu->Rx [ARM7_SP] = RX_BANK (nowy, ARM7_SP), + cpu->Rx [ARM7_LR] = RX_BANK (nowy, ARM7_LR), + cpu->Rx [ARM7_SPSR] = RX_BANK (nowy, ARM7_SPSR); + if (nowy == ARM7_MODE_fiq) + { + // copy R8-R12 + RX_BANK (ARM7_MODE_usr, 8) = cpu->Rx [8], + RX_BANK (ARM7_MODE_usr, 9) = cpu->Rx [9], + RX_BANK (ARM7_MODE_usr, 10) = cpu->Rx [10], + RX_BANK (ARM7_MODE_usr, 11) = cpu->Rx [11], + RX_BANK (ARM7_MODE_usr, 12) = cpu->Rx [12]; + cpu->Rx [8] = RX_BANK (ARM7_MODE_fiq, 8), + cpu->Rx [9] = RX_BANK (ARM7_MODE_fiq, 9), + cpu->Rx [10] = RX_BANK (ARM7_MODE_fiq, 10), + cpu->Rx [11] = RX_BANK (ARM7_MODE_fiq, 11), + cpu->Rx [12] = RX_BANK (ARM7_MODE_fiq, 12); + } + } + + // new CPSR value + cpu->Rx [ARM7_CPSR] = sr; + + // mode change could've enabled interrups, so we test for those and set + // appropriate flag for the instruction loop to catch + if (cpu->fiq) + cpu->flagi |= ARM7_FL_FIQ; +#ifndef ARM7_DREAMCAST + if (cpu->irq) + cpu->flagi |= ARM7_FL_IRQ; +#endif + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Sets FIQ line state. */ +void ARM7_SetFIQ (struct sARM7 *cpu, int stan) + { + stan = stan ? TRUE : FALSE; + // we catch changes only + if (stan ^ cpu->fiq) + { + cpu->fiq = stan; + if (cpu->fiq) + cpu->flagi |= ARM7_FL_FIQ; + } + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Sets IRQ line state. */ +void ARM7_SetIRQ (struct sARM7 *cpu, int stan) + { + stan = stan ? TRUE : FALSE; + // we catch changes only + if (stan ^ cpu->irq) + { + cpu->irq = stan; + if (cpu->irq) + cpu->flagi |= ARM7_FL_IRQ; + } + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Tests for pending interrupts, switches to one if possible. */ +void ARM7_CheckIRQ (struct sARM7 *cpu) + { + UINT32 sr = cpu->Rx [ARM7_CPSR]; + + // clear all interrupt flags + cpu->flagi &= ~(ARM7_FL_FIQ | ARM7_FL_IRQ); + + // check for pending interrupts we can switch to + // (FIQ can interrupt IRQ, but not the other way around) + if (cpu->fiq) + { + if (!(sr & ARM7_CPSR_F)) + { + // FIQ + ARM7_SetCPSR (cpu, ARM7_CPSR_MX (sr, ARM7_CPSR_M_fiq) | ARM7_CPSR_F | ARM7_CPSR_I); + cpu->Rx [ARM7_SPSR] = sr; + // set new PC (return from interrupt will subtract 4) + cpu->Rx [ARM7_LR] = cpu->Rx [ARM7_PC] + 4; + cpu->Rx [ARM7_PC] = 0x0000001c; + } + } +#ifndef ARM7_DREAMCAST + if (cpu->irq) + { + if (!(sr & ARM7_CPSR_I)) + { + // IRQ + ARM7_SetCPSR (cpu, ARM7_CPSR_MX (sr, ARM7_CPSR_M_irq) | ARM7_CPSR_I); + cpu->Rx [ARM7_SPSR] = sr; + // set new PC (return from interrupt will subtract 4) + cpu->Rx [ARM7_LR] = cpu->Rx [ARM7_PC] + 4; + cpu->Rx [ARM7_PC] = 0x00000018; + cpu->irq = 0; + } + } +#endif + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Single step. */ +void ARM7_Step (struct sARM7 *cpu) +{ + // make a step +#ifdef ARM7_THUMB + if (cpu->Rx[ARM7_CPSR] & ARM7_CPSR_T) + { + ARM7i_Thumb_Step(cpu); + } + else +#endif + { + ARM7i_Step (cpu); + } + // and test interrupts + ARM7_CheckIRQ (cpu); +} + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Runs emulation for at least n cycles, returns actual amount of cycles + burned - normal interpreter. */ +int ARM7_Execute (struct sARM7 *cpu, int n) + { + cpu->cykle = 0; + while (cpu->cykle < n) + { + ARM7_CheckIRQ (cpu); + while (!cpu->flagi && cpu->cykle < n) + // make one step, sum up cycles + cpu->cykle += ARM7i_Step (cpu); + } + return cpu->cykle; + } + //-------------------------------------------------------------------------- + + + // private functions + + + //-------------------------------------------------------------------------- + /** CPU Reset. */ +void Reset (struct sARM7 *cpu) + { + // clear ALU flags + cpu->carry = 0; + cpu->overflow = 0; + // test CPSR mode and pick a valid one if necessary + if (s_tabTryb [ARM7_CPSR_M (cpu->Rx [ARM7_CPSR])] < 0) + cpu->Rx [ARM7_CPSR] = ARM7_CPSR_I | ARM7_CPSR_F | ARM7_CPSR_M_svc; + // set up registers according to manual + RX_BANK (ARM7_MODE_svc, ARM7_LR) = cpu->Rx [ARM7_PC]; + RX_BANK (ARM7_MODE_svc, ARM7_SPSR) = cpu->Rx [ARM7_CPSR]; + ARM7_SetCPSR (cpu, ARM7_CPSR_I | ARM7_CPSR_F | ARM7_CPSR_M_svc); + cpu->Rx [ARM7_PC] = 0x00000000; + } + //-------------------------------------------------------------------------- diff --git a/plugins/ao/eng_dsf/arm7.h b/plugins/ao/eng_dsf/arm7.h new file mode 100644 index 00000000..3c9a47db --- /dev/null +++ b/plugins/ao/eng_dsf/arm7.h @@ -0,0 +1,169 @@ +// +// ARM7 processor emulator +// version 1.6 / 2008-02-16 +// (c) Radoslaw Balcewicz +// + +#ifndef _ARM7_h_ +#define _ARM7_h_ + +#include "cpuintrf.h" +#include "aica.h" + + //-------------------------------------------------------------------------- + // definitions and macros + + /** If defined, will turn on specific behavior emulation, as well as some + optimizations that are valid only for Dreamcast AICA. */ +#define ARM7_DREAMCAST + + /** Define to enable Thumb support for ARM7. */ +//#define ARM7_THUMB + + // sanity tests +#ifdef ARM7_DREAMCAST + #ifdef ARM7_THUMB + #warning "Dreamcast ARM7 is a -DI type, it doesn't support Thumb mode." + #endif +#else +// #warning "Instructions cycle counts might not be correct." +#endif + + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + // CPU definitions + + /** Status flags in CPSR register. */ +#define ARM7_CPSR_N (1 << 31) +#define ARM7_CPSR_Z (1 << 30) +#define ARM7_CPSR_C (1 << 29) +#define ARM7_CPSR_V (1 << 28) +#define ARM7_CPSR_I (1 << 7) +#define ARM7_CPSR_F (1 << 6) +#define ARM7_CPSR_T (1 << 5) + /** CPSR bit mask for current operating mode. */ +#define ARM7_CPSR_M(x) ((x) & 0x1f) +#define ARM7_CPSR_MX(sr,x) (((sr) & ~0x1f) | ((x) & 0x1f)) + /** Bit combinations for each operating mode. */ +#define ARM7_CPSR_M_usr 0x10 +#define ARM7_CPSR_M_fiq 0x11 +#define ARM7_CPSR_M_irq 0x12 +#define ARM7_CPSR_M_svc 0x13 +#define ARM7_CPSR_M_abt 0x17 +#define ARM7_CPSR_M_und 0x11 +#define ARM7_CPSR_M_sys 0x1f + + /** Control flags for ARM7 core. */ +#define ARM7_FL_FIQ (1 << 0) +#define ARM7_FL_IRQ (1 << 1) + + /** Operating modes. */ +#define ARM7_MODE_usr 0 +#define ARM7_MODE_fiq 1 +#define ARM7_MODE_irq 2 +#define ARM7_MODE_svc 3 +#define ARM7_MODE_abt 4 +#define ARM7_MODE_und 5 +#define ARM7_MODE_sys 0 + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + // register definitions + + /** ARM7 register type (all are 32-bit). */ +typedef INT32 ARM7_REG; + +enum +{ + ARM7_R0 = 0, ARM7_R1, ARM7_R2, ARM7_R3, ARM7_R4, ARM7_R5, ARM7_R6, ARM7_R7, + ARM7_R8, ARM7_R9, ARM7_R10, ARM7_R11, ARM7_R12, ARM7_R13, ARM7_R14, ARM7_R15 +}; + + /** R13 is stack pointer. */ +#define ARM7_SP 13 + /** R14 is link/return address. */ +#define ARM7_LR 14 + /** R15 is program counter. */ +#define ARM7_PC 15 + /** CPSR control register. */ +#define ARM7_CPSR 16 + /** SPSR control register. */ +#define ARM7_SPSR 17 + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** ARM7 CPU state structure. */ +struct sARM7 + { + /** All-purpose and control registers (for current mode). */ + ARM7_REG Rx [18]; + /** Banked registers for all operating modes. */ + ARM7_REG Rx_bank [6][10]; + + /** FIQ and IRQ interrupt requests. */ + int fiq, irq; + + /** Carry flag for barrel shifter and ALU operations. */ + int carry; + /** Overflow flag for arithmetic instructions. */ + int overflow; + + /** Emulation control flags. */ + int flagi; + + /** Instruction code. */ + UINT32 kod; + /** Cycle counter. */ + int cykle; + + uint8 dc_ram[8*1024*1024]; + + struct AICAinterface aica_interface; + struct _AICA *AICA; + }; + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + // public procedures + + /** ARM7 allocate spu state. */ +struct sARM7* ARM7_Alloc (void); + + /** ARM7 emulator init. */ +void ARM7_Init (struct sARM7 *cpu); + + /** Power-ON reset. */ +void ARM7_HardReset (struct sARM7 *cpu); + /** Hardware reset via /RESET line. */ +void ARM7_SoftReset (struct sARM7 *cpu); + + /** CPSR update, possibly changing operating mode. */ +void ARM7_SetCPSR (struct sARM7 *cpu, ARM7_REG sr); + + /** Sets FIQ line state. */ +void ARM7_SetFIQ (struct sARM7 *cpu, int stan); + /** Sets IRQ line state. */ +void ARM7_SetIRQ (struct sARM7 *cpu, int stan); + + /** Tests for pending interrupts, switches to one if possible. */ +void ARM7_CheckIRQ (struct sARM7 *cpu); + + /** Single step. */ +void ARM7_Step (struct sARM7 *cpu); + /** Runs emulation for at least n cycles, returns actual amount of cycles + burned - normal interpreter. */ +int ARM7_Execute (struct sARM7 *cpu, int n); + //-------------------------------------------------------------------------- + +enum +{ + ARM7_IRQ_LINE=0, ARM7_FIRQ_LINE, + ARM7_NUM_LINES +}; + +#ifdef ENABLE_DEBUGGER +extern UINT32 arm7_disasm( struct sARM7 *cpu, char *pBuf, UINT32 pc, UINT32 opcode ); +extern UINT32 thumb_disasm( struct sARM7 *cpu, char *pBuf, UINT32 pc, UINT16 opcode ); +#endif +#endif diff --git a/plugins/ao/eng_dsf/arm7i.c b/plugins/ao/eng_dsf/arm7i.c new file mode 100644 index 00000000..1b831857 --- /dev/null +++ b/plugins/ao/eng_dsf/arm7i.c @@ -0,0 +1,1340 @@ +// +// ARM7 processor emulator - interpreter core +// version 1.6 / 2008-02-16 +// (c) Radoslaw Balcewicz +// + +#include "arm7.h" +#include "arm7i.h" +#include "dc_hw.h" + + //-------------------------------------------------------------------------- + // definitions and macros + + /** PC is being incremented after every instruction fetch, so we adjust for + that on all stores and jumps. */ +#define PC_ADJUSTMENT (-4) + + /** Memory access routines. */ +#include "arm7memil.c" + + /** Bit shifts compatible with IA32. */ +#define SHL(w, k) (((UINT32)(w)) << (k)) +#define SHR(w, k) (((UINT32)(w)) >> (k)) +#define SAR(w, k) (((INT32)(w)) >> (k)) +#define ROR(w, k) (SHR (w, k) | SHL (w, 32 - (k))) + + /** Byte rotation for unaligned 32-bit read. */ +#define RBOD(w, i) (ROR (w, (i) * 8)) + + /** Data processing macros. */ +#define NEG(i) ((i) & (1 << 31)) +#define POS(i) (~(i) & (1 << 31)) +#define ADDCARRY(a, b, c) \ + ((NEG (a) & NEG (b)) |\ + (NEG (a) & POS (c)) |\ + (NEG (b) & POS (c))) ? 1 : 0; +#define ADDOVERFLOW(a, b, c) \ + ((NEG (a) & NEG (b) & POS (c)) |\ + (POS (a) & POS (b) & NEG (c))) ? 1 : 0; +#define SUBCARRY(a, b, c) \ + ((NEG (a) & POS (b)) |\ + (NEG (a) & POS (c)) |\ + (POS (b) & POS (c))) ? 1 : 0; +#define SUBOVERFLOW(a, b, c)\ + ((NEG (a) & POS (b) & POS (c)) |\ + (POS (a) & NEG (b) & NEG (c))) ? 1 : 0; + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + // private functions + + /** Condition EQ. */ +static int R_WEQ (struct sARM7 *cpu); + /** Condition NE. */ +static int R_WNE (struct sARM7 *cpu); + /** Condition CS. */ +static int R_WCS (struct sARM7 *cpu); + /** Condition CC. */ +static int R_WCC (struct sARM7 *cpu); + /** Condition MI. */ +static int R_WMI (struct sARM7 *cpu); + /** Condition PL. */ +static int R_WPL (struct sARM7 *cpu); + /** Condition VS. */ +static int R_WVS (struct sARM7 *cpu); + /** Condition VC. */ +static int R_WVC (struct sARM7 *cpu); + /** Condition HI. */ +static int R_WHI (struct sARM7 *cpu); + /** Condition LS. */ +static int R_WLS (struct sARM7 *cpu); + /** Condition GE. */ +static int R_WGE (struct sARM7 *cpu); + /** Condition LT. */ +static int R_WLT (struct sARM7 *cpu); + /** Condition GT. */ +static int R_WGT (struct sARM7 *cpu); + /** Condition LE. */ +static int R_WLE (struct sARM7 *cpu); + /** Condition AL. */ +static int R_WAL (struct sARM7 *cpu); + /** Undefined condition. */ +static int R_Wxx (struct sARM7 *cpu); + + /** Calculates barrel shifter output. */ +static UINT32 WyliczPrzes (struct sARM7 *cpu); + /** Logical shift left. */ +static UINT32 LSL_x (struct sARM7 *cpu, UINT32 w, int i); + /** Logical shift right. */ +static UINT32 LSR_x (struct sARM7 *cpu, UINT32 w, int i); + /** Arithmetic shift right. */ +static UINT32 ASR_x (struct sARM7 *cpu, UINT32 w, int i); + /** Rotate right. */ +static UINT32 ROR_x (struct sARM7 *cpu, UINT32 w, int i); + /** Rotate right extended. */ +static UINT32 RRX_1 (struct sARM7 *cpu, UINT32 w); + + /** Group 00x opcodes. */ +static void R_G00x (struct sARM7 *cpu); + /** Multiply instructions. */ +static void R_MUL_MLA (struct sARM7 *cpu); + /** Single data swap. */ +static void R_SWP (struct sARM7 *cpu); + /** PSR Transfer. */ +static void R_PSR (struct sARM7 *cpu); + /** Data processing instructions. */ +static void R_DP (struct sARM7 *cpu); + /** Data processing result writeback. */ +static void R_WynikDP (struct sARM7 *cpu, ARM7_REG w); + /** Data processing flags writeback. */ +static void R_FlagiDP (struct sARM7 *cpu, ARM7_REG w); + /** Single data transfer. */ +static void R_SDT (struct sARM7 *cpu); + /** Rozkaz "Undefined". */ +static void R_Und (struct sARM7 *cpu); + /** Block Data Transfer. */ +static void R_BDT (struct sARM7 *cpu); + /** Block load instructions. */ +static void R_LDM (struct sARM7 *cpu, int Rn, UINT32 adres); + /** Block store instructions. */ +static void R_STM (struct sARM7 *cpu, int Rn, UINT32 adres); + /** Branch/Branch with link. */ +static void R_B_BL (struct sARM7 *cpu); + /** Group 110 opcodes. */ +static void R_G110 (struct sARM7 *cpu); + /** Group 111 opcodes. */ +static void R_G111 (struct sARM7 *cpu); + +#ifdef ARM7_THUMB + /** Halfword and Signed Data Transfer. */ +static void R_HSDT (struct sARM7 *cpu); +#endif + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + // private data + + /** Flag testing functions for conditional execution. */ +static int (*s_tabWar [16]) (struct sARM7 *cpu) = {R_WEQ, R_WNE, R_WCS, R_WCC, R_WMI, R_WPL, + R_WVS, R_WVC, R_WHI, R_WLS, R_WGE, R_WLT, R_WGT, R_WLE, R_WAL, R_Wxx}; + /** Handler table for instruction groups. */ +static void (*s_tabGrup [8]) (struct sARM7 *cpu) = {R_G00x, R_G00x, R_SDT, R_SDT, R_BDT, + R_B_BL, R_G110, R_G111}; + /** Data processing instructions split to arithmetic and logical. */ +static int s_tabAL [16] = {FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, + FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE}; + + /** Cycles it took for current instruction to complete. */ +static int s_cykle; + //-------------------------------------------------------------------------- + + + // public functions + + + //-------------------------------------------------------------------------- + /** Single step, returns number of burned cycles. */ +int ARM7i_Step (struct sARM7 *cpu) + { + cpu->kod = arm7_read_32 (cpu, cpu->Rx [ARM7_PC] & ~3); + + // we increment PC here, and if there's a load from memory it will simply + // overwrite it (all PC modyfing code should be aware of this) + cpu->Rx [ARM7_PC] += 4; + s_cykle = 2; + // condition test and group selection + if (s_tabWar [(cpu->kod >> 28) & 15] (cpu)) + s_tabGrup [(cpu->kod >> 25) & 7] (cpu); + return s_cykle; + } + //-------------------------------------------------------------------------- + + + // private functions + + + //-------------------------------------------------------------------------- + /** Condition EQ. */ +int R_WEQ (struct sARM7 *cpu) + { + // "Z set" + return cpu->Rx [ARM7_CPSR] & ARM7_CPSR_Z; + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Condition NE. */ +int R_WNE (struct sARM7 *cpu) + { + // "Z clear" + return !(cpu->Rx [ARM7_CPSR] & ARM7_CPSR_Z); + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Condition CS. */ +int R_WCS (struct sARM7 *cpu) + { + // "C set" + return cpu->Rx [ARM7_CPSR] & ARM7_CPSR_C; + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Condition CC. */ +int R_WCC (struct sARM7 *cpu) + { + // "C clear" + return !(cpu->Rx [ARM7_CPSR] & ARM7_CPSR_C); + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Condition MI. */ +int R_WMI (struct sARM7 *cpu) + { + // "N set" + return cpu->Rx [ARM7_CPSR] & ARM7_CPSR_N; + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Condition PL. */ +int R_WPL (struct sARM7 *cpu) + { + // "N clear" + return !(cpu->Rx [ARM7_CPSR] & ARM7_CPSR_N); + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Condition VS. */ +int R_WVS (struct sARM7 *cpu) + { + // "V set" + return cpu->Rx [ARM7_CPSR] & ARM7_CPSR_V; + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Condition VC. */ +int R_WVC (struct sARM7 *cpu) + { + // "V clear" + return !(cpu->Rx [ARM7_CPSR] & ARM7_CPSR_V); + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Condition HI. */ +int R_WHI (struct sARM7 *cpu) + { + // "C set and Z clear" + return (cpu->Rx [ARM7_CPSR] & ARM7_CPSR_C) &&\ + !(cpu->Rx [ARM7_CPSR] & ARM7_CPSR_Z); + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Condition LS. */ +int R_WLS (struct sARM7 *cpu) + { + // "C clear or Z set" + return !(cpu->Rx [ARM7_CPSR] & ARM7_CPSR_C) ||\ + (cpu->Rx [ARM7_CPSR] & ARM7_CPSR_Z); + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Condition GE. */ +int R_WGE (struct sARM7 *cpu) + { + // "N equals V" + return (cpu->Rx [ARM7_CPSR] & ARM7_CPSR_N) &&\ + (cpu->Rx [ARM7_CPSR] & ARM7_CPSR_V) || !(cpu->Rx [ARM7_CPSR] & ARM7_CPSR_N) &&\ + !(cpu->Rx [ARM7_CPSR] & ARM7_CPSR_V); + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Condition LT. */ +int R_WLT (struct sARM7 *cpu) + { + // "N not equal to V" + return !(cpu->Rx [ARM7_CPSR] & ARM7_CPSR_N) &&\ + (cpu->Rx [ARM7_CPSR] & ARM7_CPSR_V) || (cpu->Rx [ARM7_CPSR] & ARM7_CPSR_N) &&\ + !(cpu->Rx [ARM7_CPSR] & ARM7_CPSR_V); + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Condition GT. */ +int R_WGT (struct sARM7 *cpu) + { + // "Z clear AND (N equals V)" + return !(cpu->Rx [ARM7_CPSR] & ARM7_CPSR_Z) && R_WGE (cpu); + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Condition LE. */ +int R_WLE (struct sARM7 *cpu) + { + // "Z set OR (N not equal to V)" + return (cpu->Rx [ARM7_CPSR] & ARM7_CPSR_Z) || R_WLT (cpu); + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Condition AL. */ +int R_WAL (struct sARM7 *cpu) + { + // "(ignored)" + return TRUE; + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Undefined condition. */ +int R_Wxx (struct sARM7 *cpu) + { + // behaviour undefined + return FALSE; + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Calculates barrel shifter output. */ +UINT32 WyliczPrzes (struct sARM7 *cpu) + { + int Rm, Rs, i; + UINT32 w; + + // Rm is source for the shift operation + Rm = cpu->kod & 15; + + if (cpu->kod & (1 << 4)) + { + s_cykle++; + // shift count in Rs (8 lowest bits) + if (Rm != ARM7_PC) + w = cpu->Rx [Rm]; + else + w = (cpu->Rx [ARM7_PC] & ~3) + 12 + PC_ADJUSTMENT; + // Rs can't be PC + Rs = (cpu->kod >> 8) & 15; + i = (UINT8)cpu->Rx [Rs]; + if (i == 0) + { + // special case + cpu->carry = (cpu->Rx [ARM7_CPSR] & ARM7_CPSR_C) ? 1 : 0; + return w; + } + + switch ((cpu->kod >> 5) & 3) + { + case 0: + w = LSL_x (cpu, w, i); + break; + case 1: + w = LSR_x (cpu, w, i); + break; + case 2: + w = ASR_x (cpu, w, i); + break; + case 3: + w = ROR_x (cpu, w, i); + break; + } + } + else + { + // shift count as immediate in opcode + if (Rm != ARM7_PC) + w = cpu->Rx [Rm]; + else + w = (cpu->Rx [ARM7_PC] & ~3) + 8 + PC_ADJUSTMENT; + i = (cpu->kod >> 7) & 31; + + switch ((cpu->kod >> 5) & 3) + { + case 0: + w = LSL_x (cpu, w, i); + break; + case 1: + if (i > 0) + w = LSR_x (cpu, w, i); + else + w = LSR_x (cpu, w, 32); + break; + case 2: + if (i > 0) + w = ASR_x (cpu, w, i); + else + w = ASR_x (cpu, w, 32); + break; + case 3: + if (i > 0) + w = ROR_x (cpu, w, i); + else + w = RRX_1 (cpu, w); + break; + } + } + return w; + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Logical shift left. */ +UINT32 LSL_x (struct sARM7 *cpu, UINT32 w, int i) +{ + // LSL #0 copies C into carry out and returns unmodified value + if (i == 0) + { + cpu->carry = (cpu->Rx [ARM7_CPSR] & ARM7_CPSR_C) ? 1 : 0; + return w; + } + // LSL #32 copies LSB to carry out and returns zero + if (i == 32) + { + cpu->carry = w & 1; + return 0; + } + // LSL > #32 returns zero for both carry and output + if (i > 32) + { + cpu->carry = 0; + return 0; + } + // normal shift + cpu->carry = (w & (1 << (32 - i))) ? 1 : 0; + w = SHL (w, i); + return w; +} + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Logical shift right. */ +UINT32 LSR_x (struct sARM7 *cpu, UINT32 w, int i) +{ + // LSR #32 copies MSB to carry out and returns zero + if (i == 32) + { + cpu->carry = (w & (1 << 31)) ? 1 : 0; + return 0; + } + // LSR > #32 returns zero for both carry and output + if (i > 32) + { + cpu->carry = 0; + return 0; + } + // normal shift + cpu->carry = (w & (1 << (i - 1))) ? 1 : 0; + w = SHR (w, i); + return w; +} + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Arithmetic shift right. */ +UINT32 ASR_x (struct sARM7 *cpu, UINT32 w, int i) +{ + // ASR >= #32 carry out and output value depends on the minus sign + if (i >= 32) + { + if (w & (1 << 31)) + { + cpu->carry = 1; + return ~0; + } + + cpu->carry = 0; + return 0; + } + // normal shift + cpu->carry = (w & (1 << (i - 1))) ? 1 : 0; + w = SAR (w, i); + return w; +} + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Rotate right. */ +UINT32 ROR_x (struct sARM7 *cpu, UINT32 w, int i) +{ + // mask count to [0; 31] + i &= 0x1f; + // ROR #32,#64,etc. copies MSB into carry out and returns unmodified value + if (i == 0) + { + cpu->carry = (w & (1 << 31)) ? 1 : 0; + return w; + } + // normal shift + cpu->carry = (w & (1 << (i-1))) ? 1 : 0; + w = ROR (w, i); + return w; +} + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Rotate right extended. */ +UINT32 RRX_1 (struct sARM7 *cpu, UINT32 w) + { + // same as RCR by 1 in IA32 + cpu->carry = w & 1; + return (w >> 1) | ((cpu->Rx [ARM7_CPSR] & ARM7_CPSR_C) << 2); + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Group 00x opcodes. */ +void R_G00x (struct sARM7 *cpu) + { +#ifdef ARM7_THUMB + // 24 constant bits + if ((cpu->kod & 0x0ffffff0) == 0x012fff10) // BX - branch with possible mode transfer + { + #ifdef ARM7_THUMB + int Rn = cpu->Rx[cpu->kod & 0xf]; + + // switching to Thumb mode? + if (Rn & 1) + { + ARM7_SetCPSR(cpu->Rx[ARM7_CPSR] | ARM7_CPSR_T); + } + + cpu->Rx[ARM7_PC] = Rn & ~1; + #endif + } + // 15 constant bits + else if ((cpu->kod & 0x0fb00ff0) == 0x01000090) + R_SWP (cpu); + // 10 constant bits + else if ((cpu->kod & 0x0fc000f0) == 0x00000090) + R_MUL_MLA (cpu); + // 10 constant bits + else if ((cpu->kod & 0x0e400f90) == 0x00000090) + R_HSDT (cpu); + // 9 constant bits + else if ((cpu->kod & 0x0f8000f0) == 0x00800090) + { +// logerror("G00x / Multiply long\n"); + } + // 6 constant bits + else if ((cpu->kod & 0x0e400090) == 0x00400090) + R_HSDT (cpu); + // 2 constant bits + else + { + if ((cpu->kod & 0x01900000) == 0x01000000) + // TST, TEQ, CMP & CMN without S bit are "PSR Transfer" + R_PSR (cpu); + else + // the rest is "Data processing" + R_DP (cpu); + } +#else + if ((cpu->kod & 0x03b00090) == 0x01000090) + R_SWP (cpu); + else if ((cpu->kod & 0x03c00090) == 0x00000090) + R_MUL_MLA (cpu); + else + { + if ((cpu->kod & 0x01900000) == 0x01000000) + // TST, TEQ, CMP & CMN without S bit are "PSR Transfer" + R_PSR (cpu); + else + // the rest is "Data processing" + R_DP (cpu); + } +#endif + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Single data swap. */ +void R_SWP (struct sARM7 *cpu) + { + int Rn, Rd, Rm; + UINT32 adres, w; + +#define BIT_B (cpu->kod & (1 << 21)) + + s_cykle += 4; + // none of these can be PC + Rn = (cpu->kod >> 16) & 15; + Rd = (cpu->kod >> 12) & 15; + Rm = cpu->kod & 15; + adres = cpu->Rx [Rn]; + + if (BIT_B) + { + // "byte" + w = arm7_read_8 (cpu, adres); + arm7_write_8 (cpu, adres, (UINT8)cpu->Rx [Rm]); + } + else + { + // "word" + w = RBOD (arm7_read_32 (cpu, adres & ~3), adres & 3); + arm7_write_32 (cpu, adres & ~3, cpu->Rx [Rm]); + } + cpu->Rx [Rd] = w; + +#undef BIT_B + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Multiply instructions. */ +void R_MUL_MLA (struct sARM7 *cpu) + { + int Rm, Rs, Rn, Rd; + UINT32 wynik; + +#define BIT_A (cpu->kod & (1 << 21)) +#define BIT_S (cpu->kod & (1 << 20)) + + s_cykle += 2; + // none of these can be PC, also Rd != Rm + Rd = (cpu->kod >> 16) & 15, + Rs = (cpu->kod >> 8) & 15, + Rm = cpu->kod & 15; + + // MUL + wynik = cpu->Rx [Rm] * cpu->Rx [Rs]; + if (BIT_A) + { + // MLA + Rn = (cpu->kod >> 12) & 15; + wynik += cpu->Rx [Rn]; + } + cpu->Rx [Rd] = wynik; + + if (BIT_S) + { + // V remains unchanged, C is undefined + cpu->Rx [ARM7_CPSR] &= ~(ARM7_CPSR_N | ARM7_CPSR_Z); + if (wynik == 0) + cpu->Rx [ARM7_CPSR] |= ARM7_CPSR_Z; + cpu->Rx [ARM7_CPSR] |= wynik & 0x80000000; + } + +#undef BIT_S +#undef BIT_A + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** PSR Transfer. */ +void R_PSR (struct sARM7 *cpu) + { + int Rd, Rm; + UINT32 w, arg; + +#define BIT_I (cpu->kod & (1 << 25)) +#define BIT_P (cpu->kod & (1 << 22)) + + // none of the registers involved can be PC + + if (cpu->kod & (1 << 21)) + { + // MSR + Rm = cpu->kod & 15; + if (BIT_I) + // immediate (lower 12 bits) + arg = ROR (cpu->kod & 0xff, ((cpu->kod >> 8) & 0xf) * 2); + else + // register + arg = cpu->Rx [Rm]; + + // decode mask bits + if (BIT_P) + { + w = cpu->Rx [ARM7_SPSR]; + if (ARM7_CPSR_M (cpu->Rx [ARM7_CPSR]) > ARM7_CPSR_M_usr &&\ + ARM7_CPSR_M (cpu->Rx [ARM7_CPSR]) < ARM7_CPSR_M_sys) + { + if (cpu->kod & (1 << 16)) + w = (w & 0xffffff00) | (arg & 0x000000ff); + if (cpu->kod & (1 << 17)) + w = (w & 0xffff00ff) | (arg & 0x0000ff00); + if (cpu->kod & (1 << 18)) + w = (w & 0xff00ffff) | (arg & 0x00ff0000); + if (cpu->kod & (1 << 19)) + // ARMv5E should have 0xf8000000 argument mask + w = (w & 0x00ffffff) | (arg & 0xf0000000); + } + // force valid mode + w |= 0x10; + cpu->Rx [ARM7_SPSR] = w; + } + else + { + w = cpu->Rx [ARM7_CPSR]; + // only flags can be changed in User mode + if (ARM7_CPSR_M (cpu->Rx [ARM7_CPSR]) != ARM7_CPSR_M_usr) + { + if (cpu->kod & (1 << 16)) + w = (w & 0xffffff00) | (arg & 0x000000ff); + if (cpu->kod & (1 << 17)) + w = (w & 0xffff00ff) | (arg & 0x0000ff00); + if (cpu->kod & (1 << 18)) + w = (w & 0xff00ffff) | (arg & 0x00ff0000); + } + if (cpu->kod & (1 << 19)) + // ARMv5E should have 0xf8000000 argument mask + w = (w & 0x00ffffff) | (arg & 0xf0000000); + // force valid mode + w |= 0x10; + ARM7_SetCPSR (cpu, w); + } + } + else + { + // MRS + Rd = (cpu->kod >> 12) & 15; + if (BIT_P) + cpu->Rx [Rd] = cpu->Rx [ARM7_SPSR]; + else + cpu->Rx [Rd] = cpu->Rx [ARM7_CPSR]; + } + +#undef BIT_P +#undef BIT_I + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Data processing instructions. */ +void R_DP (struct sARM7 *cpu) + { + int Rn; + ARM7_REG arg1, arg2, w; + +#define BIT_I (cpu->kod & (1 << 25)) + + // Rn can be PC, so we need to account for that + Rn = (cpu->kod >> 16) & 15; + + if (BIT_I) + { + if (Rn != ARM7_PC) + arg1 = cpu->Rx [Rn]; + else + arg1 = (cpu->Rx [ARM7_PC] & ~3) + 8 + PC_ADJUSTMENT; + // immediate in lowest 12 bits + arg2 = ROR (cpu->kod & 0xff, ((cpu->kod >> 8) & 0xf) * 2); + // preload carry out from C + cpu->carry = (cpu->Rx [ARM7_CPSR] & ARM7_CPSR_C) ? 1 : 0; + } + else + { + if (Rn != ARM7_PC) + arg1 = cpu->Rx [Rn]; + else + // register or immediate shift? + if (cpu->kod & (1 << 4)) + arg1 = (cpu->Rx [ARM7_PC] & ~3) + 12 + PC_ADJUSTMENT; + else + arg1 = (cpu->Rx [ARM7_PC] & ~3) + 8 + PC_ADJUSTMENT; + // calculate in barrel shifter + arg2 = WyliczPrzes (cpu); + } + + // decode instruction type + switch ((cpu->kod >> 21) & 15) + { + case 0: + // AND + R_WynikDP (cpu, arg1 & arg2); + break; + + case 1: + // EOR + R_WynikDP (cpu, arg1 ^ arg2); + break; + + case 2: + // SUB + w = arg1 - arg2; + cpu->carry = SUBCARRY (arg1, arg2, w); + cpu->overflow = SUBOVERFLOW (arg1, arg2, w); + R_WynikDP (cpu, w); + break; + + case 3: + // RSB + w = arg2 - arg1; + cpu->carry = SUBCARRY (arg2, arg1, w); + cpu->overflow = SUBOVERFLOW (arg2, arg1, w); + R_WynikDP (cpu, w); + break; + + case 4: + // ADD + w = arg1 + arg2; + cpu->carry = ADDCARRY (arg1, arg2, w); + cpu->overflow = ADDOVERFLOW (arg1, arg2, w); + R_WynikDP (cpu, w); + break; + + case 5: + // ADC + w = arg1 + arg2 + ((cpu->Rx [ARM7_CPSR] & ARM7_CPSR_C) ? 1 : 0); + cpu->carry = ADDCARRY (arg1, arg2, w); + cpu->overflow = ADDOVERFLOW (arg1, arg2, w); + R_WynikDP (cpu, w); + break; + + case 6: + // SBC + w = arg1 - arg2 - ((cpu->Rx [ARM7_CPSR] & ARM7_CPSR_C) ? 0 : 1); + cpu->carry = SUBCARRY (arg1, arg2, w); + cpu->overflow = SUBOVERFLOW (arg1, arg2, w); + R_WynikDP (cpu, w); + break; + + case 7: + // RSC + w = arg2 - arg1 - ((cpu->Rx [ARM7_CPSR] & ARM7_CPSR_C) ? 0 : 1); + cpu->carry = SUBCARRY (arg2, arg1, w); + cpu->overflow = SUBOVERFLOW (arg2, arg1, w); + R_WynikDP (cpu, w); + break; + + case 8: + // TST + R_FlagiDP (cpu, arg1 & arg2); + break; + + case 9: + // TEQ + R_FlagiDP (cpu, arg1 ^ arg2); + break; + + case 10: + // CMP + w = arg1 - arg2; + cpu->carry = SUBCARRY (arg1, arg2, w); + cpu->overflow = SUBOVERFLOW (arg1, arg2, w); + R_FlagiDP (cpu, w); + break; + + case 11: + // CMN + w = arg1 + arg2; + cpu->carry = ADDCARRY (arg1, arg2, w); + cpu->overflow = ADDOVERFLOW (arg1, arg2, w); + R_FlagiDP (cpu, w); + break; + + case 12: + // ORR + R_WynikDP (cpu, arg1 | arg2); + break; + + case 13: + // MOV + R_WynikDP (cpu, arg2); + break; + + case 14: + // BIC + R_WynikDP (cpu, arg1 & ~arg2); + break; + + case 15: + // MVN + R_WynikDP (cpu, ~arg2); + break; + } + +#undef BIT_I + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Data processing result writeback. */ +void R_WynikDP (struct sARM7 *cpu, ARM7_REG w) + { + int Rd; + +#define BIT_S (cpu->kod & (1 << 20)) + + Rd = (cpu->kod >> 12) & 15; + cpu->Rx [Rd] = w; + if (BIT_S) + { + if (Rd == ARM7_PC) + { + s_cykle += 4; + // copy current SPSR to CPSR + ARM7_SetCPSR (cpu, cpu->Rx [ARM7_SPSR]); + } + else + // save new flags + R_FlagiDP (cpu, w); + } + +#undef BIT_S + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Data processing flags writeback. */ +void R_FlagiDP (struct sARM7 *cpu, ARM7_REG w) + { + // arithmetic or logical instruction? + if (s_tabAL [(cpu->kod >> 21) & 15]) + { + cpu->Rx [ARM7_CPSR] &= ~(ARM7_CPSR_N | ARM7_CPSR_Z | ARM7_CPSR_C |\ + ARM7_CPSR_V); + cpu->Rx [ARM7_CPSR] |= cpu->overflow << 28; + } + else + cpu->Rx [ARM7_CPSR] &= ~(ARM7_CPSR_N | ARM7_CPSR_Z | ARM7_CPSR_C); + cpu->Rx [ARM7_CPSR] |= cpu->carry << 29; + if (w == 0) + cpu->Rx [ARM7_CPSR] |= ARM7_CPSR_Z; + cpu->Rx [ARM7_CPSR] |= w & 0x80000000; + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Single data transfer. */ +void R_SDT (struct sARM7 *cpu) + { + int Rn, Rd, offset; + UINT32 adres, w = 0; + +#define BIT_I (cpu->kod & (1 << 25)) +#define BIT_P (cpu->kod & (1 << 24)) +#define BIT_U (cpu->kod & (1 << 23)) +#define BIT_B (cpu->kod & (1 << 22)) +#define BIT_W (cpu->kod & (1 << 21)) +#define BIT_L (cpu->kod & (1 << 20)) + + if (BIT_I && (cpu->kod & (1 << 4))) + { + R_Und (cpu); + return; + } + + Rn = (cpu->kod >> 16) & 15, + Rd = (cpu->kod >> 12) & 15; + if (Rn != ARM7_PC) + adres = cpu->Rx [Rn]; + else + adres = cpu->Rx [ARM7_PC] & ~3; + if (!BIT_L) + if (Rd != ARM7_PC) + w = cpu->Rx [Rd]; + else + w = (cpu->Rx [ARM7_PC] & ~3) + 12 + PC_ADJUSTMENT; + + if (BIT_I) + // calculate value in barrel shifter + offset = WyliczPrzes (cpu); + else + // immediate in lowest 12 bits + offset = cpu->kod & 0xfff; + + if (!BIT_U) + offset = -offset; + if (BIT_P) + { + // "pre-index" + adres += offset; + if (BIT_W) + // "write-back" + cpu->Rx [Rn] = adres; + } + else + // "post-index" + cpu->Rx [Rn] += offset; + if (Rn == ARM7_PC) + adres += 8 + PC_ADJUSTMENT; + + if (BIT_L) + { + s_cykle += 3; + // "load" + if (BIT_B) + // "byte" + cpu->Rx [Rd] = arm7_read_8 (cpu, adres); + else + // "word" + cpu->Rx [Rd] = RBOD (arm7_read_32 (cpu, adres & ~3), adres & 3); + } + else + { + s_cykle += 2; + // "store" + if (BIT_B) + // "byte" + arm7_write_8 (cpu, adres, (UINT8)w); + else + // "word" + arm7_write_32 (cpu, adres & ~3, w); + } + +#undef BIT_L +#undef BIT_W +#undef BIT_B +#undef BIT_U +#undef BIT_P +#undef BIT_I + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Undefined. */ +void R_Und (struct sARM7 *cpu) + { + UINT32 sr = cpu->Rx [ARM7_CPSR]; + ARM7_SetCPSR (cpu, ARM7_CPSR_MX (sr, ARM7_CPSR_M_und) | ARM7_CPSR_I); + cpu->Rx [ARM7_SPSR] = sr; + cpu->Rx [ARM7_LR] = cpu->Rx [ARM7_PC] + 4; + cpu->Rx [ARM7_PC] = 0x00000004; + } + //-------------------------------------------------------------------------- + +#define BIT_U (cpu->kod & (1 << 23)) +#define BIT_S (cpu->kod & (1 << 22)) + //-------------------------------------------------------------------------- + /** Block Data Transfer. */ +void R_BDT (struct sARM7 *cpu) + { + int Rn, usr = FALSE; + UINT32 adres; + ARM7_REG cpsr = 0; + +#define BIT_L (cpu->kod & (1 << 20)) + + // Rn can't be PC + Rn = (cpu->kod >> 16) & 15; + adres = cpu->Rx [Rn]; + + // transfer in User mode + if (BIT_S) + if (!BIT_L || !(cpu->kod & (1 << ARM7_PC))) + usr = TRUE; + + if (usr) + { +//EMU_BLAD (BLAD_WEWNETRZNY, "BDT: user transfer"); + cpsr = cpu->Rx [ARM7_CPSR]; + ARM7_SetCPSR (cpu, ARM7_CPSR_MX (cpsr, ARM7_CPSR_M_usr)); + } + + if (BIT_L) + // "load" + R_LDM (cpu, Rn, adres); + else + // "store" + R_STM (cpu, Rn, adres); + + if (usr) + ARM7_SetCPSR (cpu, cpsr); + +#undef BIT_L + } + //-------------------------------------------------------------------------- + +#define BIT_P (cpu->kod & (1 << 24)) +#define BIT_W (cpu->kod & (1 << 21)) + //-------------------------------------------------------------------------- + /** Block load instructions. */ +void R_LDM (struct sARM7 *cpu, int Rn, UINT32 adres) + { + int i, n, sp; + + // count registers on the list + for (i = 0, n = 0; i < 16; i++) + if (cpu->kod & (1 << i)) + n++; + s_cykle += n * 2 + 1; + + n <<= 2; + // transfer type + sp = BIT_P; + if (!BIT_U) + { + // "down" + n = -n; + adres += n; + sp = !sp; + } + if (BIT_W) + // "write-back" + cpu->Rx [Rn] += n; + + // for all registers in mask + if (sp) + for (i = 0; i < 16; i++) + { + if (!(cpu->kod & (1 << i))) + continue; + adres += 4; + cpu->Rx [i] = arm7_read_32 (cpu, adres); + } + else + for (i = 0; i < 16; i++) + { + if (!(cpu->kod & (1 << i))) + continue; + cpu->Rx [i] = arm7_read_32 (cpu, adres); + adres += 4; + } + + // special case - mode change when PC is written + if ((cpu->kod & (1 << ARM7_PC)) && BIT_S) + ARM7_SetCPSR (cpu, cpu->Rx [ARM7_SPSR]); + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Block store instructions. */ +void R_STM (struct sARM7 *cpu, int Rn, UINT32 adres) + { + int i, n, p, sp; + + // count registers on the list and remember the first one + for (i = 0, n = 0, p = -1; i < 16; i++) + if (cpu->kod & (1 << i)) + { + n++; + if (p < 0) + p = i; + } + s_cykle += n * 2; + + n <<= 2; + // transfer type + sp = BIT_P; + if (!BIT_U) + { + // "down" + n = -n; + adres += n; + sp = !sp; + } + // if base register is not the first one to transfer, writeback happens here + if (BIT_W && Rn != p) + // "write-back" + cpu->Rx [Rn] += n; + + // registers R0-R14 + if (sp) + for (i = 0; i < 15; i++) + { + if (!(cpu->kod & (1 << i))) + continue; + adres += 4; + arm7_write_32 (cpu, adres, cpu->Rx [i]); + } + else + for (i = 0; i < 15; i++) + { + if (!(cpu->kod & (1 << i))) + continue; + arm7_write_32 (cpu, adres, cpu->Rx [i]); + adres += 4; + } + + // PC is a special case + if (cpu->kod & (1 << ARM7_PC)) + { + if (sp) + { + adres += 4; + arm7_write_32 (cpu, adres, (cpu->Rx [ARM7_PC] & ~3) + 12 + PC_ADJUSTMENT); + } + else + { + arm7_write_32 (cpu, adres, (cpu->Rx [ARM7_PC] & ~3) + 12 + PC_ADJUSTMENT); + adres += 4; + } + } + + // if base register is the first one to transfer, writeback happens here + if (BIT_W && Rn == p) + // "write-back" + cpu->Rx [Rn] += n; + } + //-------------------------------------------------------------------------- +#undef BIT_W +#undef BIT_P +#undef BIT_S +#undef BIT_U + + //-------------------------------------------------------------------------- + /** Branch/Branch with link. */ +void R_B_BL (struct sARM7 *cpu) + { + INT32 offset; + +#define BIT_L (cpu->kod & (1 << 24)) + + s_cykle += 4; + offset = (cpu->kod & 0x00ffffff) << 2; + if (offset & 0x02000000) + offset |= 0xfc000000; + offset += 8 + PC_ADJUSTMENT; + if (BIT_L) + // "Branch with link" + cpu->Rx [ARM7_LR] = (cpu->Rx [ARM7_PC] & ~3) + 4 + PC_ADJUSTMENT; + // "Branch" + cpu->Rx [ARM7_PC] += offset; + +#undef BIT_L + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Group 110 opcodes. */ +void R_G110 (struct sARM7 *cpu) + { +// logerror("ARM7: G110 / Coprocessor data transfer\n"); + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Group 111 opcodes. */ +void R_G111 (struct sARM7 *cpu) + { + if ((cpu->kod & 0xf0000000) == 0xe0000000) + { +/* if (cpu->kod & (1 << 4)) + logerror("ARM7: G111 / Coprocessor register transfer\n"); + else + logerror("ARM7: G111 / Coprocessor data operation\n"); */ + } + else + { + UINT32 sr = cpu->Rx [ARM7_CPSR]; + ARM7_SetCPSR (cpu, ARM7_CPSR_MX (sr, ARM7_CPSR_M_svc) | ARM7_CPSR_I); + cpu->Rx [ARM7_SPSR] = sr; + cpu->Rx [ARM7_LR] = cpu->Rx [ARM7_PC]; + cpu->Rx [ARM7_PC] = 0x00000008; + } + } + //-------------------------------------------------------------------------- + +#ifdef ARM7_THUMB + //-------------------------------------------------------------------------- + /** Halfword and Signed Data Transfer. */ +void R_HSDT () + { + int Rm, Rd, Rn, offset; + uint32_t adres, w; + +#define BIT_P (cpu->kod & (1 << 24)) +#define BIT_U (cpu->kod & (1 << 23)) +#define BIT_W (cpu->kod & (1 << 21)) +#define BIT_L (cpu->kod & (1 << 20)) +#define BIT_S (cpu->kod & (1 << 6)) +#define BIT_H (cpu->kod & (1 << 5)) + + // Rm can't be PC + Rn = (cpu->kod >> 16) & 15; + Rd = (cpu->kod >> 12) & 15; + if (Rn != ARM7_PC) + adres = cpu->Rx [Rn]; + else + adres = cpu->Rx [ARM7_PC] & ~3; + if (!BIT_L) + if (Rd != ARM7_PC) + w = cpu->Rx [Rd]; + else + w = (cpu->Rx [ARM7_PC] & ~3) + 12 + POPRAWKA_PC; + + if (1 << 22) + // immediate + offset = ((cpu->kod >> 4) & 0xf0) | (cpu->kod & 15); + else + { + // register + Rm = cpu->kod & 15; + offset = cpu->Rx [Rm]; + } + + if (!BIT_U) + offset = -offset; + if (BIT_P) + { + // "pre-index" + adres += offset; + if (BIT_W) + // "write-back" + cpu->Rx [Rn] = adres; + } + else + // "post-index" + cpu->Rx [Rn] += offset; + if (Rn == ARM7_PC) + adres += 8 + POPRAWKA_PC; + + if (BIT_L) + { + // "load" + s_cykle += 3; + if (BIT_S) + { + if (BIT_H) + // "signed halfword" + cpu->Rx [Rd] = (INT32)(INT16)arm7_read_16 (adres); + else + // "signed byte" + cpu->Rx [Rd] = (INT32)(INT8)arm7_read_8 (cpu, adres); + } + else + // "unsigned halfword" + cpu->Rx [Rd] = arm7_read_16 (adres); + } + else + { + // store + s_cykle += 2; + if (BIT_H) + // "halfword" + arm7_write_16 (adres, (UINT16)w); + else + // "byte" + arm7_write_8 (cpu, adres, (UINT8)w); + } + +#undef BIT_H +#undef BIT_S +#undef BIT_L +#undef BIT_W +#undef BIT_U +#undef BIT_P + } + //-------------------------------------------------------------------------- +#endif diff --git a/plugins/ao/eng_dsf/arm7i.h b/plugins/ao/eng_dsf/arm7i.h new file mode 100644 index 00000000..9ca50188 --- /dev/null +++ b/plugins/ao/eng_dsf/arm7i.h @@ -0,0 +1,19 @@ +// +// ARM7 processor emulator - interpreter core +// version 1.6 / 2008-02-16 +// (c) Radoslaw Balcewicz +// + +#ifndef _ARM7i_h_ +#define _ARM7i_h_ + +#include "arm7.h" + + //-------------------------------------------------------------------------- + // public functions + + /** Single step, returns number of burned cycles. */ +int ARM7i_Step(struct sARM7 *cpu); + //-------------------------------------------------------------------------- + +#endif diff --git a/plugins/ao/eng_dsf/arm7memil.c b/plugins/ao/eng_dsf/arm7memil.c new file mode 100644 index 00000000..c1872a2c --- /dev/null +++ b/plugins/ao/eng_dsf/arm7memil.c @@ -0,0 +1,56 @@ +// memory inline functions shared by ARM and THUMB modes + +static INLINE void arm7_write_32(struct sARM7 *cpu, UINT32 addr, UINT32 data ) +{ + addr &= ~3; + dc_write32(cpu, addr,data); +} + + +static INLINE void arm7_write_16(struct sARM7 *cpu, UINT32 addr, UINT16 data) +{ + addr &= ~1; + dc_write16(cpu, addr,data); +} + +static INLINE void arm7_write_8(struct sARM7 *cpu, UINT32 addr, UINT8 data) +{ + dc_write8(cpu, addr,data); +} + +static INLINE UINT32 arm7_read_32(struct sARM7 *cpu, UINT32 addr) +{ + UINT32 result; + int k = (addr & 3) << 3; + + if (k) + { + result = dc_read32 (cpu, addr & ~3); + result = (result >> k) | (result << (32 - k)); + } + else + { + result = dc_read32(cpu, addr); + } + return result; +} + +static INLINE UINT16 arm7_read_16(struct sARM7 *cpu, UINT32 addr) +{ + UINT16 result; + + result = dc_read16(cpu, addr & ~1); + + if (addr & 1) + { + result = ((result>>8) & 0xff) | ((result&0xff)<<8); + } + + return result; +} + +static INLINE UINT8 arm7_read_8(struct sARM7 *cpu, UINT32 addr) +{ + return dc_read8(cpu, addr); +} + diff --git a/plugins/ao/eng_dsf/arm7thumb.c b/plugins/ao/eng_dsf/arm7thumb.c new file mode 100644 index 00000000..f9780cab --- /dev/null +++ b/plugins/ao/eng_dsf/arm7thumb.c @@ -0,0 +1,1176 @@ +// +// ARM7 processor emulator - THUMB support +// version 2.0 / 2008-02-08 +// By R. Belmont and SGINut +// + +#include "arm7.h" +#include "arm7i.h" +#include "arm7thumb.h" + +// base cycle counts for Thumb instructions +static const int thumbCycles[256] = +{ +// 0 1 2 3 4 5 6 7 8 9 a b c d e f + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 4 + 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 5 + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, // 6 + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, // 7 + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, // 8 + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, // 9 + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // a + 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 4, 1, 1, // b + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // c + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, // d + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // e + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 // f +}; + +// utility macros + +#define IsNeg(i) ((i) >> 31) +#define IsPos(i) ((~(i)) >> 31) + +#define N_BIT 31 +#define Z_BIT 30 +#define C_BIT 29 +#define V_BIT 28 +#define SIGN_BIT ((UINT32)(1<<31)) + +#define HandleThumbALUAddFlags(rd, rn, op2) \ + ARM7_SetCPSR( \ + ((GET_CPSR &~ (ARM7_CPSR_N | ARM7_CPSR_Z | ARM7_CPSR_V | ARM7_CPSR_C)) \ + | (((!THUMB_SIGN_BITS_DIFFER(rn, op2)) && THUMB_SIGN_BITS_DIFFER(rn, rd)) \ + << V_BIT) \ + | (((~(rn)) < (op2)) << C_BIT) \ + | HandleALUNZFlags(rd))); \ + R15 += 2; + +#define HandleThumbALUSubFlags(rd, rn, op2) \ + ARM7_SetCPSR( \ + ((GET_CPSR &~ (ARM7_CPSR_N | ARM7_CPSR_Z | ARM7_CPSR_V | ARM7_CPSR_C)) \ + | ((THUMB_SIGN_BITS_DIFFER(rn, op2) && THUMB_SIGN_BITS_DIFFER(rn, rd)) \ + << V_BIT) \ + | (((IsNeg(rn) & IsPos(op2)) | (IsNeg(rn) & IsPos(rd)) | (IsPos(op2) & IsPos(rd))) ? ARM7_CPSR_C : 0) \ + | HandleALUNZFlags(rd))); \ + R15 += 2; + +#define HandleALUNZFlags(rd) \ + (((rd) & SIGN_BIT) | ((!(rd)) << Z_BIT)) + +// memory accessors +#include "arm7memil.c" + +// public functions +int ARM7i_Thumb_Step() +{ + UINT32 readword; + UINT32 addr, insn; + UINT32 rm, rn, rs, rd, op2, imm, rrs, rrd; + INT32 offs; + UINT32 pc = ARM7.Rx[ARM7_PC]; + int cycles; + + insn = arm7_read_16(pc & (~1)); + + cycles = (3 - thumbCycles[insn >> 8]); + + switch( ( insn & THUMB_INSN_TYPE ) >> THUMB_INSN_TYPE_SHIFT ) + { + case 0x0: /* Logical shifting */ + ARM7_SetCPSR(GET_CPSR &~ (ARM7_CPSR_N | ARM7_CPSR_Z)); + if( insn & THUMB_SHIFT_R ) /* Shift right */ + { + rs = ( insn & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = ( insn & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; + rrs = GET_REGISTER(rs); + offs = ( insn & THUMB_SHIFT_AMT ) >> THUMB_SHIFT_AMT_SHIFT; + if( offs != 0 ) + { + SET_REGISTER( rd, rrs >> offs ); + if( rrs & ( 1 << (offs-1) ) ) + { + ARM7_SetCPSR(GET_CPSR | ARM7_CPSR_C); + } + else + { + ARM7_SetCPSR(GET_CPSR &~ ARM7_CPSR_C); + } + } + else + { + SET_REGISTER( rd, 0 ); + if( rrs & 0x80000000 ) + { + ARM7_SetCPSR( GET_CPSR | ARM7_CPSR_C ); + } + else + { + ARM7_SetCPSR( GET_CPSR &~ ARM7_CPSR_C ); + } + } + ARM7_SetCPSR(GET_CPSR &~ ( ARM7_CPSR_Z | ARM7_CPSR_N ) ); + ARM7_SetCPSR( GET_CPSR | HandleALUNZFlags( GET_REGISTER(rd) ) ); + R15 += 2; + } + else /* Shift left */ + { + rs = ( insn & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = ( insn & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; + rrs = GET_REGISTER(rs); + offs = ( insn & THUMB_SHIFT_AMT ) >> THUMB_SHIFT_AMT_SHIFT; + if( offs != 0 ) + { + SET_REGISTER( rd, rrs << offs ); + if( rrs & ( 1 << ( 31 - ( offs - 1 ) ) ) ) + { + ARM7_SetCPSR(GET_CPSR | ARM7_CPSR_C); + } + else + { + ARM7_SetCPSR(GET_CPSR &~ ARM7_CPSR_C); + } + } + else + { + SET_REGISTER( rd, rrs ); + } + ARM7_SetCPSR( GET_CPSR &~ ( ARM7_CPSR_Z | ARM7_CPSR_N ) ); + ARM7_SetCPSR( GET_CPSR | HandleALUNZFlags( GET_REGISTER(rd) ) ); + R15 += 2; + } + break; + case 0x1: /* Arithmetic */ + if( insn & THUMB_INSN_ADDSUB ) + { + switch( ( insn & THUMB_ADDSUB_TYPE ) >> THUMB_ADDSUB_TYPE_SHIFT ) + { + case 0x0: /* ADD Rd, Rs, Rn */ + rn = GET_REGISTER( ( insn & THUMB_ADDSUB_RNIMM ) >> THUMB_ADDSUB_RNIMM_SHIFT ); + rs = GET_REGISTER( ( insn & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT ); + rd = ( insn & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; + SET_REGISTER( rd, rs + rn ); + HandleThumbALUAddFlags( GET_REGISTER(rd), rs, rn ); + break; + case 0x1: /* SUB Rd, Rs, Rn */ + rn = GET_REGISTER( ( insn & THUMB_ADDSUB_RNIMM ) >> THUMB_ADDSUB_RNIMM_SHIFT ); + rs = GET_REGISTER( ( insn & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT ); + rd = ( insn & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; + SET_REGISTER( rd, rs - rn ); + HandleThumbALUSubFlags( GET_REGISTER(rd), rs, rn ); + break; + case 0x2: /* ADD Rd, Rs, #imm */ + imm = ( insn & THUMB_ADDSUB_RNIMM ) >> THUMB_ADDSUB_RNIMM_SHIFT; + rs = GET_REGISTER( ( insn & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT ); + rd = ( insn & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; + SET_REGISTER( rd, rs + imm ); + HandleThumbALUAddFlags( GET_REGISTER(rd), rs, imm ); + break; + case 0x3: /* SUB Rd, Rs, #imm */ + imm = ( insn & THUMB_ADDSUB_RNIMM ) >> THUMB_ADDSUB_RNIMM_SHIFT; + rs = GET_REGISTER( ( insn & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT ); + rd = ( insn & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; + SET_REGISTER( rd, rs - imm ); + HandleThumbALUSubFlags( GET_REGISTER(rd), rs,imm ); + break; + default: + printf("%08x: G1 Undefined Thumb instruction: %04x\n", pc, insn); + R15 += 2; + break; + } + } + else + { + /* ASR.. */ + //if( insn & THUMB_SHIFT_R ) /* Shift right */ + { + rs = ( insn & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = ( insn & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; + rrs = GET_REGISTER(rs); + offs = ( insn & THUMB_SHIFT_AMT ) >> THUMB_SHIFT_AMT_SHIFT; + if( offs == 0 ) + { + offs = 32; + } + + if( offs >= 32 ) + { + if( rrs >> 31 ) + { + ARM7_SetCPSR(GET_CPSR | ARM7_CPSR_C); + } + else + { + ARM7_SetCPSR(GET_CPSR &~ ARM7_CPSR_C); + } + SET_REGISTER( rd, ( rrs & 0x80000000 ) ? 0xFFFFFFFF : 0x00000000 ); + } + else + { + if( ( rrs >> ( offs - 1 ) ) & 1 ) + { + ARM7_SetCPSR( GET_CPSR | ARM7_CPSR_C ); + } + else + { + ARM7_SetCPSR( GET_CPSR &~ ARM7_CPSR_C ); + } + SET_REGISTER( rd, ( rrs & 0x80000000 ) ? ( ( 0xFFFFFFFF << ( 32 - offs ) ) | ( rrs >> offs ) ) : ( rrs >> offs ) ); + } + ARM7_SetCPSR(GET_CPSR &~ (ARM7_CPSR_N | ARM7_CPSR_Z)); + ARM7_SetCPSR( GET_CPSR | HandleALUNZFlags( GET_REGISTER(rd) ) ); + R15 += 2; + } + + } + break; + case 0x2: /* CMP / MOV */ + if( insn & THUMB_INSN_CMP ) + { + rn = GET_REGISTER( ( insn & THUMB_INSN_IMM_RD ) >> THUMB_INSN_IMM_RD_SHIFT ); + op2 = ( insn & THUMB_INSN_IMM ); + rd = rn - op2; + HandleThumbALUSubFlags( rd, rn, op2 ); + //mame_printf_debug("%08x: xxx Thumb instruction: CMP R%d (%08x), %02x (N=%d, Z=%d, C=%d, V=%d)\n", pc, ( insn & THUMB_INSN_IMM_RD ) >> THUMB_INSN_IMM_RD_SHIFT, GET_REGISTER( ( insn & THUMB_INSN_IMM_RD ) >> THUMB_INSN_IMM_RD_SHIFT ), op2, N_IS_SET(GET_CPSR) ? 1 : 0, Z_IS_SET(GET_CPSR) ? 1 : 0, C_IS_SET(GET_CPSR) ? 1 : 0, V_IS_SET(GET_CPSR) ? 1 : 0); + } + else + { + rd = ( insn & THUMB_INSN_IMM_RD ) >> THUMB_INSN_IMM_RD_SHIFT; + op2 = ( insn & THUMB_INSN_IMM ); + SET_REGISTER( rd, op2 ); + ARM7_SetCPSR( GET_CPSR &~ ( ARM7_CPSR_Z | ARM7_CPSR_N ) ); + ARM7_SetCPSR( GET_CPSR | HandleALUNZFlags( GET_REGISTER(rd) ) ); + R15 += 2; + } + break; + case 0x3: /* ADD/SUB immediate */ + if( insn & THUMB_INSN_SUB ) /* SUB Rd, #Offset8 */ + { + rn = GET_REGISTER( ( insn & THUMB_INSN_IMM_RD ) >> THUMB_INSN_IMM_RD_SHIFT ); + op2 = ( insn & THUMB_INSN_IMM ); + //mame_printf_debug("%08x: Thumb instruction: SUB R%d, %02x\n", pc, ( insn & THUMB_INSN_IMM_RD ) >> THUMB_INSN_IMM_RD_SHIFT, op2); + rd = rn - op2; + SET_REGISTER( ( insn & THUMB_INSN_IMM_RD ) >> THUMB_INSN_IMM_RD_SHIFT, rd ); + HandleThumbALUSubFlags( rd, rn, op2 ); + } + else /* ADD Rd, #Offset8 */ + { + rn = GET_REGISTER( ( insn & THUMB_INSN_IMM_RD ) >> THUMB_INSN_IMM_RD_SHIFT ); + op2 = insn & THUMB_INSN_IMM; + rd = rn + op2; + //mame_printf_debug("%08x: Thumb instruction: ADD R%d, %02x\n", pc, ( insn & THUMB_INSN_IMM_RD ) >> THUMB_INSN_IMM_RD_SHIFT, op2); + SET_REGISTER( ( insn & THUMB_INSN_IMM_RD ) >> THUMB_INSN_IMM_RD_SHIFT, rd ); + HandleThumbALUAddFlags( rd, rn, op2 ); + } + break; + case 0x4: /* Rd & Rm instructions */ + switch( ( insn & THUMB_GROUP4_TYPE ) >> THUMB_GROUP4_TYPE_SHIFT ) + { + case 0x0: + switch( ( insn & THUMB_ALUOP_TYPE ) >> THUMB_ALUOP_TYPE_SHIFT ) + { + case 0x0: /* AND Rd, Rs */ + rs = ( insn & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = ( insn & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; + SET_REGISTER( rd, GET_REGISTER(rd) & GET_REGISTER(rs) ); + ARM7_SetCPSR( GET_CPSR &~ ( ARM7_CPSR_Z | ARM7_CPSR_N ) ); + ARM7_SetCPSR( GET_CPSR | HandleALUNZFlags( GET_REGISTER(rd) ) ); + R15 += 2; + break; + case 0x1: /* EOR Rd, Rs */ + rs = ( insn & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = ( insn & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; + SET_REGISTER( rd, GET_REGISTER(rd) ^ GET_REGISTER(rs) ); + ARM7_SetCPSR( GET_CPSR &~ ( ARM7_CPSR_Z | ARM7_CPSR_N ) ); + ARM7_SetCPSR( GET_CPSR | HandleALUNZFlags( GET_REGISTER(rd) ) ); + R15 += 2; + break; + case 0x2: /* LSL Rd, Rs */ + rs = ( insn & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = ( insn & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; + rrd = GET_REGISTER(rd); + offs = GET_REGISTER(rs) & 0x000000ff; + if (offs > 0) + { + if ( offs < 32 ) + { + SET_REGISTER( rd, rrd << offs ); + if( rrd & ( 1 << ( 31 - ( offs - 1 ) ) ) ) + { + ARM7_SetCPSR( GET_CPSR | ARM7_CPSR_C ); + } + else + { + ARM7_SetCPSR( GET_CPSR &~ ARM7_CPSR_C ); + } + } + else if( offs == 32 ) + { + SET_REGISTER( rd, 0 ); + if( rrd & 1 ) + { + ARM7_SetCPSR( GET_CPSR | ARM7_CPSR_C ); + } + else + { + ARM7_SetCPSR( GET_CPSR &~ ARM7_CPSR_C ); + } + } + else + { + SET_REGISTER( rd, 0 ); + ARM7_SetCPSR( GET_CPSR &~ ARM7_CPSR_C ); + } + } + ARM7_SetCPSR( GET_CPSR &~ ( ARM7_CPSR_Z | ARM7_CPSR_N ) ); + ARM7_SetCPSR( GET_CPSR | HandleALUNZFlags( GET_REGISTER(rd) ) ); + R15 += 2; + break; + case 0x3: /* LSR Rd, Rs */ + rs = ( insn & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = ( insn & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; + rrd = GET_REGISTER(rd); + offs = GET_REGISTER(rs) & 0x000000ff; + if (offs > 0) + { + if( offs < 32 ) + { + SET_REGISTER( rd, rrd >> offs ); + if( rrd & ( 1 << ( offs - 1 ) ) ) + { + ARM7_SetCPSR( GET_CPSR | ARM7_CPSR_C ); + } + else + { + ARM7_SetCPSR( GET_CPSR &~ ARM7_CPSR_C ); + } + } + else if( offs == 32 ) + { + SET_REGISTER( rd, 0 ); + if( rrd & 0x80000000 ) + { + ARM7_SetCPSR( GET_CPSR | ARM7_CPSR_C ); + } + else + { + ARM7_SetCPSR( GET_CPSR &~ ARM7_CPSR_C ); + } + } + else + { + SET_REGISTER( rd, 0 ); + ARM7_SetCPSR( GET_CPSR &~ ARM7_CPSR_C ); + } + } + ARM7_SetCPSR( GET_CPSR &~ ( ARM7_CPSR_Z | ARM7_CPSR_N ) ); + ARM7_SetCPSR( GET_CPSR | HandleALUNZFlags( GET_REGISTER(rd) ) ); + R15 += 2; + break; + case 0x4: /* ASR Rd, Rs */ + { + rs = ( insn & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = ( insn & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; + rrs = GET_REGISTER(rs)&0xff; + rrd = GET_REGISTER(rd); + if (rrs != 0) + { + if (rrs >= 32) + { + if (rrd>>31) + { + ARM7_SetCPSR(GET_CPSR | ARM7_CPSR_C); + } + else + { + ARM7_SetCPSR(GET_CPSR &~ ARM7_CPSR_C); + } + SET_REGISTER( rd, (GET_REGISTER(rd) & 0x80000000) ? 0xFFFFFFFF : 0x00000000 ); + } + else + { + if ((rrd>>(rs-1))&1) + { + ARM7_SetCPSR(GET_CPSR | ARM7_CPSR_C); + } + else + { + ARM7_SetCPSR(GET_CPSR &~ ARM7_CPSR_C); + } + SET_REGISTER( rd, (rrd & 0x80000000) ? ((0xFFFFFFFF<<(32-rrs)) | (rrd>>rrs)) : (rrd>>rrs)); + } + } + ARM7_SetCPSR(GET_CPSR &~ (ARM7_CPSR_N | ARM7_CPSR_Z)); + ARM7_SetCPSR( GET_CPSR | HandleALUNZFlags( GET_REGISTER(rd) ) ); + R15 += 2; + } + break; + case 0x5: /* ADC Rd, Rs */ + rs = ( insn & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = ( insn & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; + op2=(GET_CPSR & ARM7_CPSR_C) ? 1 : 0; + rn=GET_REGISTER(rd) + GET_REGISTER(rs) + op2; + HandleThumbALUAddFlags( rn, GET_REGISTER(rd), ( GET_REGISTER(rs) ) ); //? + SET_REGISTER( rd, rn); + break; + case 0x6: /* SBC Rd, Rs */ + rs = ( insn & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = ( insn & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; + op2=(GET_CPSR & ARM7_CPSR_C) ? 0 : 1; + rn=GET_REGISTER(rd) - GET_REGISTER(rs) - op2; + HandleThumbALUSubFlags( rn, GET_REGISTER(rd), ( GET_REGISTER(rs) ) ); //? + SET_REGISTER( rd, rn); + break; + case 0x7: /* ROR Rd, Rs */ + rs = ( insn & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = ( insn & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; + rrd = GET_REGISTER(rd); + imm = GET_REGISTER(rs) & 0x0000001f; + SET_REGISTER( rd, ( rrd >> imm ) | ( rrd << ( 32 - imm ) ) ); + if( rrd & ( 1 << ( imm - 1 ) ) ) + { + ARM7_SetCPSR( GET_CPSR | ARM7_CPSR_C ); + } + else + { + ARM7_SetCPSR( GET_CPSR &~ ARM7_CPSR_C ); + } + ARM7_SetCPSR( GET_CPSR &~ ( ARM7_CPSR_Z | ARM7_CPSR_N ) ); + ARM7_SetCPSR( GET_CPSR | HandleALUNZFlags( GET_REGISTER(rd) ) ); + R15 += 2; + break; + case 0x8: /* TST Rd, Rs */ + rs = ( insn & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = ( insn & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; + ARM7_SetCPSR( GET_CPSR &~ ( ARM7_CPSR_Z | ARM7_CPSR_N ) ); + ARM7_SetCPSR( GET_CPSR | HandleALUNZFlags( GET_REGISTER(rd) & GET_REGISTER(rs) ) ); + R15 += 2; + break; + case 0x9: /* NEG Rd, Rs - todo: check me */ + rs = ( insn & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = ( insn & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; + rrs = GET_REGISTER(rs); + rn = 0 - rrs; + SET_REGISTER( rd, rn ); + HandleThumbALUSubFlags( GET_REGISTER(rd), 0, rrs ); + break; + case 0xa: /* CMP Rd, Rs */ + rs = ( insn & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = ( insn & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; + rn = GET_REGISTER(rd) - GET_REGISTER(rs); + HandleThumbALUSubFlags( rn, GET_REGISTER(rd), GET_REGISTER(rs) ); + break; + case 0xb: /* CMN Rd, Rs - check flags, add dasm */ + rs = ( insn & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = ( insn & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; + rn = GET_REGISTER(rd) + GET_REGISTER(rs); + HandleThumbALUAddFlags( rn, GET_REGISTER(rd), GET_REGISTER(rs) ); + break; + case 0xc: /* ORR Rd, Rs */ + rs = ( insn & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = ( insn & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; + SET_REGISTER( rd, GET_REGISTER(rd) | GET_REGISTER(rs) ); + ARM7_SetCPSR( GET_CPSR &~ ( ARM7_CPSR_Z | ARM7_CPSR_N ) ); + ARM7_SetCPSR( GET_CPSR | HandleALUNZFlags( GET_REGISTER(rd) ) ); + R15 += 2; + break; + case 0xd: /* MUL Rd, Rs */ + rs = ( insn & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = ( insn & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; + rn = GET_REGISTER(rd) * GET_REGISTER(rs); + ARM7_SetCPSR( GET_CPSR &~ ( ARM7_CPSR_Z | ARM7_CPSR_N ) ); + SET_REGISTER( rd, rn ); + ARM7_SetCPSR( GET_CPSR | HandleALUNZFlags( rn ) ); + R15 += 2; + break; + case 0xe: /* BIC Rd, Rs */ + rs = ( insn & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = ( insn & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; + SET_REGISTER( rd, GET_REGISTER(rd) & (~GET_REGISTER(rs)) ); + ARM7_SetCPSR( GET_CPSR &~ ( ARM7_CPSR_Z | ARM7_CPSR_N ) ); + ARM7_SetCPSR( GET_CPSR | HandleALUNZFlags( GET_REGISTER(rd) ) ); + R15 += 2; + break; + case 0xf: /* MVN Rd, Rs */ + rs = ( insn & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = ( insn & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; + op2 = GET_REGISTER(rs); + SET_REGISTER( rd, ~op2 ); + ARM7_SetCPSR( GET_CPSR &~ ( ARM7_CPSR_Z | ARM7_CPSR_N ) ); + ARM7_SetCPSR( GET_CPSR | HandleALUNZFlags( GET_REGISTER(rd) ) ); + R15 += 2; + break; + default: + printf("%08x: G4-0 Undefined Thumb instruction: %04x %x\n", pc, insn, ( insn & THUMB_ALUOP_TYPE ) >> THUMB_ALUOP_TYPE_SHIFT); + R15 += 2; + break; + } + break; + case 0x1: + switch( ( insn & THUMB_HIREG_OP ) >> THUMB_HIREG_OP_SHIFT ) + { + case 0x0: /* ADD Rd, Rs */ + rs = ( insn & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT; + rd = insn & THUMB_HIREG_RD; + switch( ( insn & THUMB_HIREG_H ) >> THUMB_HIREG_H_SHIFT ) + { + case 0x1: /* ADD Rd, HRs */ + SET_REGISTER( rd, GET_REGISTER(rd) + GET_REGISTER(rs+8) ); + // emulate the effects of pre-fetch + if (rs == 7) + { + SET_REGISTER(rd, GET_REGISTER(rd) + 4); + } + break; + case 0x2: /* ADD HRd, Rs */ + SET_REGISTER( rd+8, GET_REGISTER(rd+8) + GET_REGISTER(rs) ); + if (rd == 7) + { + R15 += 2; + change_pc(R15); + } + break; + case 0x3: /* Add HRd, HRs */ + SET_REGISTER( rd+8, GET_REGISTER(rd+8) + GET_REGISTER(rs+8) ); + // emulate the effects of pre-fetch + if (rs == 7) + { + SET_REGISTER(rd+8, GET_REGISTER(rd+8) + 4); + } + if (rd == 7) + { + R15 += 2; + change_pc(R15); + } + break; + default: + printf("%08x: G4-1-0 Undefined Thumb instruction: %04x %x\n", pc, insn, ( insn & THUMB_HIREG_H ) >> THUMB_HIREG_H_SHIFT ); + break; + } + R15 += 2; + break; + case 0x1: /* CMP */ + switch( ( insn & THUMB_HIREG_H ) >> THUMB_HIREG_H_SHIFT ) + { + case 0x0: /* CMP Rd, Rs */ + rs = GET_REGISTER( ( ( insn & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT ) ); + rd = GET_REGISTER( insn & THUMB_HIREG_RD ); + rn = rd - rs; + HandleThumbALUSubFlags( rn, rd, rs ); + break; + case 0x1: /* CMP Rd, Hs */ + rs = GET_REGISTER( ( ( insn & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT ) + 8 ); + rd = GET_REGISTER( insn & THUMB_HIREG_RD ); + rn = rd - rs; + HandleThumbALUSubFlags( rn, rd, rs ); + break; + case 0x2: /* CMP Hd, Rs */ + rs = GET_REGISTER( ( ( insn & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT ) ); + rd = GET_REGISTER( (insn & THUMB_HIREG_RD) + 8 ); + rn = rd - rs; + HandleThumbALUSubFlags( rn, rd, rs ); + break; + case 0x3: /* CMP Hd, Hs */ + rs = GET_REGISTER( ( ( insn & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT ) + 8 ); + rd = GET_REGISTER( (insn & THUMB_HIREG_RD) + 8 ); + rn = rd - rs; + HandleThumbALUSubFlags( rn, rd, rs ); + break; + default: + printf("%08x: G4-1 Undefined Thumb instruction: %04x %x\n", pc, insn, ( insn & THUMB_HIREG_H ) >> THUMB_HIREG_H_SHIFT); + R15 += 2; + break; + } + break; + case 0x2: /* MOV */ + switch( ( insn & THUMB_HIREG_H ) >> THUMB_HIREG_H_SHIFT ) + { + case 0x1: // MOV Rd, Hs + rs = ( insn & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT; + rd = insn & THUMB_HIREG_RD; + if( rs == 7 ) + { + SET_REGISTER( rd, GET_REGISTER(rs + 8) + 4 ); + } + else + { + SET_REGISTER( rd, GET_REGISTER(rs + 8) ); + } + R15 += 2; + break; + case 0x2: // MOV Hd, Rs + rs = ( insn & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT; + rd = insn & THUMB_HIREG_RD; + SET_REGISTER( rd + 8, GET_REGISTER(rs) ); + if( rd != 7 ) + { + R15 += 2; + } + else + { + R15 &= ~1; + change_pc(R15); + } + break; + case 0x3: // MOV Hd, Hs + rs = ( insn & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT; + rd = insn & THUMB_HIREG_RD; + if (rs == 7) + { + SET_REGISTER( rd + 8, GET_REGISTER(rs+8)+4 ); + } + else + { + SET_REGISTER( rd + 8, GET_REGISTER(rs+8) ); + } + if( rd != 7 ) + { + R15 += 2; + } + + if( rd == 7 ) + { + R15 &= ~1; + change_pc(R15); + } + break; + default: + printf("%08x: G4-2 Undefined Thumb instruction: %04x (%x)\n", pc, insn, ( insn & THUMB_HIREG_H ) >> THUMB_HIREG_H_SHIFT); + R15 += 2; + break; + } + break; + case 0x3: + switch( ( insn & THUMB_HIREG_H ) >> THUMB_HIREG_H_SHIFT ) + { + case 0x0: + rd = ( insn & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT; + addr = GET_REGISTER(rd); + if( addr & 1 ) + { + addr &= ~1; + } + else + { + ARM7_SetCPSR(GET_CPSR &~ ARM7_CPSR_T); + if( addr & 2 ) + { + addr += 2; + } + } + R15 = addr; + break; + case 0x1: + addr = GET_REGISTER( ( ( insn & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT ) + 8 ); + if( ( ( ( insn & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT ) + 8 ) == 15 ) + { + addr += 2; + } + if( addr & 1 ) + { + addr &= ~1; + } + else + { + ARM7_SetCPSR(GET_CPSR &~ ARM7_CPSR_T); + if( addr & 2 ) + { + addr += 2; + } + } + R15 = addr; + break; + default: + printf("%08x: G4-3 Undefined Thumb instruction: %04x\n", pc, insn); + R15 += 2; + break; + } + break; + default: + printf("%08x: G4-x Undefined Thumb instruction: %04x\n", pc, insn); + R15 += 2; + break; + } + break; + case 0x2: + case 0x3: + readword = arm7_read_32( ( R15 & ~2 ) + 4 + ( ( insn & THUMB_INSN_IMM ) << 2 ) ); + SET_REGISTER( ( insn & THUMB_INSN_IMM_RD ) >> THUMB_INSN_IMM_RD_SHIFT, readword ); + R15 += 2; + break; + default: + printf("%08x: G4-y Undefined Thumb instruction: %04x\n", pc, insn); + R15 += 2; + break; + } + break; + case 0x5: /* LDR* STR* */ + switch( ( insn & THUMB_GROUP5_TYPE ) >> THUMB_GROUP5_TYPE_SHIFT ) + { + case 0x0: /* STR Rd, [Rn, Rm] */ + rm = ( insn & THUMB_GROUP5_RM ) >> THUMB_GROUP5_RM_SHIFT; + rn = ( insn & THUMB_GROUP5_RN ) >> THUMB_GROUP5_RN_SHIFT; + rd = ( insn & THUMB_GROUP5_RD ) >> THUMB_GROUP5_RD_SHIFT; + addr = GET_REGISTER(rn) + GET_REGISTER(rm); + arm7_write_32( addr, GET_REGISTER(rd) ); + R15 += 2; + break; + case 0x1: /* STRH Rd, [Rn, Rm] */ + rm = ( insn & THUMB_GROUP5_RM ) >> THUMB_GROUP5_RM_SHIFT; + rn = ( insn & THUMB_GROUP5_RN ) >> THUMB_GROUP5_RN_SHIFT; + rd = ( insn & THUMB_GROUP5_RD ) >> THUMB_GROUP5_RD_SHIFT; + addr = GET_REGISTER(rn) + GET_REGISTER(rm); + arm7_write_16( addr, GET_REGISTER(rd) ); + R15 += 2; + break; + case 0x2: /* STRB Rd, [Rn, Rm] */ + rm = ( insn & THUMB_GROUP5_RM ) >> THUMB_GROUP5_RM_SHIFT; + rn = ( insn & THUMB_GROUP5_RN ) >> THUMB_GROUP5_RN_SHIFT; + rd = ( insn & THUMB_GROUP5_RD ) >> THUMB_GROUP5_RD_SHIFT; + addr = GET_REGISTER(rn) + GET_REGISTER(rm); + arm7_write_8( addr, GET_REGISTER(rd) ); + R15 += 2; + break; + case 0x3: /* LDSB Rd, [Rn, Rm] todo, add dasm */ + rm = ( insn & THUMB_GROUP5_RM ) >> THUMB_GROUP5_RM_SHIFT; + rn = ( insn & THUMB_GROUP5_RN ) >> THUMB_GROUP5_RN_SHIFT; + rd = ( insn & THUMB_GROUP5_RD ) >> THUMB_GROUP5_RD_SHIFT; + addr = GET_REGISTER(rn) + GET_REGISTER(rm); + op2 = arm7_read_8( addr ); + if( op2 & 0x00000080 ) + { + op2 |= 0xffffff00; + } + SET_REGISTER( rd, op2 ); + R15 += 2; + break; + case 0x4: /* LDR Rd, [Rn, Rm] */ + rm = ( insn & THUMB_GROUP5_RM ) >> THUMB_GROUP5_RM_SHIFT; + rn = ( insn & THUMB_GROUP5_RN ) >> THUMB_GROUP5_RN_SHIFT; + rd = ( insn & THUMB_GROUP5_RD ) >> THUMB_GROUP5_RD_SHIFT; + addr = GET_REGISTER(rn) + GET_REGISTER(rm); + op2 = arm7_read_32( addr ); + SET_REGISTER( rd, op2 ); + R15 += 2; + break; + case 0x5: /* LDRH Rd, [Rn, Rm] */ + rm = ( insn & THUMB_GROUP5_RM ) >> THUMB_GROUP5_RM_SHIFT; + rn = ( insn & THUMB_GROUP5_RN ) >> THUMB_GROUP5_RN_SHIFT; + rd = ( insn & THUMB_GROUP5_RD ) >> THUMB_GROUP5_RD_SHIFT; + addr = GET_REGISTER(rn) + GET_REGISTER(rm); + op2 = arm7_read_16( addr ); + SET_REGISTER( rd, op2 ); + R15 += 2; + break; + + case 0x6: /* LDRB Rd, [Rn, Rm] */ + rm = ( insn & THUMB_GROUP5_RM ) >> THUMB_GROUP5_RM_SHIFT; + rn = ( insn & THUMB_GROUP5_RN ) >> THUMB_GROUP5_RN_SHIFT; + rd = ( insn & THUMB_GROUP5_RD ) >> THUMB_GROUP5_RD_SHIFT; + addr = GET_REGISTER(rn) + GET_REGISTER(rm); + op2 = arm7_read_8( addr ); + SET_REGISTER( rd, op2 ); + R15 += 2; + break; + case 0x7: /* LDSH Rd, [Rn, Rm] */ + rm = ( insn & THUMB_GROUP5_RM ) >> THUMB_GROUP5_RM_SHIFT; + rn = ( insn & THUMB_GROUP5_RN ) >> THUMB_GROUP5_RN_SHIFT; + rd = ( insn & THUMB_GROUP5_RD ) >> THUMB_GROUP5_RD_SHIFT; + addr = GET_REGISTER(rn) + GET_REGISTER(rm); + op2 = arm7_read_16( addr ); + if( op2 & 0x00008000 ) + { + op2 |= 0xffff0000; + } + SET_REGISTER( rd, op2 ); + R15 += 2; + break; + default: + printf("%08x: G5 Undefined Thumb instruction: %04x\n", pc, insn); + R15 += 2; + break; + } + break; + case 0x6: /* Word Store w/ Immediate Offset */ + if( insn & THUMB_LSOP_L ) /* Load */ + { + rn = ( insn & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = insn & THUMB_ADDSUB_RD; + offs = ( ( insn & THUMB_LSOP_OFFS ) >> THUMB_LSOP_OFFS_SHIFT ) << 2; + SET_REGISTER( rd, arm7_read_32(GET_REGISTER(rn) + offs) ); // fix + R15 += 2; + } + else /* Store */ + { + rn = ( insn & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = insn & THUMB_ADDSUB_RD; + offs = ( ( insn & THUMB_LSOP_OFFS ) >> THUMB_LSOP_OFFS_SHIFT ) << 2; + arm7_write_32( GET_REGISTER(rn) + offs, GET_REGISTER(rd) ); + R15 += 2; + } + break; + case 0x7: /* Byte Store w/ Immeidate Offset */ + if( insn & THUMB_LSOP_L ) /* Load */ + { + rn = ( insn & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = insn & THUMB_ADDSUB_RD; + offs = ( insn & THUMB_LSOP_OFFS ) >> THUMB_LSOP_OFFS_SHIFT; + SET_REGISTER( rd, arm7_read_8( GET_REGISTER(rn) + offs ) ); + R15 += 2; + } + else /* Store */ + { + rn = ( insn & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = insn & THUMB_ADDSUB_RD; + offs = ( insn & THUMB_LSOP_OFFS ) >> THUMB_LSOP_OFFS_SHIFT; + arm7_write_8( GET_REGISTER(rn) + offs, GET_REGISTER(rd) ); + R15 += 2; + } + break; + case 0x8: /* Load/Store Halfword */ + if( insn & THUMB_HALFOP_L ) /* Load */ + { + imm = ( insn & THUMB_HALFOP_OFFS ) >> THUMB_HALFOP_OFFS_SHIFT; + rs = ( insn & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = ( insn & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; + SET_REGISTER( rd, arm7_read_16( GET_REGISTER(rs) + ( imm << 1 ) ) ); + R15 += 2; + } + else /* Store */ + { + imm = ( insn & THUMB_HALFOP_OFFS ) >> THUMB_HALFOP_OFFS_SHIFT; + rs = ( insn & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = ( insn & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; + arm7_write_16( GET_REGISTER(rs) + ( imm << 1 ), GET_REGISTER(rd) ); + R15 += 2; + } + break; + case 0x9: /* Stack-Relative Load/Store */ + if( insn & THUMB_STACKOP_L ) + { + rd = ( insn & THUMB_STACKOP_RD ) >> THUMB_STACKOP_RD_SHIFT; + offs = (UINT8)( insn & THUMB_INSN_IMM ); + readword = arm7_read_32( GET_REGISTER(13) + ( (UINT32)offs << 2 ) ); + SET_REGISTER( rd, readword ); + R15 += 2; + } + else + { + rd = ( insn & THUMB_STACKOP_RD ) >> THUMB_STACKOP_RD_SHIFT; + offs = (UINT8)( insn & THUMB_INSN_IMM ); + arm7_write_32( GET_REGISTER(13) + ( (UINT32)offs << 2 ), GET_REGISTER(rd) ); + R15 += 2; + } + break; + case 0xa: /* Get relative address */ + if( insn & THUMB_RELADDR_SP ) /* ADD Rd, SP, #nn */ + { + rd = ( insn & THUMB_RELADDR_RD ) >> THUMB_RELADDR_RD_SHIFT; + offs = (UINT8)( insn & THUMB_INSN_IMM ) << 2; + SET_REGISTER( rd, GET_REGISTER(13) + offs ); + R15 += 2; + } + else /* ADD Rd, PC, #nn */ + { + rd = ( insn & THUMB_RELADDR_RD ) >> THUMB_RELADDR_RD_SHIFT; + offs = (UINT8)( insn & THUMB_INSN_IMM ) << 2; + SET_REGISTER( rd, ( ( R15 + 4 ) & ~2 ) + offs ); + R15 += 2; + } + break; + case 0xb: /* Stack-Related Opcodes */ + switch( ( insn & THUMB_STACKOP_TYPE ) >> THUMB_STACKOP_TYPE_SHIFT ) + { + case 0x0: /* ADD SP, #imm */ + addr = ( insn & THUMB_INSN_IMM ); + addr &= ~THUMB_INSN_IMM_S; + SET_REGISTER( 13, GET_REGISTER(13) + ( ( insn & THUMB_INSN_IMM_S ) ? -( addr << 2 ) : ( addr << 2 ) ) ); + R15 += 2; + break; + case 0x4: /* PUSH {Rlist} */ + for( offs = 7; offs >= 0; offs-- ) + { + if( insn & ( 1 << offs ) ) + { + SET_REGISTER( 13, GET_REGISTER(13) - 4 ); + arm7_write_32( GET_REGISTER(13), GET_REGISTER(offs) ); + } + } + R15 += 2; + break; + case 0x5: /* PUSH {Rlist}{LR} */ + SET_REGISTER( 13, GET_REGISTER(13) - 4 ); + arm7_write_32( GET_REGISTER(13), GET_REGISTER(14) ); + for( offs = 7; offs >= 0; offs-- ) + { + if( insn & ( 1 << offs ) ) + { + SET_REGISTER( 13, GET_REGISTER(13) - 4 ); + arm7_write_32( GET_REGISTER(13), GET_REGISTER(offs) ); + } + } + R15 += 2; + break; + case 0xc: /* POP {Rlist} */ + for( offs = 0; offs < 8; offs++ ) + { + if( insn & ( 1 << offs ) ) + { + SET_REGISTER( offs, arm7_read_32( GET_REGISTER(13) ) ); + SET_REGISTER( 13, GET_REGISTER(13) + 4 ); + } + } + R15 += 2; + break; + case 0xd: /* POP {Rlist}{PC} */ + for( offs = 0; offs < 8; offs++ ) + { + if( insn & ( 1 << offs ) ) + { + SET_REGISTER( offs, arm7_read_32( GET_REGISTER(13) ) ); + SET_REGISTER( 13, GET_REGISTER(13) + 4 ); + } + } + R15 = arm7_read_32( GET_REGISTER(13) ) & ~1; + SET_REGISTER( 13, GET_REGISTER(13) + 4 ); + break; + default: + printf("%08x: Gb Undefined Thumb instruction: %04x\n", pc, insn); + R15 += 2; + break; + } + break; + case 0xc: /* Multiple Load/Store */ + if( insn & THUMB_MULTLS ) /* Load */ + { + rd = ( insn & THUMB_MULTLS_BASE ) >> THUMB_MULTLS_BASE_SHIFT; + for( offs = 0; offs < 8; offs++ ) + { + if( insn & ( 1 << offs ) ) + { + SET_REGISTER( offs, arm7_read_32( (GET_REGISTER(rd)&0xfffffffc) ) ); + SET_REGISTER( rd, GET_REGISTER(rd) + 4 ); + } + } + R15 += 2; + } + else /* Store */ + { + rd = ( insn & THUMB_MULTLS_BASE ) >> THUMB_MULTLS_BASE_SHIFT; + for( offs = 0; offs < 8; offs++ ) + { + if( insn & ( 1 << offs ) ) + { + arm7_write_32( (GET_REGISTER(rd)&0xfffffffc), GET_REGISTER(offs) ); + SET_REGISTER( rd, GET_REGISTER(rd) + 4 ); + } + } + R15 += 2; + } + break; + case 0xd: /* Conditional Branch */ + offs = (INT8)( insn & THUMB_INSN_IMM ); + switch( ( insn & THUMB_COND_TYPE ) >> THUMB_COND_TYPE_SHIFT ) + { + case COND_EQ: + if( Z_IS_SET(GET_CPSR) ) + { + R15 += 4 + (offs << 1); + } + else + { + R15 += 2; + } + break; + case COND_NE: + if( Z_IS_CLEAR(GET_CPSR) ) + { + R15 += 4 + (offs << 1); + } + else + { + R15 += 2; + } + break; + case COND_CS: + if( C_IS_SET(GET_CPSR) ) + { + R15 += 4 + (offs << 1); + } + else + { + R15 += 2; + } + break; + case COND_CC: + if( C_IS_CLEAR(GET_CPSR) ) + { + R15 += 4 + (offs << 1); + } + else + { + R15 += 2; + } + break; + case COND_MI: + if( N_IS_SET(GET_CPSR) ) + { + R15 += 4 + (offs << 1); + } + else + { + R15 += 2; + } + break; + case COND_PL: + if( N_IS_CLEAR(GET_CPSR) ) + { + R15 += 4 + (offs << 1); + } + else + { + R15 += 2; + } + break; + case COND_VS: + if( V_IS_SET(GET_CPSR) ) + { + R15 += 4 + (offs << 1); + } + else + { + R15 += 2; + } + break; + case COND_VC: + if( V_IS_CLEAR(GET_CPSR) ) + { + R15 += 4 + (offs << 1); + } + else + { + R15 += 2; + } + break; + case COND_HI: + if( C_IS_SET(GET_CPSR) && Z_IS_CLEAR(GET_CPSR) ) + { + R15 += 4 + (offs << 1); + } + else + { + R15 += 2; + } + break; + case COND_LS: + if( C_IS_CLEAR(GET_CPSR) || Z_IS_SET(GET_CPSR) ) + { + R15 += 4 + (offs << 1); + } + else + { + R15 += 2; + } + break; + case COND_GE: + if( !(GET_CPSR & ARM7_CPSR_N) == !(GET_CPSR & ARM7_CPSR_V) ) + { + R15 += 4 + (offs << 1); + } + else + { + R15 += 2; + } + break; + case COND_LT: + if( !(GET_CPSR & ARM7_CPSR_N) != !(GET_CPSR & ARM7_CPSR_V) ) + { + R15 += 4 + (offs << 1); + } + else + { + R15 += 2; + } + break; + case COND_GT: + if( Z_IS_CLEAR(GET_CPSR) && ( !(GET_CPSR & ARM7_CPSR_N) == !(GET_CPSR & ARM7_CPSR_V) ) ) + { + R15 += 4 + (offs << 1); + } + else + { + R15 += 2; + } + break; + case COND_LE: + if( Z_IS_SET(GET_CPSR) || ( !(GET_CPSR & ARM7_CPSR_N) != !(GET_CPSR & ARM7_CPSR_V) ) ) + { + R15 += 4 + (offs << 1); + } + else + { + R15 += 2; + } + break; + case COND_AL: + printf("%08x: Undefined Thumb instruction: %04x (ARM9 reserved)\n", pc, insn); + R15 += 2; + break; + + case COND_NV: // SWI (this is sort of a "hole" in the opcode encoding) + ARM7_SetSWI(); +// R15 -= 4; + break; + } + break; + case 0xe: /* B #offs */ + if( insn & THUMB_BLOP_LO ) + { + addr = GET_REGISTER(14); + addr += ( insn & THUMB_BLOP_OFFS ) << 1; + addr &= 0xfffffffc; + SET_REGISTER( 14, ( R15 + 4 ) | 1 ); + R15 = addr; + } + else + { + offs = ( insn & THUMB_BRANCH_OFFS ) << 1; + if( offs & 0x00000800 ) + { + offs |= 0xfffff800; + } + R15 += 4 + offs; + } + break; + case 0xf: /* BL */ + if( insn & THUMB_BLOP_LO ) + { + addr = GET_REGISTER(14); + addr += ( insn & THUMB_BLOP_OFFS ) << 1; + SET_REGISTER( 14, ( R15 + 2 ) | 1 ); + R15 = addr; + } + else + { + addr = ( insn & THUMB_BLOP_OFFS ) << 12; + if( addr & ( 1 << 22 ) ) + { + addr |= 0xff800000; + } + addr += R15 + 4; + SET_REGISTER( 14, addr ); + R15 += 2; + } + break; + default: + printf("%08x: Undefined Thumb instruction: %04x\n", pc, insn); + R15 += 2; + break; + } + + return cycles; +} diff --git a/plugins/ao/eng_dsf/arm7thumb.h b/plugins/ao/eng_dsf/arm7thumb.h new file mode 100644 index 00000000..dabcd8ac --- /dev/null +++ b/plugins/ao/eng_dsf/arm7thumb.h @@ -0,0 +1,117 @@ +#ifndef _ARM7_THUMB_ +#define _ARM7_THUMB_ + +#define THUMB_INSN_TYPE ((UINT16) 0xf000) +#define THUMB_COND_TYPE ((UINT16) 0x0f00) +#define THUMB_GROUP4_TYPE ((UINT16) 0x0c00) +#define THUMB_GROUP5_TYPE ((UINT16) 0x0e00) +#define THUMB_GROUP5_RM ((UINT16) 0x01c0) +#define THUMB_GROUP5_RN ((UINT16) 0x0038) +#define THUMB_GROUP5_RD ((UINT16) 0x0007) +#define THUMB_ADDSUB_RNIMM ((UINT16) 0x01c0) +#define THUMB_ADDSUB_RS ((UINT16) 0x0038) +#define THUMB_ADDSUB_RD ((UINT16) 0x0007) +#define THUMB_INSN_ADDSUB ((UINT16) 0x0800) +#define THUMB_INSN_CMP ((UINT16) 0x0800) +#define THUMB_INSN_SUB ((UINT16) 0x0800) +#define THUMB_INSN_IMM_RD ((UINT16) 0x0700) +#define THUMB_INSN_IMM_S ((UINT16) 0x0080) +#define THUMB_INSN_IMM ((UINT16) 0x00ff) +#define THUMB_ADDSUB_TYPE ((UINT16) 0x0600) +#define THUMB_HIREG_OP ((UINT16) 0x0300) +#define THUMB_HIREG_H ((UINT16) 0x00c0) +#define THUMB_HIREG_RS ((UINT16) 0x0038) +#define THUMB_HIREG_RD ((UINT16) 0x0007) +#define THUMB_STACKOP_TYPE ((UINT16) 0x0f00) +#define THUMB_STACKOP_L ((UINT16) 0x0800) +#define THUMB_STACKOP_RD ((UINT16) 0x0700) +#define THUMB_ALUOP_TYPE ((UINT16) 0x03c0) +#define THUMB_BLOP_LO ((UINT16) 0x0800) +#define THUMB_BLOP_OFFS ((UINT16) 0x07ff) +#define THUMB_SHIFT_R ((UINT16) 0x0800) +#define THUMB_SHIFT_AMT ((UINT16) 0x07c0) +#define THUMB_HALFOP_L ((UINT16) 0x0800) +#define THUMB_HALFOP_OFFS ((UINT16) 0x07c0) +#define THUMB_BRANCH_OFFS ((UINT16) 0x07ff) +#define THUMB_LSOP_L ((UINT16) 0x0800) +#define THUMB_LSOP_OFFS ((UINT16) 0x07c0) +#define THUMB_MULTLS ((UINT16) 0x0800) +#define THUMB_MULTLS_BASE ((UINT16) 0x0700) +#define THUMB_RELADDR_SP ((UINT16) 0x0800) +#define THUMB_RELADDR_RD ((UINT16) 0x0700) +#define THUMB_INSN_TYPE_SHIFT 12 +#define THUMB_COND_TYPE_SHIFT 8 +#define THUMB_GROUP4_TYPE_SHIFT 10 +#define THUMB_GROUP5_TYPE_SHIFT 9 +#define THUMB_ADDSUB_TYPE_SHIFT 9 +#define THUMB_INSN_IMM_RD_SHIFT 8 +#define THUMB_STACKOP_TYPE_SHIFT 8 +#define THUMB_HIREG_OP_SHIFT 8 +#define THUMB_STACKOP_RD_SHIFT 8 +#define THUMB_MULTLS_BASE_SHIFT 8 +#define THUMB_RELADDR_RD_SHIFT 8 +#define THUMB_HIREG_H_SHIFT 6 +#define THUMB_HIREG_RS_SHIFT 3 +#define THUMB_ALUOP_TYPE_SHIFT 6 +#define THUMB_SHIFT_AMT_SHIFT 6 +#define THUMB_HALFOP_OFFS_SHIFT 6 +#define THUMB_LSOP_OFFS_SHIFT 6 +#define THUMB_GROUP5_RM_SHIFT 6 +#define THUMB_GROUP5_RN_SHIFT 3 +#define THUMB_GROUP5_RD_SHIFT 0 +#define THUMB_ADDSUB_RNIMM_SHIFT 6 +#define THUMB_ADDSUB_RS_SHIFT 3 +#define THUMB_ADDSUB_RD_SHIFT 0 + +#define THUMB_SIGN_BIT ((UINT32)(1<<31)) +#define THUMB_SIGN_BITS_DIFFER(a,b) (((a)^(b)) >> 31) + +#define N_IS_SET(pc) ((pc) & ARM7_CPSR_N) +#define Z_IS_SET(pc) ((pc) & ARM7_CPSR_Z) +#define C_IS_SET(pc) ((pc) & ARM7_CPSR_C) +#define V_IS_SET(pc) ((pc) & ARM7_CPSR_V) +#define I_IS_SET(pc) ((pc) & ARM7_CPSR_I) +#define F_IS_SET(pc) ((pc) & ARM7_CPSR_F) +#define T_IS_SET(pc) ((pc) & ARM7_CPSR_T) + +#define N_IS_CLEAR(pc) (!N_IS_SET(pc)) +#define Z_IS_CLEAR(pc) (!Z_IS_SET(pc)) +#define C_IS_CLEAR(pc) (!C_IS_SET(pc)) +#define V_IS_CLEAR(pc) (!V_IS_SET(pc)) +#define I_IS_CLEAR(pc) (!I_IS_SET(pc)) +#define F_IS_CLEAR(pc) (!F_IS_SET(pc)) +#define T_IS_CLEAR(pc) (!T_IS_SET(pc)) + +enum +{ + COND_EQ = 0, /* Z: equal */ + COND_NE, /* ~Z: not equal */ + COND_CS, COND_HS = 2, /* C: unsigned higher or same */ + COND_CC, COND_LO = 3, /* ~C: unsigned lower */ + COND_MI, /* N: negative */ + COND_PL, /* ~N: positive or zero */ + COND_VS, /* V: overflow */ + COND_VC, /* ~V: no overflow */ + COND_HI, /* C && ~Z: unsigned higher */ + COND_LS, /* ~C || Z: unsigned lower or same */ + COND_GE, /* N == V: greater or equal */ + COND_LT, /* N != V: less than */ + COND_GT, /* ~Z && (N == V): greater than */ + COND_LE, /* Z || (N != V): less than or equal */ + COND_AL, /* always */ + COND_NV /* never */ +}; + +#define GET_CPSR ARM7.Rx [ARM7_CPSR] + +#define GET_REGISTER(r) ARM7.Rx[(r)] +#define SET_REGISTER(r, v) ARM7.Rx[(r)] = (v) + +#define R15 ARM7.Rx[ARM7_PC] + + +// public function +int ARM7i_Thumb_Step(void); + +#endif + diff --git a/plugins/ao/eng_dsf/dc_hw.c b/plugins/ao/eng_dsf/dc_hw.c new file mode 100644 index 00000000..769e128a --- /dev/null +++ b/plugins/ao/eng_dsf/dc_hw.c @@ -0,0 +1,182 @@ +// dc_hw.c - Hardware found on the ARM7/AICA side of the Dreamcast + +#include "ao.h" +#include "dc_hw.h" +#include "aica.h" + +#define DK_CORE (1) + +#if DK_CORE +#include "arm7.h" +#else +#include "arm7core.h" +#endif + +static void aica_irq(struct sARM7 *cpu, int irq) +{ + if (irq > 0) + { + #if DK_CORE + ARM7_SetFIQ(cpu, TRUE); + #else + set_irq_line(ARM7_FIRQ_LINE, 1); + #endif + } + else + { + #if DK_CORE + ARM7_SetFIQ(cpu, FALSE); + #else + set_irq_line(ARM7_FIRQ_LINE, 0); + #endif + } +} + +#define MIXER_PAN_LEFT 1 +#define MIXER_PAN_RIGHT 2 +#define MIXER(level,pan) ((level & 0xff) | ((pan & 0x03) << 8)) +#define YM3012_VOL(LVol,LPan,RVol,RPan) (MIXER(LVol,LPan)|(MIXER(RVol,RPan) << 16)) + +uint8 dc_read8(struct sARM7 *cpu, int addr) +{ + if (addr < 0x800000) + { + return cpu->dc_ram[addr]; + } + + if ((addr >= 0x800000) && (addr <= 0x807fff)) + { + int foo = AICA_0_r(cpu->AICA, (addr-0x800000)/2, 0); + + if (addr & 1) + { + return foo>>8; + } + else + { + return foo & 0xff; + } + } + + printf("R8 @ %x\n", addr); + return -1; +} + +uint16 dc_read16(struct sARM7 *cpu, int addr) +{ + if (addr < 0x800000) + { + return cpu->dc_ram[addr] | (cpu->dc_ram[addr+1]<<8); + } + + if ((addr >= 0x800000) && (addr <= 0x807fff)) + { + return AICA_0_r(cpu->AICA, (addr-0x800000)/2, 0); + } + + printf("R16 @ %x\n", addr); + return -1; +} + +uint32 dc_read32(struct sARM7 *cpu, int addr) +{ + if (addr < 0x800000) + { + return cpu->dc_ram[addr] | (cpu->dc_ram[addr+1]<<8) | (cpu->dc_ram[addr+2]<<16) | (cpu->dc_ram[addr+3]<<24); + } + + if ((addr >= 0x800000) && (addr <= 0x807fff)) + { + addr &= 0x7fff; + return AICA_0_r(cpu->AICA, addr/2, 0) & 0xffff; + } + +// printf("R32 @ %x\n", addr); + return 0; +} + +void dc_write8(struct sARM7 *cpu, int addr, uint8 data) +{ + if (addr < 0x800000) + { + cpu->dc_ram[addr] = data; + return; + } + + if ((addr >= 0x800000) && (addr <= 0x807fff)) + { + addr -= 0x800000; + if ((addr & 1)) + AICA_0_w(cpu->AICA, addr>>1, data<<8, 0x00ff); + else + AICA_0_w(cpu->AICA, addr>>1, data, 0xff00); + return; + } + + printf("W8 %x @ %x\n", data, addr); +} + +void dc_write16(struct sARM7 *cpu, int addr, uint16 data) +{ + if (addr < 0x800000) + { + cpu->dc_ram[addr] = data&0xff; + cpu->dc_ram[addr+1] = (data>>8) & 0xff; + return; + } + + if ((addr >= 0x800000) && (addr <= 0x807fff)) + { + AICA_0_w(cpu->AICA, (addr-0x800000)/2, data, 0); + return; + } + + printf("W16 %x @ %x\n", data, addr); +} + +void dc_write32(struct sARM7 *cpu, int addr, uint32 data) +{ + if (addr < 0x800000) + { + cpu->dc_ram[addr] = data&0xff; + cpu->dc_ram[addr+1] = (data>>8) & 0xff; + cpu->dc_ram[addr+2] = (data>>16) & 0xff; + cpu->dc_ram[addr+3] = (data>>24) & 0xff; + return; + } + + if ((addr >= 0x800000) && (addr <= 0x807fff)) + { + addr -= 0x800000; + AICA_0_w(cpu->AICA, (addr>>1), data&0xffff, 0x0000); + AICA_0_w(cpu->AICA, (addr>>1)+1, data>>16, 0x0000); + return; + } + + printf("W32 %x @ %x\n", data, addr); +} + +void dc_hw_init(struct sARM7 *cpu) +{ +#if 0 +static struct AICAinterface aica_interface = +{ + 1, + { cpu->dc_ram, }, + { YM3012_VOL(100, MIXER_PAN_LEFT, 100, MIXER_PAN_RIGHT) }, + { aica_irq, }, +}; +#endif + + cpu->aica_interface.num = 1; + cpu->aica_interface.region[0] = cpu->dc_ram; + cpu->aica_interface.mixing_level[0] = YM3012_VOL(100, MIXER_PAN_LEFT, 100, MIXER_PAN_RIGHT); + cpu->aica_interface.irq_callback[0] = aica_irq; + cpu->aica_interface.cpu = cpu; + cpu->AICA = aica_start(&cpu->aica_interface); +} + +void dc_hw_free (struct sARM7 *cpu) { + aica_stop (cpu->AICA); + cpu->AICA = NULL; +} diff --git a/plugins/ao/eng_dsf/dc_hw.h b/plugins/ao/eng_dsf/dc_hw.h new file mode 100644 index 00000000..33345efe --- /dev/null +++ b/plugins/ao/eng_dsf/dc_hw.h @@ -0,0 +1,16 @@ +#ifndef _DC_HW_H_ +#define _DC_HW_H_ + +#include "arm7i.h" + +void dc_hw_init(struct sARM7 *cpu); +void dc_hw_free (struct sARM7 *cpu); +void dc_write8(struct sARM7 *cpu, int addr, uint8 data); +void dc_write16(struct sARM7 *cpu, int addr, uint16 data); +void dc_write32(struct sARM7 *cpu, int addr, uint32 data); +uint8 dc_read8(struct sARM7 *cpu, int addr); +uint16 dc_read16(struct sARM7 *cpu, int addr); +uint32 dc_read32(struct sARM7 *cpu, int addr); + +#endif + diff --git a/plugins/ao/eng_dsf/eng_dsf.c b/plugins/ao/eng_dsf/eng_dsf.c new file mode 100644 index 00000000..b58b6ed4 --- /dev/null +++ b/plugins/ao/eng_dsf/eng_dsf.c @@ -0,0 +1,288 @@ +// +// Audio Overload +// Emulated music player +// +// (C) 2000-2008 Richard F. Bannister +// + +// +// eng_dsf.c +// + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "ao.h" +#include "eng_protos.h" +#include "corlett.h" +#include "dc_hw.h" +#include "cpuintrf.h" +#include "aica.h" +#include "aicadsp.h" + +#define DEBUG_LOADER (1) +#define DK_CORE (1) + +#if DK_CORE +#include "arm7.h" +#else +#include "arm7core.h" +#endif + +typedef struct { + corlett_t *c; + char psfby[256]; + uint32 decaybegin, decayend, total_samples; + struct sARM7 *cpu; + uint8 init_dc_ram[8*1024*1024]; +} dsf_synth_t; + +void *dsf_start(const char *path, uint8 *buffer, uint32 length) +{ + dsf_synth_t *s = malloc (sizeof (dsf_synth_t)); + memset (s, 0, sizeof (dsf_synth_t)); + + uint8 *file, *lib_decoded, *lib_raw_file; + uint32 offset, plength, lengthMS, fadeMS; + uint64 file_len, lib_len, lib_raw_length; + corlett_t *lib; + char *libfile; + int i; + + // Decode the current SSF + if (corlett_decode(buffer, length, &file, &file_len, &s->c) != AO_SUCCESS) + { + dsf_stop (s); + return NULL; + } + + #if DEBUG_LOADER + printf("%d bytes decoded\n", file_len); + #endif + + s->cpu = ARM7_Alloc (); + // Get the library file, if any + for (i=0; i<9; i++) { + libfile = i ? s->c->libaux[i-1] : s->c->lib; + if (libfile[0] != 0) + { + uint64 tmp_length; + char libpath[PATH_MAX]; + const char *e = path + strlen(path); + while (e > path && *e != '/') { + e--; + } + if (*e == '/') { + e++; + memcpy (libpath, path, e-path); + libpath[e-path] = 0; + strcat (libpath, libfile); + } + else { + strcpy (libpath, libfile); + } + + #if DEBUG_LOADER + printf("Loading library: %s\n", libpath); + #endif + if (ao_get_lib(libpath, &lib_raw_file, &tmp_length) != AO_SUCCESS) + { + dsf_stop (s); + return NULL; + } + lib_raw_length = tmp_length; + + if (corlett_decode(lib_raw_file, lib_raw_length, &lib_decoded, &lib_len, &lib) != AO_SUCCESS) + { + free(lib_raw_file); + dsf_stop (s); + return NULL; + } + + // Free up raw file + free(lib_raw_file); + + // patch the file into ram + offset = lib_decoded[0] | lib_decoded[1]<<8 | lib_decoded[2]<<16 | lib_decoded[3]<<24; + memcpy(&s->cpu->dc_ram[offset], lib_decoded+4, lib_len-4); + + // Dispose the corlett structure for the lib - we don't use it + free(lib); + } + } + + // now patch the file into RAM over the libraries + offset = file[3]<<24 | file[2]<<16 | file[1]<<8 | file[0]; + memcpy(&s->cpu->dc_ram[offset], file+4, file_len-4); + + free(file); + + // Finally, set psfby/ssfby tag + strcpy(s->psfby, "n/a"); + if (s->c) + { + for (i = 0; i < MAX_UNKNOWN_TAGS; i++) + { + if ((!strcasecmp(s->c->tag_name[i], "psfby")) || (!strcasecmp(s->c->tag_name[i], "ssfby"))) + strcpy(s->psfby, s->c->tag_data[i]); + } + } + + #if DEBUG_LOADER && 0 + { + FILE *f; + + f = fopen("dcram.bin", "wb"); + fwrite(s->cpu->dc_ram, 2*1024*1024, 1, f); + fclose(f); + } + #endif + + + memcpy (s->init_dc_ram, s->cpu->dc_ram, sizeof (s->init_dc_ram)); + #if DK_CORE + ARM7_Init(s->cpu); + #else + arm7_init(cpu, 0, 45000000, NULL, NULL); + arm7_reset(s->cpu); + #endif + dc_hw_init(s->cpu); + + // now figure out the time in samples for the length/fade + lengthMS = psfTimeToMS(s->c->inf_length); + fadeMS = psfTimeToMS(s->c->inf_fade); + s->total_samples = 0; + + if (lengthMS == 0) + { + lengthMS = ~0; + } + + if (lengthMS == ~0) + { + s->decaybegin = lengthMS; + } + else + { + lengthMS = (lengthMS * 441) / 10; + fadeMS = (fadeMS * 441) / 10; + + s->decaybegin = lengthMS; + s->decayend = lengthMS + fadeMS; + } + + return s; +} + +int32 dsf_gen(void *handle, int16 *buffer, uint32 samples) +{ + dsf_synth_t *s = handle; + + int i; + int16 output[44100/30], output2[44100/30]; + int16 *stereo[2]; + int16 *outp = buffer; + int opos; + + opos = 0; + for (i = 0; i < samples; i++) + { + #if DK_CORE + ARM7_Execute(s->cpu, (33000000 / 60 / 4) / 735); + #else + arm7_execute(s->cpu, (33000000 / 60 / 4) / 735); + #endif + stereo[0] = &output[opos]; + stereo[1] = &output2[opos]; + AICA_Update(s->cpu->AICA, NULL, NULL, stereo, 1); + opos++; + } + + for (i = 0; i < samples; i++) + { + // process the fade tags + if (s->total_samples >= s->decaybegin) + { + if (s->total_samples >= s->decayend) + { + // song is done here, signal your player appropriately! +// ao_song_done = 1; + output[i] = 0; + output2[i] = 0; + } + else + { + int32 fader = 256 - (256*(s->total_samples - s->decaybegin)/(s->decayend-s->decaybegin)); + output[i] = (output[i] * fader)>>8; + output2[i] = (output2[i] * fader)>>8; + + s->total_samples++; + } + } + else + { + s->total_samples++; + } + + *outp++ = output[i]; + *outp++ = output2[i]; + } + + return AO_SUCCESS; +} + +int32 dsf_stop(void *handle) +{ + return AO_SUCCESS; +} + +int32 dsf_command(void *handle, int32 command, int32 parameter) +{ + dsf_synth_t *s = handle; + switch (command) + { + case COMMAND_RESTART: + dc_hw_free (s->cpu); + memcpy (s->cpu->dc_ram, s->init_dc_ram, sizeof (s->init_dc_ram)); + ARM7_Init(s->cpu); + dc_hw_init (s->cpu); + s->total_samples = 0; + return AO_SUCCESS; + + } + return AO_FAIL; +} + +int32 dsf_fill_info(void *handle, ao_display_info *info) +{ + dsf_synth_t *s = handle; + if (s->c == NULL) + return AO_FAIL; + + strcpy(info->title[1], "Name: "); + sprintf(info->info[1], "%s", s->c->inf_title); + + strcpy(info->title[2], "Game: "); + sprintf(info->info[2], "%s", s->c->inf_game); + + strcpy(info->title[3], "Artist: "); + sprintf(info->info[3], "%s", s->c->inf_artist); + + strcpy(info->title[4], "Copyright: "); + sprintf(info->info[4], "%s", s->c->inf_copy); + + strcpy(info->title[5], "Year: "); + sprintf(info->info[5], "%s", s->c->inf_year); + + strcpy(info->title[6], "Length: "); + sprintf(info->info[6], "%s", s->c->inf_length); + + strcpy(info->title[7], "Fade: "); + sprintf(info->info[7], "%s", s->c->inf_fade); + + strcpy(info->title[8], "Ripper: "); + sprintf(info->info[8], "%s", s->psfby); + + return AO_SUCCESS; +} diff --git a/plugins/ao/eng_protos.h b/plugins/ao/eng_protos.h new file mode 100644 index 00000000..9f4a02a1 --- /dev/null +++ b/plugins/ao/eng_protos.h @@ -0,0 +1,53 @@ +// +// Audio Overload +// Emulated music player +// +// (C) 2000-2007 Richard F. Bannister +// + +// +// eng_protos.h +// + +void *psf_start(const char *path, uint8 *, uint32 length); +int32 psf_gen(void *, int16 *, uint32); +int32 psf_stop(void *); +int32 psf_command(void *, int32, int32); +int32 psf_fill_info(void *, ao_display_info *); + +void *psf2_start(const char *path, uint8 *, uint32 length); +int32 psf2_gen(void *, int16 *, uint32); +int32 psf2_stop(void *); +int32 psf2_command(void *, int32, int32); +int32 psf2_fill_info(void *, ao_display_info *); + +void *qsf_start(const char *path, uint8 *, uint32 length); +int32 qsf_gen(void *, int16 *, uint32); +int32 qsf_stop(void *); +int32 qsf_command(void *, int32, int32); +int32 qsf_fill_info(void*, ao_display_info *); + +void *ssf_start(const char *path, uint8 *, uint32 length); +int32 ssf_gen(void *, int16 *, uint32); +int32 ssf_stop(void *); +int32 ssf_command(void *, int32, int32); +int32 ssf_fill_info(void *, ao_display_info *); + +void *spu_start(const char *path, uint8 *, uint32 length); +int32 spu_gen(void *, int16 *, uint32); +int32 spu_stop(void *); +int32 spu_command(void *, int32, int32); +int32 spu_fill_info(void *, ao_display_info *); + +uint8 qsf_memory_read(uint16 addr); +uint8 qsf_memory_readop(uint16 addr); +uint8 qsf_memory_readport(uint16 addr); +void qsf_memory_write(uint16 addr, uint8 byte); +void qsf_memory_writeport(uint16 addr, uint8 byte); + +void *dsf_start(const char *path, uint8 *, uint32 length); +int32 dsf_gen(void *, int16 *, uint32); +int32 dsf_stop(void *); +int32 dsf_command(void *, int32, int32); +int32 dsf_fill_info(void *, ao_display_info *); + diff --git a/plugins/ao/eng_psf/cpuintrf.h b/plugins/ao/eng_psf/cpuintrf.h new file mode 100644 index 00000000..1317f418 --- /dev/null +++ b/plugins/ao/eng_psf/cpuintrf.h @@ -0,0 +1,668 @@ +#ifndef CPUINTRF_H +#define CPUINTRF_H + +#include "osd_cpu.h" + +/* The old system is obsolete and no longer supported by the core */ +#define NEW_INTERRUPT_SYSTEM 1 + +#define MAX_IRQ_LINES 8 /* maximum number of IRQ lines per CPU */ + +#define CLEAR_LINE 0 /* clear (a fired, held or pulsed) line */ +#define ASSERT_LINE 1 /* assert an interrupt immediately */ +#define HOLD_LINE 2 /* hold interrupt line until enable is true */ +#define PULSE_LINE 3 /* pulse interrupt line for one instruction */ + +#define MAX_REGS 64 /* maximum number of register of any CPU */ + +#define IRQ_LINE_NMI 10 +/* Values passed to the cpu_info function of a core to retrieve information */ +enum { + CPU_INFO_REG, + CPU_INFO_FLAGS=MAX_REGS, + CPU_INFO_NAME, + CPU_INFO_FAMILY, + CPU_INFO_VERSION, + CPU_INFO_FILE, + CPU_INFO_CREDITS, + CPU_INFO_REG_LAYOUT, + CPU_INFO_WIN_LAYOUT +}; + +#define CPU_IS_LE 0 /* emulated CPU is little endian */ +#define CPU_IS_BE 1 /* emulated CPU is big endian */ + +/* + * This value is passed to cpu_get_reg to retrieve the previous + * program counter value, ie. before a CPU emulation started + * to fetch opcodes and arguments for the current instrution. + */ +#define REG_PREVIOUSPC -1 + +/* + * This value is passed to cpu_get_reg/cpu_set_reg, instead of one of + * the names from the enum a CPU core defines for it's registers, + * to get or set the contents of the memory pointed to by a stack pointer. + * You can specify the n'th element on the stack by (REG_SP_CONTENTS-n), + * ie. lower negative values. The actual element size (UINT16 or UINT32) + * depends on the CPU core. + * This is also used to replace the cpu_geturnpc() function. + */ +#define REG_SP_CONTENTS -2 + +/* + * These flags can be defined in the makefile (or project) to + * exclude (zero) or include (non zero) specific CPU cores + */ +#ifndef HAS_GENSYNC +#define HAS_GENSYNC 0 +#endif +#ifndef HAS_Z80 +#define HAS_Z80 0 +#endif +#ifndef HAS_Z80_VM +#define HAS_Z80_VM 0 +#endif +#ifndef HAS_8080 +#define HAS_8080 0 +#endif +#ifndef HAS_8085A +#define HAS_8085A 0 +#endif +#ifndef HAS_M6502 +#define HAS_M6502 0 +#endif +#ifndef HAS_M65C02 +#define HAS_M65C02 0 +#endif +#ifndef HAS_M65SC02 +#define HAS_M65SC02 0 +#endif +#ifndef HAS_M65CE02 +#define HAS_M65CE02 0 +#endif +#ifndef HAS_M6509 +#define HAS_M6509 0 +#endif +#ifndef HAS_M6510 +#define HAS_M6510 0 +#endif +#ifndef HAS_N2A03 +#define HAS_N2A03 0 +#endif +#ifndef HAS_H6280 +#define HAS_H6280 0 +#endif +#ifndef HAS_I86 +#define HAS_I86 0 +#endif +#ifndef HAS_V20 +#define HAS_V20 0 +#endif +#ifndef HAS_V30 +#define HAS_V30 0 +#endif +#ifndef HAS_V33 +#define HAS_V33 0 +#endif +#ifndef HAS_I8035 +#define HAS_I8035 0 +#endif +#ifndef HAS_I8039 +#define HAS_I8039 0 +#endif +#ifndef HAS_I8048 +#define HAS_I8048 0 +#endif +#ifndef HAS_N7751 +#define HAS_N7751 0 +#endif +#ifndef HAS_M6800 +#define HAS_M6800 0 +#endif +#ifndef HAS_M6801 +#define HAS_M6801 0 +#endif +#ifndef HAS_M6802 +#define HAS_M6802 0 +#endif +#ifndef HAS_M6803 +#define HAS_M6803 0 +#endif +#ifndef HAS_M6808 +#define HAS_M6808 0 +#endif +#ifndef HAS_HD63701 +#define HAS_HD63701 0 +#endif +#ifndef HAS_M6805 +#define HAS_M6805 0 +#endif +#ifndef HAS_M68705 +#define HAS_M68705 0 +#endif +#ifndef HAS_HD63705 +#define HAS_HD63705 0 +#endif +#ifndef HAS_HD6309 +#define HAS_HD6309 0 +#endif +#ifndef HAS_M6809 +#define HAS_M6809 0 +#endif +#ifndef HAS_KONAMI +#define HAS_KONAMI 0 +#endif +#ifndef HAS_M68000 +#define HAS_M68000 0 +#endif +#ifndef HAS_M68010 +#define HAS_M68010 0 +#endif +#ifndef HAS_M68020 +#define HAS_M68020 0 +#endif +#ifndef HAS_T11 +#define HAS_T11 0 +#endif +#ifndef HAS_S2650 +#define HAS_S2650 0 +#endif +#ifndef HAS_TMS34010 +#define HAS_TMS34010 0 +#endif +#ifndef HAS_TMS9900 +#define HAS_TMS9900 0 +#endif +#ifndef HAS_TMS9940 +#define HAS_TMS9940 0 +#endif +#ifndef HAS_TMS9980 +#define HAS_TMS9980 0 +#endif +#ifndef HAS_TMS9985 +#define HAS_TMS9985 0 +#endif +#ifndef HAS_TMS9989 +#define HAS_TMS9989 0 +#endif +#ifndef HAS_TMS9995 +#define HAS_TMS9995 0 +#endif +#ifndef HAS_TMS99105A +#define HAS_TMS99105A 0 +#endif +#ifndef HAS_TMS99110A +#define HAS_TMS99110A 0 +#endif +#ifndef HAS_Z8000 +#define HAS_Z8000 0 +#endif +#ifndef HAS_TMS320C10 +#define HAS_TMS320C10 0 +#endif +#ifndef HAS_CCPU +#define HAS_CCPU 0 +#endif +#ifndef HAS_PDP1 +#define HAS_PDP1 0 +#endif +#ifndef HAS_ADSP2100 +#define HAS_ADSP2100 0 +#endif + +/* ASG 971222 -- added this generic structure */ +struct cpu_interface +{ + unsigned cpu_num; + void (*reset)(void *param); + void (*exit)(void); + int (*execute)(int cycles); + void (*burn)(int cycles); + unsigned (*get_context)(void *reg); + void (*set_context)(void *reg); + unsigned (*get_pc)(void); + void (*set_pc)(unsigned val); + unsigned (*get_sp)(void); + void (*set_sp)(unsigned val); + unsigned (*get_reg)(int regnum); + void (*set_reg)(int regnum, unsigned val); + void (*set_nmi_line)(int linestate); + void (*set_irq_line)(int irqline, int linestate); + void (*set_irq_callback)(int(*callback)(int irqline)); + void (*internal_interrupt)(int type); + void (*cpu_state_save)(void *file); + void (*cpu_state_load)(void *file); + const char* (*cpu_info)(void *context,int regnum); + unsigned (*cpu_dasm)(char *buffer,unsigned pc); + unsigned num_irqs; + int default_vector; + int *icount; + double overclock; + int no_int, irq_int, nmi_int; + int (*memory_read)(int offset); + void (*memory_write)(int offset, int data); + void (*set_op_base)(int pc); + int address_shift; + unsigned address_bits, endianess, align_unit, max_inst_len; + unsigned abits1, abits2, abitsmin; +}; + +extern struct cpu_interface cpuintf[]; + +void cpu_init(void); +void cpu_run(void); + +/* optional watchdog */ +void watchdog_reset_w(int offset,int data); +int watchdog_reset_r(int offset); +/* Use this function to reset the machine */ +void machine_reset(void); +/* Use this function to reset a single CPU */ +void cpu_set_reset_line(int cpu,int state); +/* Use this function to halt a single CPU */ +void cpu_set_halt_line(int cpu,int state); + +/* This function returns CPUNUM current status (running or halted) */ +int cpu_getstatus(int cpunum); +int cpu_gettotalcpu(void); +int cpu_getactivecpu(void); +void cpu_setactivecpu(int cpunum); + +/* Returns the current program counter */ +unsigned cpu_get_pc(void); +/* Set the current program counter */ +void cpu_set_pc(unsigned val); + +/* Returns the current stack pointer */ +unsigned cpu_get_sp(void); +/* Set the current stack pointer */ +void cpu_set_sp(unsigned val); + +/* Get the active CPUs context and return it's size */ +unsigned cpu_get_context(void *context); +/* Set the active CPUs context */ +void cpu_set_context(void *context); + +/* Returns a specific register value (mamedbg) */ +unsigned cpu_get_reg(int regnum); +/* Sets a specific register value (mamedbg) */ +void cpu_set_reg(int regnum, unsigned val); + +/* Returns previous pc (start of opcode causing read/write) */ +/* int cpu_getpreviouspc(void); */ +#define cpu_getpreviouspc() cpu_get_reg(REG_PREVIOUSPC) + +/* Returns the return address from the top of the stack (Z80 only) */ +/* int cpu_getreturnpc(void); */ +/* This can now be handled with a generic function */ +#define cpu_geturnpc() cpu_get_reg(REG_SP_CONTENTS) + +int cycles_currently_ran(void); +int cycles_left_to_run(void); + +/* Returns the number of CPU cycles which take place in one video frame */ +int cpu_gettotalcycles(void); +/* Returns the number of CPU cycles before the next interrupt handler call */ +int cpu_geticount(void); +/* Returns the number of CPU cycles before the end of the current video frame */ +int cpu_getfcount(void); +/* Returns the number of CPU cycles in one video frame */ +int cpu_getfperiod(void); +/* Scales a given value by the ratio of fcount / fperiod */ +int cpu_scalebyfcount(int value); +/* Returns the current scanline number */ +int cpu_getscanline(void); +/* Returns the amount of time until a given scanline */ +double cpu_getscanlinetime(int scanline); +/* Returns the duration of a single scanline */ +double cpu_getscanlineperiod(void); +/* Returns the duration of a single scanline in cycles */ +int cpu_getscanlinecycles(void); +/* Returns the number of cycles since the beginning of this frame */ +int cpu_getcurrentcycles(void); +/* Returns the current horizontal beam position in pixels */ +int cpu_gethorzbeampos(void); +/* + Returns the number of times the interrupt handler will be called before + the end of the current video frame. This is can be useful to interrupt + handlers to synchronize their operation. If you call this from outside + an interrupt handler, add 1 to the result, i.e. if it returns 0, it means + that the interrupt handler will be called once. +*/ +int cpu_getiloops(void); + +/* Returns the current VBLANK state */ +int cpu_getvblank(void); + +/* Returns the number of the video frame we are currently playing */ +int cpu_getcurrentframe(void); + + +/* generate a trigger after a specific period of time */ +void cpu_triggertime (double duration, int trigger); +/* generate a trigger now */ +void cpu_trigger (int trigger); + +/* burn CPU cycles until a timer trigger */ +void cpu_spinuntil_trigger (int trigger); +/* burn CPU cycles until the next interrupt */ +void cpu_spinuntil_int (void); +/* burn CPU cycles until our timeslice is up */ +void cpu_spin (void); +/* burn CPU cycles for a specific period of time */ +void cpu_spinuntil_time (double duration); + +/* yield our timeslice for a specific period of time */ +void cpu_yielduntil_trigger (int trigger); +/* yield our timeslice until the next interrupt */ +void cpu_yielduntil_int (void); +/* yield our current timeslice */ +void cpu_yield (void); +/* yield our timeslice for a specific period of time */ +void cpu_yielduntil_time (double duration); + +/* set the NMI line state for a CPU, normally use PULSE_LINE */ +void cpu_set_nmi_line(int cpunum, int state); +/* set the IRQ line state for a specific irq line of a CPU */ +/* normally use state HOLD_LINE, irqline 0 for first IRQ type of a cpu */ +void cpu_set_irq_line(int cpunum, int irqline, int state); +/* this is to be called by CPU cores only! */ +void cpu_generate_internal_interrupt(int cpunum, int type); +/* set the vector to be returned during a CPU's interrupt acknowledge cycle */ +void cpu_irq_line_vector_w(int cpunum, int irqline, int vector); + +/* use these in your write memory/port handles to set an IRQ vector */ +/* offset corresponds to the irq line number here */ +void cpu_0_irq_line_vector_w(int offset, int data); +void cpu_1_irq_line_vector_w(int offset, int data); +void cpu_2_irq_line_vector_w(int offset, int data); +void cpu_3_irq_line_vector_w(int offset, int data); +void cpu_4_irq_line_vector_w(int offset, int data); +void cpu_5_irq_line_vector_w(int offset, int data); +void cpu_6_irq_line_vector_w(int offset, int data); +void cpu_7_irq_line_vector_w(int offset, int data); + +/* Obsolete functions: avoid to use them in new drivers if possible. */ + +/* cause an interrupt on a CPU */ +void cpu_cause_interrupt(int cpu,int type); +void cpu_clear_pending_interrupts(int cpu); +void interrupt_enable_w(int offset,int data); +void interrupt_vector_w(int offset,int data); +int interrupt(void); +int nmi_interrupt(void); +int m68_level1_irq(void); +int m68_level2_irq(void); +int m68_level3_irq(void); +int m68_level4_irq(void); +int m68_level5_irq(void); +int m68_level6_irq(void); +int m68_level7_irq(void); +int ignore_interrupt(void); + +/* CPU context access */ +void* cpu_getcontext (int _activecpu); +int cpu_is_saving_context(int _activecpu); + +/*************************************************************************** + * Get information for the currently active CPU + * cputype is a value from the CPU enum in driver.h + ***************************************************************************/ +/* Return number of address bits */ +unsigned cpu_address_bits(void); +/* Return address mask */ +unsigned cpu_address_mask(void); +/* Return address shift factor (TMS34010 bit addressing mode) */ +int cpu_address_shift(void); +/* Return endianess of the emulated CPU (CPU_IS_LE or CPU_IS_BE) */ +unsigned cpu_endianess(void); +/* Return opcode align unit (1 byte, 2 word, 4 dword) */ +unsigned cpu_align_unit(void); +/* Return maximum instruction length */ +unsigned cpu_max_inst_len(void); + +/* Return name of the active CPU */ +const char *cpu_name(void); +/* Return family name of the active CPU */ +const char *cpu_core_family(void); +/* Return core version of the active CPU */ +const char *cpu_core_version(void); +/* Return core filename of the active CPU */ +const char *cpu_core_file(void); +/* Return credits info for of the active CPU */ +const char *cpu_core_credits(void); +/* Return register layout definition for the active CPU */ +const char *cpu_reg_layout(void); +/* Return (debugger) window layout definition for the active CPU */ +const char *cpu_win_layout(void); + +/* Disassemble an instruction at PC into the given buffer */ +unsigned cpu_dasm(char *buffer, unsigned pc); +/* Return a string describing the currently set flag (status) bits of the active CPU */ +const char *cpu_flags(void); +/* Return a string with a register name and hex value for the active CPU */ +/* regnum is a value defined in the CPU cores header files */ +const char *cpu_dump_reg(int regnum); +/* Return a string describing the active CPUs current state */ +const char *cpu_dump_state(void); + +/*************************************************************************** + * Get information for a specific CPU type + * cputype is a value from the CPU enum in driver.h + ***************************************************************************/ +/* Return address shift factor */ +/* TMS320C10 -1: word addressing mode, TMS34010 3: bit addressing mode */ +int cputype_address_shift(int cputype); +/* Return number of address bits */ +unsigned cputype_address_bits(int cputype); +/* Return address mask */ +unsigned cputype_address_mask(int cputype); +/* Return endianess of the emulated CPU (CPU_IS_LE or CPU_IS_BE) */ +unsigned cputype_endianess(int cputype); +/* Return opcode align unit (1 byte, 2 word, 4 dword) */ +unsigned cputype_align_unit(int cputype); +/* Return maximum instruction length */ +unsigned cputype_max_inst_len(int cputype); + +/* Return name of the CPU */ +const char *cputype_name(int cputype); +/* Return family name of the CPU */ +const char *cputype_core_family(int cputype); +/* Return core version number of the CPU */ +const char *cputype_core_version(int cputype); +/* Return core filename of the CPU */ +const char *cputype_core_file(int cputype); +/* Return credits for the CPU core */ +const char *cputype_core_credits(int cputype); +/* Return register layout definition for the CPU core */ +const char *cputype_reg_layout(int cputype); +/* Return (debugger) window layout definition for the CPU core */ +const char *cputype_win_layout(int cputype); + +/*************************************************************************** + * Get (or set) information for a numbered CPU of the running machine + * cpunum is a value between 0 and cpu_gettotalcpu() - 1 + ***************************************************************************/ +/* Return number of address bits */ +unsigned cpunum_address_bits(int cputype); +/* Return address mask */ +unsigned cpunum_address_mask(int cputype); +/* Return endianess of the emulated CPU (CPU_LSB_FIRST or CPU_MSB_FIRST) */ +unsigned cpunum_endianess(int cputype); +/* Return opcode align unit (1 byte, 2 word, 4 dword) */ +unsigned cpunum_align_unit(int cputype); +/* Return maximum instruction length */ +unsigned cpunum_max_inst_len(int cputype); + +/* Get a register value for the specified CPU number of the running machine */ +unsigned cpunum_get_reg(int cpunum, int regnum); +/* Set a register value for the specified CPU number of the running machine */ +void cpunum_set_reg(int cpunum, int regnum, unsigned val); + +/* Return (debugger) register layout definition for the CPU core */ +const char *cpunum_reg_layout(int cpunum); +/* Return (debugger) window layout definition for the CPU core */ +const char *cpunum_win_layout(int cpunum); + +unsigned cpunum_dasm(int cpunum,char *buffer,unsigned pc); +/* Return a string describing the currently set flag (status) bits of the CPU */ +const char *cpunum_flags(int cpunum); +/* Return a string with a register name and value */ +/* regnum is a value defined in the CPU cores header files */ +const char *cpunum_dump_reg(int cpunum, int regnum); +/* Return a string describing the CPUs current state */ +const char *cpunum_dump_state(int cpunum); +/* Return a name for the specified cpu number */ +const char *cpunum_name(int cpunum); +/* Return a family name for the specified cpu number */ +const char *cpunum_core_family(int cpunum); +/* Return a version for the specified cpu number */ +const char *cpunum_core_version(int cpunum); +/* Return a the source filename for the specified cpu number */ +const char *cpunum_core_file(int cpunum); +/* Return a the credits for the specified cpu number */ +const char *cpunum_core_credits(int cpunum); + +/* Dump all of the running machines CPUs state to stderr */ +void cpu_dump_states(void); + +/* daisy-chain link */ +typedef struct { + void (*reset)(int); /* reset callback */ + int (*interrupt_entry)(int); /* entry callback */ + void (*interrupt_reti)(int); /* reti callback */ + int irq_param; /* callback paramater */ +} Z80_DaisyChain; + +#define Z80_MAXDAISY 4 /* maximum of daisy chan device */ + +#define Z80_INT_REQ 0x01 /* interrupt request mask */ +#define Z80_INT_IEO 0x02 /* interrupt disable mask(IEO) */ + +#define Z80_VECTOR(device,state) (((device)<<8)|(state)) + +#ifndef INLINE +#define INLINE inline +#endif + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +#define cpu_readmem16 memory_read +#define cpu_readport16 memory_readport +#define cpu_writeport16 memory_writeport +#define cpu_writemem16 memory_write +#define cpu_readop memory_readop +#define cpu_readop_arg memory_read +#define logerror(x, ...) +#define change_pc16(x) +#define CALL_MAME_DEBUG + +#define ADDRESS_SPACES 3 /* maximum number of address spaces */ +#define ADDRESS_SPACE_PROGRAM 0 /* program address space */ +#define ADDRESS_SPACE_DATA 1 /* data address space */ +#define ADDRESS_SPACE_IO 2 /* I/O address space */ + +enum +{ + /* internal flags (not for use by drivers!) */ + INTERNAL_CLEAR_LINE = 100 + CLEAR_LINE, + INTERNAL_ASSERT_LINE = 100 + ASSERT_LINE, + + /* input lines */ + MAX_INPUT_LINES = 32+3, + INPUT_LINE_IRQ0 = 0, + INPUT_LINE_IRQ1 = 1, + INPUT_LINE_IRQ2 = 2, + INPUT_LINE_IRQ3 = 3, + INPUT_LINE_IRQ4 = 4, + INPUT_LINE_IRQ5 = 5, + INPUT_LINE_IRQ6 = 6, + INPUT_LINE_IRQ7 = 7, + INPUT_LINE_IRQ8 = 8, + INPUT_LINE_IRQ9 = 9, + INPUT_LINE_NMI = MAX_INPUT_LINES - 3, + + /* special input lines that are implemented in the core */ + INPUT_LINE_RESET = MAX_INPUT_LINES - 2, + INPUT_LINE_HALT = MAX_INPUT_LINES - 1, + + /* output lines */ + MAX_OUTPUT_LINES = 32 +}; + +enum +{ + /* --- the following bits of info are returned as 64-bit signed integers --- */ + CPUINFO_INT_FIRST = 0x00000, + + CPUINFO_INT_CONTEXT_SIZE = CPUINFO_INT_FIRST, /* R/O: size of CPU context in bytes */ + CPUINFO_INT_INPUT_LINES, /* R/O: number of input lines */ + CPUINFO_INT_OUTPUT_LINES, /* R/O: number of output lines */ + CPUINFO_INT_DEFAULT_IRQ_VECTOR, /* R/O: default IRQ vector */ + CPUINFO_INT_ENDIANNESS, /* R/O: either CPU_IS_BE or CPU_IS_LE */ + CPUINFO_INT_CLOCK_DIVIDER, /* R/O: internal clock divider */ + CPUINFO_INT_MIN_INSTRUCTION_BYTES, /* R/O: minimum bytes per instruction */ + CPUINFO_INT_MAX_INSTRUCTION_BYTES, /* R/O: maximum bytes per instruction */ + CPUINFO_INT_MIN_CYCLES, /* R/O: minimum cycles for a single instruction */ + CPUINFO_INT_MAX_CYCLES, /* R/O: maximum cycles for a single instruction */ + + CPUINFO_INT_DATABUS_WIDTH, /* R/O: data bus size for each address space (8,16,32,64) */ + CPUINFO_INT_DATABUS_WIDTH_LAST = CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACES - 1, + CPUINFO_INT_ADDRBUS_WIDTH, /* R/O: address bus size for each address space (12-32) */ + CPUINFO_INT_ADDRBUS_WIDTH_LAST = CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACES - 1, + CPUINFO_INT_ADDRBUS_SHIFT, /* R/O: shift applied to addresses each address space (+3 means >>3, -1 means <<1) */ + CPUINFO_INT_ADDRBUS_SHIFT_LAST = CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACES - 1, + + CPUINFO_INT_SP, /* R/W: the current stack pointer value */ + CPUINFO_INT_PC, /* R/W: the current PC value */ + CPUINFO_INT_PREVIOUSPC, /* R/W: the previous PC value */ + CPUINFO_INT_INPUT_STATE, /* R/W: states for each input line */ + CPUINFO_INT_INPUT_STATE_LAST = CPUINFO_INT_INPUT_STATE + MAX_INPUT_LINES - 1, + CPUINFO_INT_OUTPUT_STATE, /* R/W: states for each output line */ + CPUINFO_INT_OUTPUT_STATE_LAST = CPUINFO_INT_OUTPUT_STATE + MAX_OUTPUT_LINES - 1, + CPUINFO_INT_REGISTER, /* R/W: values of up to MAX_REGs registers */ + CPUINFO_INT_REGISTER_LAST = CPUINFO_INT_REGISTER + MAX_REGS - 1, + + CPUINFO_INT_CPU_SPECIFIC = 0x08000, /* R/W: CPU-specific values start here */ + + /* --- the following bits of info are returned as pointers to data or functions --- */ + CPUINFO_PTR_FIRST = 0x10000, + + CPUINFO_PTR_SET_INFO = CPUINFO_PTR_FIRST, /* R/O: void (*set_info)(UINT32 state, INT64 data, void *ptr) */ + CPUINFO_PTR_GET_CONTEXT, /* R/O: void (*get_context)(void *buffer) */ + CPUINFO_PTR_SET_CONTEXT, /* R/O: void (*set_context)(void *buffer) */ + CPUINFO_PTR_INIT, /* R/O: void (*init)(void) */ + CPUINFO_PTR_RESET, /* R/O: void (*reset)(void *param) */ + CPUINFO_PTR_EXIT, /* R/O: void (*exit)(void) */ + CPUINFO_PTR_EXECUTE, /* R/O: int (*execute)(int cycles) */ + CPUINFO_PTR_BURN, /* R/O: void (*burn)(int cycles) */ + CPUINFO_PTR_DISASSEMBLE, /* R/O: void (*disassemble)(char *buffer, offs_t pc) */ + CPUINFO_PTR_IRQ_CALLBACK, /* R/W: int (*irqcallback)(int state) */ + CPUINFO_PTR_INSTRUCTION_COUNTER, /* R/O: int *icount */ + CPUINFO_PTR_REGISTER_LAYOUT, /* R/O: struct debug_register_layout *layout */ + CPUINFO_PTR_WINDOW_LAYOUT, /* R/O: struct debug_window_layout *layout */ + CPUINFO_PTR_INTERNAL_MEMORY_MAP, /* R/O: construct_map_t map */ + CPUINFO_PTR_INTERNAL_MEMORY_MAP_LAST = CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACES - 1, + CPUINFO_PTR_DEBUG_REGISTER_LIST, /* R/O: int *list: list of registers for NEW_DEBUGGER */ + + CPUINFO_PTR_CPU_SPECIFIC = 0x18000, /* R/W: CPU-specific values start here */ + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + CPUINFO_STR_FIRST = 0x20000, + + CPUINFO_STR_NAME = CPUINFO_STR_FIRST, /* R/O: name of the CPU */ + CPUINFO_STR_CORE_FAMILY, /* R/O: family of the CPU */ + CPUINFO_STR_CORE_VERSION, /* R/O: version of the CPU core */ + CPUINFO_STR_CORE_FILE, /* R/O: file containing the CPU core */ + CPUINFO_STR_CORE_CREDITS, /* R/O: credits for the CPU core */ + CPUINFO_STR_FLAGS, /* R/O: string representation of the main flags value */ + CPUINFO_STR_REGISTER, /* R/O: string representation of up to MAX_REGs registers */ + CPUINFO_STR_REGISTER_LAST = CPUINFO_STR_REGISTER + MAX_REGS - 1, + + CPUINFO_STR_CPU_SPECIFIC = 0x28000 /* R/W: CPU-specific values start here */ +}; + +#endif /* CPUINTRF_H */ diff --git a/plugins/ao/eng_psf/eng_psf.c b/plugins/ao/eng_psf/eng_psf.c new file mode 100644 index 00000000..86c1ac92 --- /dev/null +++ b/plugins/ao/eng_psf/eng_psf.c @@ -0,0 +1,469 @@ +/* + Audio Overload SDK - PSF file format engine + + Copyright (c) 2007 R. Belmont and Richard Bannister. + + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "ao.h" +#include "eng_protos.h" +#include "cpuintrf.h" +#include "psx.h" + +#include "peops/stdafx.h" +#include "peops/externals.h" +#include "peops/regs.h" +#include "peops/registers.h" +#include "peops/spu.h" + + +#include "corlett.h" + +#define DEBUG_LOADER (0) + +int psf_refresh = -1; // hack + +typedef struct { + corlett_t *c; + char psfby[256]; + mips_cpu_context *mips_cpu; + char *spu_pOutput; +} psf_synth_t; + +static uint32 initialPC, initialGP, initialSP; + +static void spu_update (unsigned char* pSound,long lBytes,void *data) +{ + psf_synth_t *s = data; + memcpy(s->spu_pOutput, pSound, lBytes); +} + +void *psf_start(const char *path, uint8 *buffer, uint32 length) +{ + psf_synth_t *s = malloc (sizeof (psf_synth_t)); + psf_refresh = -1; + + uint8 *file, *lib_decoded, *lib_raw_file, *alib_decoded; + uint32 offset, plength, PC, SP, GP, lengthMS, fadeMS; + uint64 file_len, lib_len, lib_raw_length, alib_len; + corlett_t *lib; + int i; + union cpuinfo mipsinfo; + +// printf("Length = %d\n", length); + + // Decode the current GSF + if (corlett_decode(buffer, length, &file, &file_len, &s->c) != AO_SUCCESS) + { + psf_stop (s); + return NULL; + } + +// printf("file_len %d reserve %d\n", file_len, c->res_size); + + // check for PSX EXE signature + if (strncmp((char *)file, "PS-X EXE", 8)) + { + psf_stop (s); + return NULL; + } + + #if DEBUG_LOADER + offset = file[0x18] | file[0x19]<<8 | file[0x1a]<<16 | file[0x1b]<<24; + printf("Text section start: %x\n", offset); + offset = file[0x1c] | file[0x1d]<<8 | file[0x1e]<<16 | file[0x1f]<<24; + printf("Text section size: %x\n", offset); + printf("Region: [%s]\n", &file[0x4c]); + printf("refresh: [%s]\n", c->inf_refresh); + #endif + + if (s->c->inf_refresh[0] == '5') + { + psf_refresh = 50; + } + if (s->c->inf_refresh[0] == '6') + { + psf_refresh = 60; + } + + PC = file[0x10] | file[0x11]<<8 | file[0x12]<<16 | file[0x13]<<24; + GP = file[0x14] | file[0x15]<<8 | file[0x16]<<16 | file[0x17]<<24; + SP = file[0x30] | file[0x31]<<8 | file[0x32]<<16 | file[0x33]<<24; + + #if DEBUG_LOADER + printf("Top level: PC %x GP %x SP %x\n", PC, GP, SP); + #endif + + s->mips_cpu = mips_alloc(); + // Get the library file, if any + if (s->c->lib[0] != 0) + { + uint64 tmp_length; + + #if DEBUG_LOADER + printf("Loading library: %s\n", c->lib); + #endif + if (ao_get_lib(s->c->lib, &lib_raw_file, &tmp_length) != AO_SUCCESS) + { + psf_stop (s); + return NULL; + } + lib_raw_length = tmp_length; + + if (corlett_decode(lib_raw_file, lib_raw_length, &lib_decoded, &lib_len, &lib) != AO_SUCCESS) + { + free(lib_raw_file); + psf_stop (s); + return NULL; + } + + // Free up raw file + free(lib_raw_file); + + if (strncmp((char *)lib_decoded, "PS-X EXE", 8)) + { + printf("Major error! PSF was OK, but referenced library is not!\n"); + free(lib); + psf_stop (s); + return NULL; + } + + #if DEBUG_LOADER + offset = lib_decoded[0x18] | lib_decoded[0x19]<<8 | lib_decoded[0x1a]<<16 | lib_decoded[0x1b]<<24; + printf("Text section start: %x\n", offset); + offset = lib_decoded[0x1c] | lib_decoded[0x1d]<<8 | lib_decoded[0x1e]<<16 | lib_decoded[0x1f]<<24; + printf("Text section size: %x\n", offset); + printf("Region: [%s]\n", &lib_decoded[0x4c]); + printf("refresh: [%s]\n", lib->inf_refresh); + #endif + + // if the original file had no refresh tag, give the lib a shot + if (psf_refresh == -1) + { + if (lib->inf_refresh[0] == '5') + { + psf_refresh = 50; + } + if (lib->inf_refresh[0] == '6') + { + psf_refresh = 60; + } + } + + PC = lib_decoded[0x10] | lib_decoded[0x11]<<8 | lib_decoded[0x12]<<16 | lib_decoded[0x13]<<24; + GP = lib_decoded[0x14] | lib_decoded[0x15]<<8 | lib_decoded[0x16]<<16 | lib_decoded[0x17]<<24; + SP = lib_decoded[0x30] | lib_decoded[0x31]<<8 | lib_decoded[0x32]<<16 | lib_decoded[0x33]<<24; + + #if DEBUG_LOADER + printf("Library: PC %x GP %x SP %x\n", PC, GP, SP); + #endif + + // now patch the file into RAM + offset = lib_decoded[0x18] | lib_decoded[0x19]<<8 | lib_decoded[0x1a]<<16 | lib_decoded[0x1b]<<24; + offset &= 0x3fffffff; // kill any MIPS cache segment indicators + plength = lib_decoded[0x1c] | lib_decoded[0x1d]<<8 | lib_decoded[0x1e]<<16 | lib_decoded[0x1f]<<24; + #if DEBUG_LOADER + printf("library offset: %x plength: %d\n", offset, plength); + #endif + memcpy(&s->mips_cpu->psx_ram[offset/4], lib_decoded+2048, plength); + + // Dispose the corlett structure for the lib - we don't use it + free(lib); + } + + // now patch the main file into RAM OVER the libraries (but not the aux lib) + offset = file[0x18] | file[0x19]<<8 | file[0x1a]<<16 | file[0x1b]<<24; + offset &= 0x3fffffff; // kill any MIPS cache segment indicators + plength = file[0x1c] | file[0x1d]<<8 | file[0x1e]<<16 | file[0x1f]<<24; + + // Philosoma has an illegal "plength". *sigh* + if (plength > (file_len-2048)) + { + plength = file_len-2048; + } + memcpy(&s->mips_cpu->psx_ram[offset/4], file+2048, plength); + + // load any auxiliary libraries now + for (i = 0; i < 8; i++) + { + if (s->c->libaux[i][0] != 0) + { + uint64 tmp_length; + + #if DEBUG_LOADER + printf("Loading aux library: %s\n", c->libaux[i]); + #endif + + if (ao_get_lib(s->c->libaux[i], &lib_raw_file, &tmp_length) != AO_SUCCESS) + { + psf_stop (s); + return NULL; + } + lib_raw_length = tmp_length; + + if (corlett_decode(lib_raw_file, lib_raw_length, &alib_decoded, &alib_len, &lib) != AO_SUCCESS) + { + free(lib_raw_file); + psf_stop (s); + return NULL; + } + + // Free up raw file + free(lib_raw_file); + + if (strncmp((char *)alib_decoded, "PS-X EXE", 8)) + { + printf("Major error! PSF was OK, but referenced library is not!\n"); + free(lib); + psf_stop (s); + return NULL; + } + + #if DEBUG_LOADER + offset = alib_decoded[0x18] | alib_decoded[0x19]<<8 | alib_decoded[0x1a]<<16 | alib_decoded[0x1b]<<24; + printf("Text section start: %x\n", offset); + offset = alib_decoded[0x1c] | alib_decoded[0x1d]<<8 | alib_decoded[0x1e]<<16 | alib_decoded[0x1f]<<24; + printf("Text section size: %x\n", offset); + printf("Region: [%s]\n", &alib_decoded[0x4c]); + #endif + + // now patch the file into RAM + offset = alib_decoded[0x18] | alib_decoded[0x19]<<8 | alib_decoded[0x1a]<<16 | alib_decoded[0x1b]<<24; + offset &= 0x3fffffff; // kill any MIPS cache segment indicators + plength = alib_decoded[0x1c] | alib_decoded[0x1d]<<8 | alib_decoded[0x1e]<<16 | alib_decoded[0x1f]<<24; + memcpy(&s->mips_cpu->psx_ram[offset/4], alib_decoded+2048, plength); + + // Dispose the corlett structure for the lib - we don't use it + free(lib); + } + } + + free(file); +// free(lib_decoded); + + // Finally, set psfby tag + strcpy(s->psfby, "n/a"); + if (s->c) + { + int i; + for (i = 0; i < MAX_UNKNOWN_TAGS; i++) + { + if (!strcasecmp(s->c->tag_name[i], "psfby")) + strcpy(s->psfby, s->c->tag_data[i]); + } + } + + mips_init (s->mips_cpu); + mips_reset(s->mips_cpu, NULL); +// // clear PSX work RAM before we start scribbling in it +// memset(s->mips_cpu->psx_ram, 0, 2*1024*1024); + + + // set the initial PC, SP, GP + #if DEBUG_LOADER + printf("Initial PC %x, GP %x, SP %x\n", PC, GP, SP); + printf("Refresh = %d\n", psf_refresh); + #endif + mipsinfo.i = PC; + mips_set_info(s->mips_cpu, CPUINFO_INT_PC, &mipsinfo); + + // set some reasonable default for the stack + if (SP == 0) + { + SP = 0x801fff00; + } + + mipsinfo.i = SP; + mips_set_info(s->mips_cpu, CPUINFO_INT_REGISTER + MIPS_R29, &mipsinfo); + mips_set_info(s->mips_cpu, CPUINFO_INT_REGISTER + MIPS_R30, &mipsinfo); + + mipsinfo.i = GP; + mips_set_info(s->mips_cpu, CPUINFO_INT_REGISTER + MIPS_R28, &mipsinfo); + + #if DEBUG_LOADER && 1 + { + FILE *f; + + f = fopen("psxram.bin", "wb"); + fwrite(psx_ram, 2*1024*1024, 1, f); + fclose(f); + } + #endif + + psx_hw_init(s->mips_cpu); + SPUinit(s->mips_cpu, spu_update, s); + SPUopen(s->mips_cpu); + + lengthMS = psfTimeToMS(s->c->inf_length); + fadeMS = psfTimeToMS(s->c->inf_fade); + + #if DEBUG_LOADER + printf("length %d fade %d\n", lengthMS, fadeMS); + #endif + + if (lengthMS == 0) + { + lengthMS = ~0; + } + + setlength(s->mips_cpu->spu, lengthMS, fadeMS); + + // patch illegal Chocobo Dungeon 2 code - CaitSith2 put a jump in the delay slot from a BNE + // and rely on Highly Experimental's buggy-ass CPU to rescue them. Verified on real hardware + // that the initial code is wrong. + if (s->c->inf_game) + { + if (!strcmp(s->c->inf_game, "Chocobo Dungeon 2")) + { + if (s->mips_cpu->psx_ram[0xbc090/4] == LE32(0x0802f040)) + { + s->mips_cpu->psx_ram[0xbc090/4] = LE32(0); + s->mips_cpu->psx_ram[0xbc094/4] = LE32(0x0802f040); + s->mips_cpu->psx_ram[0xbc098/4] = LE32(0); + } + } + } + +// psx_ram[0x118b8/4] = LE32(0); // crash 2 hack + + // backup the initial state for restart + memcpy(s->mips_cpu->initial_ram, s->mips_cpu->psx_ram, 2*1024*1024); + memcpy(s->mips_cpu->initial_scratch, s->mips_cpu->psx_scratch, 0x400); + initialPC = PC; + initialGP = GP; + initialSP = SP; + + mips_execute(s->mips_cpu, 5000); + + return s; +} + +int32 psf_gen(void *handle, int16 *buffer, uint32 samples) +{ + psf_synth_t *s = handle; + int i; + + for (i = 0; i < samples; i++) + { + psx_hw_slice(s->mips_cpu); + SPUasync(s->mips_cpu, 384); + } + + s->spu_pOutput = (char *)buffer; + SPU_flushboot(s->mips_cpu); + + psx_hw_frame(s->mips_cpu); + + return AO_SUCCESS; +} + +int32 psf_stop(void *handle) +{ + psf_synth_t *s = handle; + SPUclose(s->mips_cpu); + free(s->c); + free (s); + + return AO_SUCCESS; +} + +int32 psf_command(void *handle, int32 command, int32 parameter) +{ + psf_synth_t *s = handle; + union cpuinfo mipsinfo; + uint32 lengthMS, fadeMS; + + switch (command) + { + case COMMAND_RESTART: + SPUclose(s->mips_cpu); + + memcpy(s->mips_cpu->psx_ram, s->mips_cpu->initial_ram, 2*1024*1024); + memcpy(s->mips_cpu->psx_scratch, s->mips_cpu->initial_scratch, 0x400); + +// mips_init(); + mips_reset(s->mips_cpu, NULL); + psx_hw_init(s->mips_cpu); + SPUinit(s->mips_cpu, spu_update, s); + SPUopen(s->mips_cpu); + + lengthMS = psfTimeToMS(s->c->inf_length); + fadeMS = psfTimeToMS(s->c->inf_fade); + + if (lengthMS == 0) + { + lengthMS = ~0; + } + setlength(s->mips_cpu->spu, lengthMS, fadeMS); + + mipsinfo.i = initialPC; + mips_set_info(s->mips_cpu, CPUINFO_INT_PC, &mipsinfo); + mipsinfo.i = initialSP; + mips_set_info(s->mips_cpu, CPUINFO_INT_REGISTER + MIPS_R29, &mipsinfo); + mips_set_info(s->mips_cpu, CPUINFO_INT_REGISTER + MIPS_R30, &mipsinfo); + mipsinfo.i = initialGP; + mips_set_info(s->mips_cpu, CPUINFO_INT_REGISTER + MIPS_R28, &mipsinfo); + + mips_execute(s->mips_cpu, 5000); + + return AO_SUCCESS; + + } + return AO_FAIL; +} + +int32 psf_fill_info(void *handle, ao_display_info *info) +{ + psf_synth_t *s = handle; + if (s->c == NULL) + return AO_FAIL; + + strcpy(info->title[1], "Name: "); + sprintf(info->info[1], "%s", s->c->inf_title); + + strcpy(info->title[2], "Game: "); + sprintf(info->info[2], "%s", s->c->inf_game); + + strcpy(info->title[3], "Artist: "); + sprintf(info->info[3], "%s", s->c->inf_artist); + + strcpy(info->title[4], "Copyright: "); + sprintf(info->info[4], "%s", s->c->inf_copy); + + strcpy(info->title[5], "Year: "); + sprintf(info->info[5], "%s", s->c->inf_year); + + strcpy(info->title[6], "Length: "); + sprintf(info->info[6], "%s", s->c->inf_length); + + strcpy(info->title[7], "Fade: "); + sprintf(info->info[7], "%s", s->c->inf_fade); + + strcpy(info->title[8], "Ripper: "); + sprintf(info->info[8], "%s", s->psfby); + + return AO_SUCCESS; +} diff --git a/plugins/ao/eng_psf/eng_psf2.c b/plugins/ao/eng_psf/eng_psf2.c new file mode 100644 index 00000000..854e9012 --- /dev/null +++ b/plugins/ao/eng_psf/eng_psf2.c @@ -0,0 +1,722 @@ +/* + Audio Overload SDK - PSF2 file format engine + + Copyright (c) 2007-2008 R. Belmont and Richard Bannister. + + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +// +// Audio Overload +// Emulated music player +// +// (C) 2000-2008 Richard F. Bannister +// + +// +// eng_psf2.c +// +// References: +// psf_format.txt v1.6 by Neill Corlett (s->filesystem and decompression info) +// Intel ELF format specs ELF.PS (general ELF parsing info) +// http://ps2dev.org/kb.x?T=457 (IRX relocation and inter-module call info) +// http://ps2dev.org/ (the whole site - lots of IOP info) +// spu2regs.txt (comes with SexyPSF source: IOP hardware info) +// 64-bit ELF Object File Specification: http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf (MIPS ELF relocation types) + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <zlib.h> + +#include "ao.h" +#include "eng_protos.h" +#include "cpuintrf.h" +#include "psx.h" + +#include "peops2/stdafx.h" +#include "peops2/externals.h" +#include "peops2/regs.h" +#include "peops2/registers.h" +#include "peops2/spu.h" + +#include "corlett.h" + +#define DEBUG_LOADER (0) +#define MAX_FS (32) // maximum # of s->filesystems (libs and subdirectories) + +// ELF relocation helpers +#define ELF32_R_SYM(val) ((val) >> 8) +#define ELF32_R_TYPE(val) ((val) & 0xff) + +// main RAM +static uint32 loadAddr, lengthMS, fadeMS; +static uint8 *filesys[MAX_FS]; +static uint32 fssize[MAX_FS]; +static int num_fs; + +typedef struct { + corlett_t *c; + char psfby[256]; + uint32 initialPC, initialSP; + + uint8 *lib_raw_file; + mips_cpu_context *mips_cpu; + char *spu_pOutput; +} psf2_synth_t; + +void ps2_update(unsigned char *pSound, long lBytes, void *data) +{ + psf2_synth_t *s = data; + memcpy(s->spu_pOutput, pSound, lBytes); // (for direct 44.1kHz output) +} + +#if 0 +static uint32 secname(uint8 *start, uint32 strndx, uint32 shoff, uint32 shentsize, uint32 name) +{ + uint32 offset, shent; + + // get string table section + shent = shoff + (shentsize * strndx); + + // find the offset to the section + offset = start[shent+16] | start[shent+17]<<8 | start[shent+18]<<16 | start[shent+19]<<24; + + offset += name; + + return offset; +} +#endif + +static void do_iopmod(uint8 *start, uint32 offset) +{ + uint32 nameoffs, saddr, heap, tsize, dsize, bsize, vers2; + + nameoffs = start[offset] | start[offset+1]<<8 | start[offset+2]<<16 | start[offset+3]<<24; + + saddr = start[offset+4] | start[offset+5]<<8 | start[offset+6]<<16 | start[offset+7]<<24; + heap = start[offset+8] | start[offset+9]<<8 | start[offset+10]<<16 | start[offset+11]<<24; + tsize = start[offset+12] | start[offset+13]<<8 | start[offset+14]<<16 | start[offset+15]<<24; + dsize = start[offset+16] | start[offset+17]<<8 | start[offset+18]<<16 | start[offset+19]<<24; + bsize = start[offset+20] | start[offset+21]<<8 | start[offset+22]<<16 | start[offset+23]<<24; + vers2 = start[offset+24] | start[offset+25]<<8; + +// printf("nameoffs %08x saddr %08x heap %08x tsize %08x dsize %08x bsize %08x\n", nameoffs, saddr, heap, tsize, dsize, bsize); + #if DEBUG_LOADER + printf("vers: %04x name [%s]\n", vers2, &start[offset+26]); + #endif +} + +uint32 psf2_load_elf(mips_cpu_context *cpu, uint8 *start, uint32 len) +{ + uint32 entry, phoff, shoff, phentsize, shentsize, phnum, shnum, shstrndx; + uint32 name, type, flags, addr, offset, size, shent; + uint32 totallen; + int i, rec; +// FILE *f; + + if (loadAddr & 3) + { + loadAddr &= ~3; + loadAddr += 4; + } + + #if DEBUG_LOADER + printf("psf2_load_elf: starting at %08x\n", loadAddr | 0x80000000); + #endif + + if ((start[0] != 0x7f) || (start[1] != 'E') || (start[2] != 'L') || (start[3] != 'F')) + { + printf("Not an ELF file\n"); + return 0xffffffff; + } + + entry = start[24] | start[25]<<8 | start[26]<<16 | start[27]<<24; // 0x18 + phoff = start[28] | start[29]<<8 | start[30]<<16 | start[31]<<24; // 0x1c + shoff = start[32] | start[33]<<8 | start[34]<<16 | start[35]<<24; // 0x20 + +// printf("Entry: %08x phoff %08x shoff %08x\n", entry, phoff, shoff); + + phentsize = start[42] | start[43]<<8; // 0x2a + phnum = start[44] | start[45]<<8; // 0x2c + shentsize = start[46] | start[47]<<8; // 0x2e + shnum = start[48] | start[49]<<8; // 0x30 + shstrndx = start[50] | start[51]<<8; // 0x32 + +// printf("phentsize %08x phnum %d shentsize %08x shnum %d shstrndx %d\n", phentsize, phnum, shentsize, shnum, shstrndx); + + // process ELF sections + shent = shoff; + totallen = 0; + for (i = 0; i < shnum; i++) + { + name = start[shent] | start[shent+1]<<8 | start[shent+2]<<16 | start[shent+3]<<24; + type = start[shent+4] | start[shent+5]<<8 | start[shent+6]<<16 | start[shent+7]<<24; + flags = start[shent+8] | start[shent+9]<<8 | start[shent+10]<<16 | start[shent+11]<<24; + addr = start[shent+12] | start[shent+13]<<8 | start[shent+14]<<16 | start[shent+15]<<24; + offset = start[shent+16] | start[shent+17]<<8 | start[shent+18]<<16 | start[shent+19]<<24; + size = start[shent+20] | start[shent+21]<<8 | start[shent+22]<<16 | start[shent+23]<<24; + +// printf("Section %02d: name %08x [%s] type %08x flags %08x addr %08x offset %08x size %08x\n", i, name, &start[secname(start, shstrndx, shoff, shentsize, name)], type, flags, addr, offset, size); + + switch (type) + { + case 0: // section table header - do nothing + break; + + case 1: // PROGBITS: copy data to destination + memcpy(&cpu->psx_ram[(loadAddr + addr)/4], &start[offset], size); + totallen += size; + break; + + case 2: // SYMTAB: ignore + break; + + case 3: // STRTAB: ignore + break; + + case 8: // NOBITS: BSS region, zero out destination + memset(&cpu->psx_ram[(loadAddr + addr)/4], 0, size); + totallen += size; + break; + + case 9: // REL: short relocation data + for (rec = 0; rec < (size/8); rec++) + { + uint32 offs, info, target, temp, val, vallo; + static uint32 hi16offs = 0, hi16target = 0; + + offs = start[offset+(rec*8)] | start[offset+1+(rec*8)]<<8 | start[offset+2+(rec*8)]<<16 | start[offset+3+(rec*8)]<<24; + info = start[offset+4+(rec*8)] | start[offset+5+(rec*8)]<<8 | start[offset+6+(rec*8)]<<16 | start[offset+7+(rec*8)]<<24; + target = LE32(cpu->psx_ram[(loadAddr+offs)/4]); + +// printf("[%04d] offs %08x type %02x info %08x => %08x\n", rec, offs, ELF32_R_TYPE(info), ELF32_R_SYM(info), target); + + switch (ELF32_R_TYPE(info)) + { + case 2: // R_MIPS_32 + target += loadAddr; +// target |= 0x80000000; + break; + + case 4: // R_MIPS_26 + temp = (target & 0x03ffffff); + target &= 0xfc000000; + temp += (loadAddr>>2); + target |= temp; + break; + + case 5: // R_MIPS_HI16 + hi16offs = offs; + hi16target = target; + break; + + case 6: // R_MIPS_LO16 + vallo = ((target & 0xffff) ^ 0x8000) - 0x8000; + + val = ((hi16target & 0xffff) << 16) + vallo; + val += loadAddr; +// val |= 0x80000000; + + /* Account for the sign extension that will happen in the low bits. */ + val = ((val >> 16) + ((val & 0x8000) != 0)) & 0xffff; + + hi16target = (hi16target & ~0xffff) | val; + + /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */ + val = loadAddr + vallo; + target = (target & ~0xffff) | (val & 0xffff); + + cpu->psx_ram[(loadAddr+hi16offs)/4] = LE32(hi16target); + break; + + default: + printf("FATAL: Unknown MIPS ELF relocation!\n"); + return 0xffffffff; + break; + } + + cpu->psx_ram[(loadAddr+offs)/4] = LE32(target); + } + break; + + case 0x70000080: // .iopmod + do_iopmod(start, offset); + break; + + default: + #if DEBUG_LOADER + printf("Unhandled ELF section type %d\n", type); + #endif + break; + } + + shent += shentsize; + } + + entry += loadAddr; + entry |= 0x80000000; + loadAddr += totallen; + + #if DEBUG_LOADER + printf("psf2_load_elf: entry PC %08x\n", entry); + #endif + return entry; +} + +static uint32 load_file_ex(uint8 *top, uint8 *start, uint32 len, char *file, uint8 *buf, uint32 buflen) +{ + int32 numfiles, i, j; + uint8 *cptr; + uint32 offs, uncomp, bsize, cofs, uofs; + uint32 X; + uLongf dlength; + int uerr; + char matchname[512], *remainder; + + // strip out to only the directory name + i = 0; + while ((file[i] != '/') && (file[i] != '\\') && (file[i] != '\0')) + { + matchname[i] = file[i]; + i++; + } + matchname[i] = '\0'; + remainder = &file[i+1]; + + cptr = start + 4; + + numfiles = start[0] | start[1]<<8 | start[2]<<16 | start[3]<<24; + + for (i = 0; i < numfiles; i++) + { + offs = cptr[36] | cptr[37]<<8 | cptr[38]<<16 | cptr[39]<<24; + uncomp = cptr[40] | cptr[41]<<8 | cptr[42]<<16 | cptr[43]<<24; + bsize = cptr[44] | cptr[45]<<8 | cptr[46]<<16 | cptr[47]<<24; + + #if DEBUG_LOADER + printf("[%s vs %s]: ofs %08x uncomp %08x bsize %08x\n", cptr, matchname, offs, uncomp, bsize); + #endif + + if (!strcasecmp((char *)cptr, matchname)) + { + if ((uncomp == 0) && (bsize == 0)) + { + #if DEBUG_LOADER + printf("Drilling into subdirectory [%s] with [%s] at offset %x\n", matchname, remainder, offs); + #endif + return load_file_ex(top, &top[offs], len-offs, remainder, buf, buflen); + } + + X = (uncomp + bsize - 1) / bsize; + + cofs = offs + (X*4); + uofs = 0; + for (j = 0; j < X; j++) + { + uint32 usize; + + usize = top[offs+(j*4)] | top[offs+1+(j*4)]<<8 | top[offs+2+(j*4)]<<16 | top[offs+3+(j*4)]<<24; + + dlength = buflen - uofs; + + uerr = uncompress(&buf[uofs], &dlength, &top[cofs], usize); + if (uerr != Z_OK) + { + printf("Decompress fail: %x %d!\n", (unsigned int)dlength, uerr); + return 0xffffffff; + } + + cofs += usize; + uofs += dlength; + } + + return uncomp; + } + else + { + cptr += 48; + } + } + + return 0xffffffff; +} + +static uint32 load_file(int fs, char *file, uint8 *buf, uint32 buflen) +{ + return load_file_ex(filesys[fs], filesys[fs], fssize[fs], file, buf, buflen); +} + +#if 0 +static dump_files(int fs, uint8 *buf, uint32 buflen) +{ + int32 numfiles, i, j; + uint8 *cptr; + uint32 offs, uncomp, bsize, cofs, uofs; + uint32 X; + uLongf dlength; + int uerr; + uint8 *start; + uint32 len; + FILE *f; + char tfn[128]; + + printf("Dumping FS %d\n", fs); + + start = s->filesys[fs]; + len = s->fssize[fs]; + + cptr = start + 4; + + numfiles = start[0] | start[1]<<8 | start[2]<<16 | start[3]<<24; + + for (i = 0; i < numfiles; i++) + { + offs = cptr[36] | cptr[37]<<8 | cptr[38]<<16 | cptr[39]<<24; + uncomp = cptr[40] | cptr[41]<<8 | cptr[42]<<16 | cptr[43]<<24; + bsize = cptr[44] | cptr[45]<<8 | cptr[46]<<16 | cptr[47]<<24; + + if (bsize > 0) + { + X = (uncomp + bsize - 1) / bsize; + + printf("[dump %s]: ofs %08x uncomp %08x bsize %08x\n", cptr, offs, uncomp, bsize); + + cofs = offs + (X*4); + uofs = 0; + for (j = 0; j < X; j++) + { + uint32 usize; + + usize = start[offs+(j*4)] | start[offs+1+(j*4)]<<8 | start[offs+2+(j*4)]<<16 | start[offs+3+(j*4)]<<24; + + dlength = buflen - uofs; + + uerr = uncompress(&buf[uofs], &dlength, &start[cofs], usize); + if (uerr != Z_OK) + { + printf("Decompress fail: %x %d!\n", dlength, uerr); + return 0xffffffff; + } + + cofs += usize; + uofs += dlength; + } + + sprintf(tfn, "iopfiles/%s", cptr); + f = fopen(tfn, "wb"); + fwrite(buf, uncomp, 1, f); + fclose(f); + } + else + { + printf("[subdir %s]: ofs %08x uncomp %08x bsize %08x\n", cptr, offs, uncomp, bsize); + } + + cptr += 48; + } + + return 0xffffffff; +} +#endif + +// find a file on our filesystems +uint32 psf2_load_file(mips_cpu_context *cpu, char *file, uint8 *buf, uint32 buflen) +{ + int i; + uint32 flen; + + for (i = 0; i < num_fs; i++) + { + flen = load_file(i, file, buf, buflen); + if (flen != 0xffffffff) + { + return flen; + } + } + + return 0xffffffff; +} + +void *psf2_start(const char *path, uint8 *buffer, uint32 length) +{ + psf2_synth_t *s = malloc (sizeof (psf2_synth_t)); + + uint8 *file, *lib_decoded; + uint32 irx_len; + uint64 file_len, lib_raw_length, lib_len; + uint8 *buf; + union cpuinfo mipsinfo; + corlett_t *lib; + + loadAddr = 0x23f00; // this value makes allocations work out similarly to how they would + // in Highly Experimental (as per Shadow Hearts' hard-coded assumptions) + + // Decode the current PSF2 + if (corlett_decode(buffer, length, &file, &file_len, &s->c) != AO_SUCCESS) + { + free (s); + return NULL; + } + + if (file_len > 0) printf("ERROR: PSF2 can't have a program section! ps %08x\n", (unsigned int)file_len); + + #if DEBUG_LOADER + printf("FS section: size %x\n", s->c->res_size); + #endif + + num_fs = 1; + filesys[0] = (uint8 *)s->c->res_section; + fssize[0] = s->c->res_size; + + // Get the library file, if any + if (s->c->lib[0] != 0) + { + uint64 tmp_length; + + #if DEBUG_LOADER + printf("Loading library: %s\n", s->c->lib); + #endif + if (ao_get_lib(s->c->lib, &s->lib_raw_file, &tmp_length) != AO_SUCCESS) + { + free (s); + return NULL; + } + lib_raw_length = tmp_length; + + if (corlett_decode(s->lib_raw_file, lib_raw_length, &lib_decoded, &lib_len, &lib) != AO_SUCCESS) + { + free(s->lib_raw_file); + free (s); + return NULL; + } + + #if DEBUG_LOADER + printf("Lib FS section: size %x bytes\n", lib->res_size); + #endif + + num_fs++; + filesys[1] = (uint8 *)lib->res_section; + fssize[1] = lib->res_size; + } + + // dump all files + #if 0 + buf = (uint8 *)malloc(16*1024*1024); + dump_files(0, buf, 16*1024*1024); + if (s->c->lib[0] != 0) + dump_files(1, buf, 16*1024*1024); + free(buf); + #endif + + s->mips_cpu = mips_alloc (); + mips_init(s->mips_cpu); + mips_reset(s->mips_cpu, NULL); + + // load psf2.irx, which kicks everything off + buf = (uint8 *)malloc(512*1024); + irx_len = psf2_load_file(s->mips_cpu, "psf2.irx", buf, 512*1024); + + if (irx_len != 0xffffffff) + { + s->initialPC = psf2_load_elf(s->mips_cpu, buf, irx_len); + s->initialSP = 0x801ffff0; + } + free(buf); + + if (s->initialPC == 0xffffffff) + { + free (s); + return NULL; + } + + lengthMS = psfTimeToMS(s->c->inf_length); + fadeMS = psfTimeToMS(s->c->inf_fade); + if (lengthMS == 0) + { + lengthMS = ~0; + } + + mipsinfo.i = s->initialPC; + mips_set_info(s->mips_cpu, CPUINFO_INT_PC, &mipsinfo); + + mipsinfo.i = s->initialSP; + mips_set_info(s->mips_cpu, CPUINFO_INT_REGISTER + MIPS_R29, &mipsinfo); + mips_set_info(s->mips_cpu, CPUINFO_INT_REGISTER + MIPS_R30, &mipsinfo); + + // set RA + mipsinfo.i = 0x80000000; + mips_set_info(s->mips_cpu, CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo); + + // set A0 & A1 to point to "aofile:/" + mipsinfo.i = 2; // argc + mips_set_info(s->mips_cpu, CPUINFO_INT_REGISTER + MIPS_R4, &mipsinfo); + + mipsinfo.i = 0x80000004; // argv + mips_set_info(s->mips_cpu, CPUINFO_INT_REGISTER + MIPS_R5, &mipsinfo); + s->mips_cpu->psx_ram[1] = LE32(0x80000008); + + buf = (uint8 *)(&s->mips_cpu->psx_ram[2]); + strcpy((char *)buf, "aofile:/"); + + s->mips_cpu->psx_ram[0] = LE32(FUNCT_HLECALL); + + // back up initial RAM image to quickly restart songs + memcpy(s->mips_cpu->initial_ram, s->mips_cpu->psx_ram, 2*1024*1024); + + psx_hw_init(s->mips_cpu); + SPU2init(s->mips_cpu, ps2_update, s); + SPU2open(s->mips_cpu, NULL); + setlength2(s->mips_cpu->spu2, lengthMS, fadeMS); + + return s; +} + +int32 psf2_gen(void *handle, int16 *buffer, uint32 samples) +{ + int i; + psf2_synth_t *s = handle; + +// memset (buffer, 0, samples * 4); +// return AO_SUCCESS; +// + s->spu_pOutput = (char *)buffer; + + for (i = 0; i < samples; i++) + { + SPU2async(s->mips_cpu, 1); + ps2_hw_slice(s->mips_cpu); + } + + ps2_hw_frame(s->mips_cpu); + + return AO_SUCCESS; +} + +int32 psf2_stop(void *handle) +{ + psf2_synth_t *s = handle; + SPU2close(s->mips_cpu); + if (s->c->lib[0] != 0) + { + free(s->lib_raw_file); + } + free(s->c); + free (s); + + return AO_SUCCESS; +} + +int32 psf2_command(void *handle, int32 command, int32 parameter) +{ + psf2_synth_t *s = handle; + union cpuinfo mipsinfo; + uint32 lengthMS, fadeMS; + + switch (command) + { + case COMMAND_RESTART: + SPU2close(s->mips_cpu); + + memcpy(s->mips_cpu->psx_ram, s->mips_cpu->initial_ram, 2*1024*1024); + + mips_init(s->mips_cpu); + mips_reset(s->mips_cpu, NULL); + psx_hw_init(s->mips_cpu); + SPU2init(s->mips_cpu, ps2_update, s); + SPU2open(s->mips_cpu, NULL); + + mipsinfo.i = s->initialPC; + mips_set_info(s->mips_cpu, CPUINFO_INT_PC, &mipsinfo); + + mipsinfo.i = s->initialSP; + mips_set_info(s->mips_cpu, CPUINFO_INT_REGISTER + MIPS_R29, &mipsinfo); + mips_set_info(s->mips_cpu, CPUINFO_INT_REGISTER + MIPS_R30, &mipsinfo); + + // set RA + mipsinfo.i = 0x80000000; + mips_set_info(s->mips_cpu, CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo); + + // set A0 & A1 to point to "aofile:/" + mipsinfo.i = 2; // argc + mips_set_info(s->mips_cpu, CPUINFO_INT_REGISTER + MIPS_R4, &mipsinfo); + + mipsinfo.i = 0x80000004; // argv + mips_set_info(s->mips_cpu, CPUINFO_INT_REGISTER + MIPS_R5, &mipsinfo); + + psx_hw_init(s->mips_cpu); + + lengthMS = psfTimeToMS(s->c->inf_length); + fadeMS = psfTimeToMS(s->c->inf_fade); + if (lengthMS == 0) + { + lengthMS = ~0; + } + setlength2(s->mips_cpu->spu2, lengthMS, fadeMS); + + return AO_SUCCESS; + + } + return AO_FAIL; +} + +int32 psf2_fill_info(void *handle, ao_display_info *info) +{ + psf2_synth_t *s = handle; + if (s->c == NULL) + return AO_FAIL; + + strcpy(info->title[1], "Name: "); + sprintf(info->info[1], "%s", s->c->inf_title); + + strcpy(info->title[2], "Game: "); + sprintf(info->info[2], "%s", s->c->inf_game); + + strcpy(info->title[3], "Artist: "); + sprintf(info->info[3], "%s", s->c->inf_artist); + + strcpy(info->title[4], "Copyright: "); + sprintf(info->info[4], "%s", s->c->inf_copy); + + strcpy(info->title[5], "Year: "); + sprintf(info->info[5], "%s", s->c->inf_year); + + strcpy(info->title[6], "Length: "); + sprintf(info->info[6], "%s", s->c->inf_length); + + strcpy(info->title[7], "Fade: "); + sprintf(info->info[7], "%s", s->c->inf_fade); + + strcpy(info->title[8], "Ripper: "); + sprintf(info->info[8], "%s", s->psfby); + + return AO_SUCCESS; +} + +uint32 psf2_get_loadaddr(void) +{ + return loadAddr; +} + +void psf2_set_loadaddr(uint32 new) +{ + loadAddr = new; +} diff --git a/plugins/ao/eng_psf/eng_spu.c b/plugins/ao/eng_psf/eng_spu.c new file mode 100644 index 00000000..dbda70ac --- /dev/null +++ b/plugins/ao/eng_psf/eng_spu.c @@ -0,0 +1,341 @@ +/* + Audio Overload SDK - SPU file format engine + + Copyright (c) 2007 R. Belmont and Richard Bannister. + + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +// +// eng_spu.c +// +// Note: support for old-format files is not tested and may not work. All the rips I could find +// are in the newer format. Also, CDDA and XA commands do not work - I've not found a rip using them. +// + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "ao.h" +#include "eng_protos.h" +#include "cpuintrf.h" +#include "psx.h" +#include "peops/externals.h" +#include "peops/spu.h" +#include "peops/regs.h" + +typedef struct { + uint8 *start_of_file, *song_ptr; + uint32 cur_tick, cur_event, num_events, next_tick, end_tick; + int old_fmt; + char name[128], song[128], company[128]; + char *spu_pOutput; + mips_cpu_context *mips_cpu; +} spu_synth_t; + + +static void spu_update (unsigned char* pSound,long lBytes,void *data) +{ + spu_synth_t *s = data; + memcpy(s->spu_pOutput, pSound, lBytes); +} + + +void *spu_start(const char *path, uint8 *buffer, uint32 length) +{ + spu_synth_t *s = malloc (sizeof (spu_synth_t)); + memset (s, 0, sizeof (spu_synth_t)); + + int i; + uint16 reg; + + if (strncmp((char *)buffer, "SPU", 3)) + { + spu_stop (s); + return NULL; + } + + s->start_of_file = buffer; + + s->mips_cpu = mips_alloc (); + SPUinit(s->mips_cpu, spu_update, s); + SPUopen(s->mips_cpu); + setlength(s->mips_cpu->spu, ~0, 0); + + // upload the SPU RAM image + SPUinjectRAMImage(s->mips_cpu, (unsigned short *)&buffer[0]); + + // apply the register image + for (i = 0; i < 512; i += 2) + { + reg = buffer[0x80000+i] | buffer[0x80000+i+1]<<8; + + SPUwriteRegister(s->mips_cpu, (i/2)+0x1f801c00, reg); + } + + s->old_fmt = 1; + + if ((buffer[0x80200] != 0x44) || (buffer[0x80201] != 0xac) || (buffer[0x80202] != 0x00) || (buffer[0x80203] != 0x00)) + { + s->old_fmt = 0; + } + + if (s->old_fmt) + { + s->num_events = buffer[0x80204] | buffer[0x80205]<<8 | buffer[0x80206]<<16 | buffer[0x80207]<<24; + + if (((s->num_events * 12) + 0x80208) > length) + { + s->old_fmt = 0; + } + else + { + s->cur_tick = 0; + } + } + + if (!s->old_fmt) + { + s->end_tick = buffer[0x80200] | buffer[0x80201]<<8 | buffer[0x80202]<<16 | buffer[0x80203]<<24; + s->cur_tick = buffer[0x80204] | buffer[0x80205]<<8 | buffer[0x80206]<<16 | buffer[0x80207]<<24; + s->next_tick = s->cur_tick; + } + + s->song_ptr = &buffer[0x80208]; + s->cur_event = 0; + + strncpy((char *)&buffer[4], s->name, 128); + strncpy((char *)&buffer[0x44], s->song, 128); + strncpy((char *)&buffer[0x84], s->company, 128); + + return s; +} + +static void spu_tick(spu_synth_t *s) +{ + uint32 time, reg, size; + uint16 rdata; + uint8 opcode; + + if (s->old_fmt) + { + time = s->song_ptr[0] | s->song_ptr[1]<<8 | s->song_ptr[2]<<16 | s->song_ptr[3]<<24; + + while ((time == s->cur_tick) && (s->cur_event < s->num_events)) + { + reg = s->song_ptr[4] | s->song_ptr[5]<<8 | s->song_ptr[6]<<16 | s->song_ptr[7]<<24; + rdata = s->song_ptr[8] | s->song_ptr[9]<<8; + + SPUwriteRegister(s->mips_cpu, reg, rdata); + + s->cur_event++; + s->song_ptr += 12; + + time = s->song_ptr[0] | s->song_ptr[1]<<8 | s->song_ptr[2]<<16 | s->song_ptr[3]<<24; + } + } + else + { + if (s->cur_tick < s->end_tick) + { + while (s->cur_tick == s->next_tick) + { + opcode = s->song_ptr[0]; + s->song_ptr++; + + switch (opcode) + { + case 0: // write register + reg = s->song_ptr[0] | s->song_ptr[1]<<8 | s->song_ptr[2]<<16 | s->song_ptr[3]<<24; + rdata = s->song_ptr[4] | s->song_ptr[5]<<8; + + SPUwriteRegister(s->mips_cpu, reg, rdata); + + s->next_tick = s->song_ptr[6] | s->song_ptr[7]<<8 | s->song_ptr[8]<<16 | s->song_ptr[9]<<24; + s->song_ptr += 10; + break; + + case 1: // read register + reg = s->song_ptr[0] | s->song_ptr[1]<<8 | s->song_ptr[2]<<16 | s->song_ptr[3]<<24; + SPUreadRegister(s->mips_cpu, reg); + s->next_tick = s->song_ptr[4] | s->song_ptr[5]<<8 | s->song_ptr[6]<<16 | s->song_ptr[7]<<24; + s->song_ptr += 8; + break; + + case 2: // dma write + size = s->song_ptr[0] | s->song_ptr[1]<<8 | s->song_ptr[2]<<16 | s->song_ptr[3]<<24; + s->song_ptr += (4 + size); + s->next_tick = s->song_ptr[0] | s->song_ptr[1]<<8 | s->song_ptr[2]<<16 | s->song_ptr[3]<<24; + s->song_ptr += 4; + break; + + case 3: // dma read + s->next_tick = s->song_ptr[4] | s->song_ptr[5]<<8 | s->song_ptr[6]<<16 | s->song_ptr[7]<<24; + s->song_ptr += 8; + break; + + case 4: // xa play + s->song_ptr += (32 + 16384); + s->next_tick = s->song_ptr[0] | s->song_ptr[1]<<8 | s->song_ptr[2]<<16 | s->song_ptr[3]<<24; + s->song_ptr += 4; + break; + + case 5: // cdda play + size = s->song_ptr[0] | s->song_ptr[1]<<8 | s->song_ptr[2]<<16 | s->song_ptr[3]<<24; + s->song_ptr += (4 + size); + s->next_tick = s->song_ptr[0] | s->song_ptr[1]<<8 | s->song_ptr[2]<<16 | s->song_ptr[3]<<24; + s->song_ptr += 4; + break; + + default: + printf("Unknown opcode %d\n", opcode); + exit(-1); + break; + } + } + } + else + { +// ao_s->song_done = 1; + } + } + + s->cur_tick++; +} + +int32 spu_gen(void *handle, int16 *buffer, uint32 samples) +{ + spu_synth_t *s = handle; + int i, run = 1; + + if (s->old_fmt) + { + if (s->cur_event >= s->num_events) + { + run = 0; + } + } + else + { + if (s->cur_tick >= s->end_tick) + { + run = 0; + } + } + + if (run) + { + for (i = 0; i < samples; i++) + { + spu_tick(s); + SPUasync(s->mips_cpu, 384); + } + + s->spu_pOutput = (char *)buffer; + SPU_flushboot(s->mips_cpu); + } + else + { + memset(buffer, 0, samples*2*sizeof(int16)); + } + + return AO_SUCCESS; +} + +int32 spu_stop(void *handle) +{ + free (handle); + return AO_SUCCESS; +} + +int32 spu_command(void *handle, int32 command, int32 parameter) +{ + spu_synth_t *s = handle; + switch (command) + { + case COMMAND_GET_MIN: + case COMMAND_GET_MAX: + { + return 0; + } + break; + + case COMMAND_HAS_PREV: + case COMMAND_HAS_NEXT: + case COMMAND_PREV: + case COMMAND_NEXT: + case COMMAND_JUMP: + { + return AO_FAIL; + } + break; + + case COMMAND_RESTART: + { + printf ("eng_spu restart\n"); + uint8 *buffer = s->start_of_file; + int i; + uint16 reg; + + // apply the register image + for (i = 0; i < 512; i += 2) + { + reg = buffer[0x80000+i] | buffer[0x80000+i+1]<<8; + + SPUwriteRegister(s->mips_cpu, (i/2)+0x1f801c00, reg); + } + + if (!s->old_fmt) + { + s->end_tick = buffer[0x80200] | buffer[0x80201]<<8 | buffer[0x80202]<<16 | buffer[0x80203]<<24; + s->cur_tick = buffer[0x80204] | buffer[0x80205]<<8 | buffer[0x80206]<<16 | buffer[0x80207]<<24; + s->next_tick = s->cur_tick; + } + + s->song_ptr = &buffer[0x80208]; + s->cur_event = 0; + return AO_SUCCESS; + } + break; + +#if VERBOSE + default: + printf("Unknown command executed!\n"); + break; +#endif + } + + return AO_FAIL; +} + +int32 spu_fill_info(void *handle, ao_display_info *info) +{ + spu_synth_t *s = handle; + strcpy(info->title[1], "Game: "); + sprintf(info->info[1], "%.128s", s->name); + strcpy(info->title[2], "Song: "); + sprintf(info->info[2], "%.128s", s->song); + strcpy(info->title[3], "Company: "); + sprintf(info->info[3], "%.128s", s->company); + + return AO_SUCCESS; +} diff --git a/plugins/ao/eng_psf/mamemem.h b/plugins/ao/eng_psf/mamemem.h new file mode 100644 index 00000000..a28deca8 --- /dev/null +++ b/plugins/ao/eng_psf/mamemem.h @@ -0,0 +1,662 @@ +#ifndef _MEMORY_H +#define _MEMORY_H + +#include <stddef.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __GNU__ +#define UNUSEDARG __attribute__((__unused__)) +#else +#define UNUSEDARG +#endif + +#define MAX_BANKS 20 + + +/* obsolete, to be removed */ +#define READ_WORD(a) (*(UINT16 *)(a)) +#define WRITE_WORD(a,d) (*(UINT16 *)(a) = (d)) +#define COMBINE_WORD(w,d) (((w) & ((d) >> 16)) | ((d) & 0xffff)) +#define COMBINE_WORD_MEM(a,d) (WRITE_WORD((a), (READ_WORD(a) & ((d) >> 16)) | (d))) + +#define ASSERT_LINE (1) +#define CLEAR_LINE (0) +#define TIME_NEVER (0) + +#define TIME_IN_HZ(hz) (1.0 / (double)(hz)) +#define TIME_IN_MSEC(ms) ((double)(ms) * (1.0 / 1000.0)) +#define TIME_IN_USEC(us) ((double)(us) * (1.0 / 1000000.0)) + +/*************************************************************************** + +Note that the memory hooks are not passed the actual memory address where +the operation takes place, but the offset from the beginning of the block +they are assigned to. This makes handling of mirror addresses easier, and +makes the handlers a bit more "object oriented". If you handler needs to +read/write the main memory area, provide a "base" pointer: it will be +initialized by the main engine to point to the beginning of the memory block +assigned to the handler. You may also provided a pointer to "size": it +will be set to the length of the memory area processed by the handler. + +***************************************************************************/ + +#define MEMORY_WIDTH_MASK 0x00000003 +#define MEMORY_WIDTH_8 0x00000001 +#define MEMORY_WIDTH_16 0x00000002 +#define MEMORY_WIDTH_32 0x00000003 + +#define MEMORY_TYPE_MASK 0x30000000 +#define MEMORY_TYPE_MEM 0x10000000 +#define MEMORY_TYPE_IO 0x20000000 + +#define MEMORY_DIRECTION_MASK 0xc0000000 +#define MEMORY_DIRECTION_READ 0x40000000 +#define MEMORY_DIRECTION_WRITE 0x80000000 + +typedef unsigned int offs_t; +typedef offs_t (*opbase_handler)(UNUSEDARG offs_t address); + +/*************************************************************************** + 8-BIT Core memory read/write/opbase handler types +***************************************************************************/ + +typedef unsigned char data8_t; +typedef unsigned short data16_t; + +typedef data8_t (*mem_read_handler)(UNUSEDARG offs_t offset); +typedef void (*mem_write_handler)(UNUSEDARG offs_t offset, UNUSEDARG data8_t data); + +#define READ_HANDLER(name) data8_t name(UNUSEDARG offs_t offset) +#define WRITE_HANDLER(name) void name(UNUSEDARG offs_t offset, UNUSEDARG data8_t data) +#define OPBASE_HANDLER(name) offs_t name(UNUSEDARG offs_t address) + +#define READ16_HANDLER(name) data16_t name(UNUSEDARG offs_t offset, UNUSEDARG UINT32 mem_mask) +#define WRITE16_HANDLER(name) void name(UNUSEDARG offs_t offset, UNUSEDARG data16_t data, UNUSEDARG UINT32 mem_mask) +#define OPBASE16_HANDLER(name) offs_t name(UNUSEDARG offs_t address) + +#define MRA_NOP 0 /* don't care, return 0 */ +#define MWA_NOP 0 /* do nothing */ +#define MRA_RAM ((mem_read_handler)-1) /* plain RAM location (return its contents) */ +#define MWA_RAM ((mem_write_handler)-1) /* plain RAM location (store the value) */ +#define MRA_ROM ((mem_read_handler)-2) /* plain ROM location (return its contents) */ +#define MWA_ROM ((mem_write_handler)-2) /* plain ROM location (do nothing) */ +/************************************************************************** + * If the CPU opcodes are encrypted, they are fetched from a different + * memory space. In such a case, if the program dynamically creates code + * in RAM and executes it, it won't work unless you use MWA_RAMROM + * to affect both memory spaces. + **************************************************************************/ +#define MWA_RAMROM ((mem_write_handler)-3) + +/* bank memory */ +#define MRA_BANK1 ((mem_read_handler)-10) +#define MWA_BANK1 ((mem_write_handler)-10) +#define MRA_BANK2 ((mem_read_handler)-11) +#define MWA_BANK2 ((mem_write_handler)-11) +#define MRA_BANK3 ((mem_read_handler)-12) +#define MWA_BANK3 ((mem_write_handler)-12) +#define MRA_BANK4 ((mem_read_handler)-13) +#define MWA_BANK4 ((mem_write_handler)-13) +#define MRA_BANK5 ((mem_read_handler)-14) +#define MWA_BANK5 ((mem_write_handler)-14) +#define MRA_BANK6 ((mem_read_handler)-15) +#define MWA_BANK6 ((mem_write_handler)-15) +#define MRA_BANK7 ((mem_read_handler)-16) +#define MWA_BANK7 ((mem_write_handler)-16) +#define MRA_BANK8 ((mem_read_handler)-17) +#define MWA_BANK8 ((mem_write_handler)-17) +#define MRA_BANK9 ((mem_read_handler)-18) +#define MWA_BANK9 ((mem_write_handler)-18) +#define MRA_BANK10 ((mem_read_handler)-19) +#define MWA_BANK10 ((mem_write_handler)-19) +#define MRA_BANK11 ((mem_read_handler)-20) +#define MWA_BANK11 ((mem_write_handler)-20) +#define MRA_BANK12 ((mem_read_handler)-21) +#define MWA_BANK12 ((mem_write_handler)-21) +#define MRA_BANK13 ((mem_read_handler)-22) +#define MWA_BANK13 ((mem_write_handler)-22) +#define MRA_BANK14 ((mem_read_handler)-23) +#define MWA_BANK14 ((mem_write_handler)-23) +#define MRA_BANK15 ((mem_read_handler)-24) +#define MWA_BANK15 ((mem_write_handler)-24) +#define MRA_BANK16 ((mem_read_handler)-25) +#define MWA_BANK16 ((mem_write_handler)-25) +#define MRA_BANK17 ((mem_read_handler)-26) +#define MWA_BANK17 ((mem_write_handler)-26) +#define MRA_BANK18 ((mem_read_handler)-27) +#define MWA_BANK18 ((mem_write_handler)-27) +#define MRA_BANK19 ((mem_read_handler)-28) +#define MWA_BANK19 ((mem_write_handler)-28) +#define MRA_BANK20 ((mem_read_handler)-29) +#define MWA_BANK20 ((mem_write_handler)-29) + +struct Memory_ReadAddress +{ + offs_t start, end; + mem_read_handler handler; /* see special values above */ +}; + +struct Memory_WriteAddress +{ + offs_t start, end; + mem_write_handler handler; /* see special values above */ + data8_t **base; /* optional (see explanation above) */ + size_t *size; /* optional (see explanation above) */ +}; + +#define MEMORY_MARKER ((offs_t)~0) + +#define MEMORY_END { MEMORY_MARKER, 0 } }; + +#define IS_MEMORY_MARKER( ma ) ((ma)->start == MEMORY_MARKER && (ma)->end < MEMORY_MARKER) +#define IS_MEMORY_END( ma ) ((ma)->start == MEMORY_MARKER && (ma)->end == 0) + +#define MEMORY_READ_START(name) const struct Memory_ReadAddress name[] = { \ + { MEMORY_MARKER, MEMORY_DIRECTION_READ | MEMORY_TYPE_MEM | MEMORY_WIDTH_8 }, +#define MEMORY_WRITE_START(name) const struct Memory_WriteAddress name[] = { \ + { MEMORY_MARKER, MEMORY_DIRECTION_WRITE | MEMORY_TYPE_MEM | MEMORY_WIDTH_8 }, + +/*************************************************************************** + 16-BIT Core memory read/write/opbase handler types +***************************************************************************/ + +typedef data16_t (*mem_read16_handler)(UNUSEDARG offs_t offset); +typedef void (*mem_write16_handler)(UNUSEDARG offs_t offset, UNUSEDARG data16_t data, UNUSEDARG UINT32 mem_mask); + +#define READ16_HANDLER(name) data16_t name(UNUSEDARG offs_t offset, UNUSEDARG UINT32 mem_mask) +#define WRITE16_HANDLER(name) void name(UNUSEDARG offs_t offset, UNUSEDARG data16_t data, UNUSEDARG UINT32 mem_mask) +#define OPBASE16_HANDLER(name) offs_t name(UNUSEDARG offs_t address) + +#define MRA16_NOP 0 /* don't care, return 0 */ +#define MWA16_NOP 0 /* do nothing */ +#define MRA16_RAM ((mem_read16_handler)-1) /* plain RAM location (return its contents) */ +#define MWA16_RAM ((mem_write16_handler)-1) /* plqain RAM location (store the value) */ +#define MRA16_ROM ((mem_read16_handler)-2) /* plain ROM location (return its contents) */ +#define MWA16_ROM ((mem_write16_handler)-2) /* plain ROM location (do nothing) */ +/************************************************************************** + * If the CPU opcodes are encrypted, they are fetched from a different + * memory space. In such a case, if the program dynamically creates code + * in RAM and executes it, it won't work unless you use MWA_RAMROM + * to affect both memory spaces. + **************************************************************************/ +#define MWA16_RAMROM ((mem_write16_handler)-3) + +/* bank memory */ +#define MRA16_BANK1 ((mem_read16_handler)-10) +#define MWA16_BANK1 ((mem_write16_handler)-10) +#define MRA16_BANK2 ((mem_read16_handler)-11) +#define MWA16_BANK2 ((mem_write16_handler)-11) +#define MRA16_BANK3 ((mem_read16_handler)-12) +#define MWA16_BANK3 ((mem_write16_handler)-12) +#define MRA16_BANK4 ((mem_read16_handler)-13) +#define MWA16_BANK4 ((mem_write16_handler)-13) +#define MRA16_BANK5 ((mem_read16_handler)-14) +#define MWA16_BANK5 ((mem_write16_handler)-14) +#define MRA16_BANK6 ((mem_read16_handler)-15) +#define MWA16_BANK6 ((mem_write16_handler)-15) +#define MRA16_BANK7 ((mem_read16_handler)-16) +#define MWA16_BANK7 ((mem_write16_handler)-16) +#define MRA16_BANK8 ((mem_read16_handler)-17) +#define MWA16_BANK8 ((mem_write16_handler)-17) +#define MRA16_BANK9 ((mem_read16_handler)-18) +#define MWA16_BANK9 ((mem_write16_handler)-18) +#define MRA16_BANK10 ((mem_read16_handler)-19) +#define MWA16_BANK10 ((mem_write16_handler)-19) +#define MRA16_BANK11 ((mem_read16_handler)-20) +#define MWA16_BANK11 ((mem_write16_handler)-20) +#define MRA16_BANK12 ((mem_read16_handler)-21) +#define MWA16_BANK12 ((mem_write16_handler)-21) +#define MRA16_BANK13 ((mem_read16_handler)-22) +#define MWA16_BANK13 ((mem_write16_handler)-22) +#define MRA16_BANK14 ((mem_read16_handler)-23) +#define MWA16_BANK14 ((mem_write16_handler)-23) +#define MRA16_BANK15 ((mem_read16_handler)-24) +#define MWA16_BANK15 ((mem_write16_handler)-24) +#define MRA16_BANK16 ((mem_read16_handler)-25) +#define MWA16_BANK16 ((mem_write16_handler)-25) +#define MRA16_BANK17 ((mem_read16_handler)-26) +#define MWA16_BANK17 ((mem_write16_handler)-26) +#define MRA16_BANK18 ((mem_read16_handler)-27) +#define MWA16_BANK18 ((mem_write16_handler)-27) +#define MRA16_BANK19 ((mem_read16_handler)-28) +#define MWA16_BANK19 ((mem_write16_handler)-28) +#define MRA16_BANK20 ((mem_read16_handler)-29) +#define MWA16_BANK20 ((mem_write16_handler)-29) + +struct Memory_ReadAddress16 +{ + offs_t start, end; + mem_read16_handler handler; /* see special values above */ +}; + +struct Memory_WriteAddress16 +{ + offs_t start, end; + mem_write16_handler handler; /* see special values above */ + data16_t **base; /* optional (see explanation above) */ + size_t *size; /* optional (see explanation above) */ +}; + +#define MEMORY_READ16_START(name) const struct Memory_ReadAddress16 name[] = { \ + { MEMORY_MARKER, MEMORY_DIRECTION_READ | MEMORY_TYPE_MEM | MEMORY_WIDTH_16 }, +#define MEMORY_WRITE16_START(name) const struct Memory_WriteAddress16 name[] = { \ + { MEMORY_MARKER, MEMORY_DIRECTION_WRITE | MEMORY_TYPE_MEM | MEMORY_WIDTH_16 }, + +/*************************************************************************** + 32-BIT Core memory read/write/opbase handler types +***************************************************************************/ + +typedef UINT32 data32_t; + +typedef data32_t (*mem_read32_handler)(UNUSEDARG offs_t offset); +typedef void (*mem_write32_handler)(UNUSEDARG offs_t offset, UNUSEDARG data32_t data, UNUSEDARG UINT32 mem_mask); + +#define READ32_HANDLER(name) data32_t name(UNUSEDARG offs_t offset, UNUSEDARG UINT32 mem_mask) +#define WRITE32_HANDLER(name) void name(UNUSEDARG offs_t offset, UNUSEDARG data32_t data, UNUSEDARG UINT32 mem_mask) +#define OPBASE32_HANDLER(name) offs_t name(UNUSEDARG offs_t address) + +#define MRA32_NOP 0 /* don't care, return 0 */ +#define MWA32_NOP 0 /* do nothing */ +#define MRA32_RAM ((mem_read32_handler)-1) /* plain RAM location (return its contents) */ +#define MWA32_RAM ((mem_write32_handler)-1) /* plain RAM location (store the value) */ +#define MRA32_ROM ((mem_read32_handler)-2) /* plain ROM location (return its contents) */ +#define MWA32_ROM ((mem_write32_handler)-2) /* plain ROM location (do nothing) */ +/************************************************************************** + * If the CPU opcodes are encrypted, they are fetched from a different + * memory space. In such a case, if the program dynamically creates code + * in RAM and executes it, it won't work unless you use MWA_RAMROM + * to affect both memory spaces. + **************************************************************************/ +#define MWA32_RAMROM ((mem_write32_handler)-3) + +/* bank memory */ +#define MRA32_BANK1 ((mem_read32_handler)-10) +#define MWA32_BANK1 ((mem_write32_handler)-10) +#define MRA32_BANK2 ((mem_read32_handler)-11) +#define MWA32_BANK2 ((mem_write32_handler)-11) +#define MRA32_BANK3 ((mem_read32_handler)-12) +#define MWA32_BANK3 ((mem_write32_handler)-12) +#define MRA32_BANK4 ((mem_read32_handler)-13) +#define MWA32_BANK4 ((mem_write32_handler)-13) +#define MRA32_BANK5 ((mem_read32_handler)-14) +#define MWA32_BANK5 ((mem_write32_handler)-14) +#define MRA32_BANK6 ((mem_read32_handler)-15) +#define MWA32_BANK6 ((mem_write32_handler)-15) +#define MRA32_BANK7 ((mem_read32_handler)-16) +#define MWA32_BANK7 ((mem_write32_handler)-16) +#define MRA32_BANK8 ((mem_read32_handler)-17) +#define MWA32_BANK8 ((mem_write32_handler)-17) +#define MRA32_BANK9 ((mem_read32_handler)-18) +#define MWA32_BANK9 ((mem_write32_handler)-18) +#define MRA32_BANK10 ((mem_read32_handler)-19) +#define MWA32_BANK10 ((mem_write32_handler)-19) +#define MRA32_BANK11 ((mem_read32_handler)-20) +#define MWA32_BANK11 ((mem_write32_handler)-20) +#define MRA32_BANK12 ((mem_read32_handler)-21) +#define MWA32_BANK12 ((mem_write32_handler)-21) +#define MRA32_BANK13 ((mem_read32_handler)-22) +#define MWA32_BANK13 ((mem_write32_handler)-22) +#define MRA32_BANK14 ((mem_read32_handler)-23) +#define MWA32_BANK14 ((mem_write32_handler)-23) +#define MRA32_BANK15 ((mem_read32_handler)-24) +#define MWA32_BANK15 ((mem_write32_handler)-24) +#define MRA32_BANK32 ((mem_read32_handler)-25) +#define MWA32_BANK32 ((mem_write32_handler)-25) +#define MRA32_BANK17 ((mem_read32_handler)-26) +#define MWA32_BANK17 ((mem_write32_handler)-26) +#define MRA32_BANK18 ((mem_read32_handler)-27) +#define MWA32_BANK18 ((mem_write32_handler)-27) +#define MRA32_BANK19 ((mem_read32_handler)-28) +#define MWA32_BANK19 ((mem_write32_handler)-28) +#define MRA32_BANK20 ((mem_read32_handler)-29) +#define MWA32_BANK20 ((mem_write32_handler)-29) + +struct Memory_ReadAddress32 +{ + offs_t start, end; + mem_read32_handler handler; /* see special values above */ +}; + +struct Memory_WriteAddress32 +{ + offs_t start, end; + mem_write32_handler handler; /* see special values above */ + data32_t **base; /* optional (see explanation above) */ + size_t *size; /* optional (see explanation above) */ +}; + +#define MEMORY_READ32_START(name) const struct Memory_ReadAddress32 name[] = { \ + { MEMORY_MARKER, MEMORY_DIRECTION_READ | MEMORY_TYPE_MEM | MEMORY_WIDTH_32 }, +#define MEMORY_WRITE32_START(name) const struct Memory_WriteAddress32 name[] = { \ + { MEMORY_MARKER, MEMORY_DIRECTION_WRITE | MEMORY_TYPE_MEM | MEMORY_WIDTH_32 }, + +/*************************************************************************** + +IN and OUT ports are handled like memory accesses, the hook template is the +same so you can interchange them. Of course there is no 'base' pointer for +IO ports. + +***************************************************************************/ + +struct IO_ReadPort +{ + offs_t start,end; + mem_read_handler handler; /* see special values below */ +}; + +#define IORP_NOP 0 /* don't care, return 0 */ + + +struct IO_WritePort +{ + offs_t start,end; + mem_write_handler handler; /* see special values below */ +}; + +#define IOWP_NOP 0 /* do nothing */ + +#define PORT_READ_START(name) const struct IO_ReadPort name[] = { \ + { MEMORY_MARKER, MEMORY_DIRECTION_READ | MEMORY_TYPE_IO | MEMORY_WIDTH_8 }, +#define PORT_WRITE_START(name) const struct IO_WritePort name[] = { \ + { MEMORY_MARKER, MEMORY_DIRECTION_WRITE | MEMORY_TYPE_IO | MEMORY_WIDTH_8 }, +#define PORT_END MEMORY_END + +/*************************************************************************** + +If a memory region contains areas that are outside of the ROM region for +an address space, the memory system will allocate an array of structures +to track the external areas. + +***************************************************************************/ + +#define MAX_EXT_MEMORY 64 + +struct ExtMemory +{ + offs_t start,end,region; + UINT8 *data; +}; + +extern struct ExtMemory ext_memory[MAX_EXT_MEMORY]; + + + +/*************************************************************************** + +For a given number of address bits, we need to determine how many elements +there are in the first and second-order lookup tables. We also need to know +how many low-order bits to ignore. The ABITS* values represent these +constants for each address space type we support. + +***************************************************************************/ + +/* memory element block size */ +#define MH_SBITS 8 /* sub element bank size */ +#define MH_PBITS 8 /* port current element size */ +#define MH_ELEMAX 64 /* sub elements limit */ +#define MH_HARDMAX 64 /* hardware functions limit */ + +/* 16 bits address */ +#define ABITS1_16 12 +#define ABITS2_16 4 +#define ABITS_MIN_16 0 /* minimum memory block is 1 byte */ +/* 16 bits address (word access) */ +#define ABITS1_16W 12 +#define ABITS2_16W 3 +#define ABITS_MIN_16W 1 /* minimum memory block is 2 bytes */ +/* 20 bits address */ +#define ABITS1_20 12 +#define ABITS2_20 8 +#define ABITS_MIN_20 0 /* minimum memory block is 1 byte */ +/* 21 bits address */ +#define ABITS1_21 13 +#define ABITS2_21 8 +#define ABITS_MIN_21 0 /* minimum memory block is 1 byte */ +/* 24 bits address */ +#define ABITS1_24 16 +#define ABITS2_24 8 +#define ABITS_MIN_24 0 /* minimum memory block is 1 byte */ +/* 24 bits address (word access) */ +#define ABITS1_24W 15 +#define ABITS2_24W 8 +#define ABITS_MIN_24W 1 /* minimum memory block is 2 bytes */ +/* 24 bits address (dword access) */ +#define ABITS1_24DW 14 +#define ABITS2_24DW 8 +#define ABITS_MIN_24DW 2 /* minimum memory block is 4 bytes */ +/* 26 bits address (dword access) */ +#define ABITS1_26DW 16 +#define ABITS2_26DW 8 +#define ABITS_MIN_26DW 2 /* minimum memory block is 4 bytes */ +/* 29 bits address (word access) */ +#define ABITS1_29W 20 +#define ABITS2_29W 8 +#define ABITS_MIN_29W 1 /* minimum memory block is 2 bytes */ +/* 32 bits address (word access) */ +#define ABITS1_32W 23 +#define ABITS2_32W 8 +#define ABITS_MIN_32W 1 /* minimum memory block is 2 bytes */ +/* 32 bits address (dword access) */ +#define ABITS1_32DW 22 +#define ABITS2_32DW 8 +#define ABITS_MIN_32DW 2 /* minimum memory block is 4 bytes */ +/* mask bits */ +#define MHMASK(abits) (0xffffffff >> (32 - abits)) + + +/*************************************************************************** + + Global variables + +***************************************************************************/ + +typedef unsigned char MHELE; + +extern MHELE ophw; /* opcode handler */ +extern MHELE *cur_mrhard; /* current set of read handlers */ +extern MHELE *cur_mwhard; /* current set of write handlers */ + +extern UINT8 *OP_RAM; /* opcode RAM base */ +extern UINT8 *OP_ROM; /* opcode ROM base */ +extern UINT8 *cpu_bankbase[]; /* array of bank bases */ + + +/* global memory access width and mask (16-bit and 32-bit under-size accesses) */ +//extern UINT32 mem_width; +//extern UINT32 mem_mask; +//extern UINT32 mem_offs; + +/*************************************************************************** + + Macros + +***************************************************************************/ + +/* ----- 16-bit memory accessing ----- */ +#define COMBINE_DATA(varptr) (*(varptr) = (*(varptr) & mem_mask) | (data & ~mem_mask)) +#define ACCESSING_LSB ((mem_mask & 0x00ff) == 0) +#define ACCESSING_MSB ((mem_mask & 0xff00) == 0) + +//extern unsigned char prgrom[128*1024]; + +/* ----- opcode reading ----- */ +#define cpu_readop cpu_readmem16 +//#define cpu_readop16(A) READ_WORD(&prgrom[A&0x3fff]) +//#define cpu_readop32(A) READ_DWORD(&prgrom[A&0x3fff]) + +/* ----- opcode argument reading ----- */ +#define cpu_readop_arg cpu_readmem16 +//#define cpu_readop_arg16(A) READ_WORD(&prgrom[A&0x3fff]) +//#define cpu_readop_arg32(A) READ_DWORD(&prgrom[A&0x3fff]) + +/* ----- bank switching for CPU cores ----- */ +#define change_pc_generic(pc,abits2,abitsmin,shift,setop) \ +{ \ + if (cur_mrhard[(pc)>>(abits2+abitsmin+shift)] != ophw) \ + setop(pc); \ +} +#define change_pc16(pc) +//change_pc_generic(pc, ABITS2_16, ABITS_MIN_16, 0, cpu_setOPbase16) +#define change_pc20(pc) change_pc_generic(pc, ABITS2_20, ABITS_MIN_20, 0, cpu_setOPbase20) +#define change_pc21(pc) change_pc_generic(pc, ABITS2_21, ABITS_MIN_21, 0, cpu_setOPbase21) +#define change_pc24(pc) change_pc_generic(pc, ABITS2_24, ABITS_MIN_24, 0, cpu_setOPbase24) +#define change_pc16bew(pc) change_pc_generic(pc, ABITS2_16W, ABITS_MIN_16W, 0, cpu_setOPbase16bew) +#define change_pc16lew(pc) change_pc_generic(pc, ABITS2_16W, ABITS_MIN_16W, 0, cpu_setOPbase16lew) +#define change_pc24bew(pc) change_pc_generic(pc, ABITS2_24W, ABITS_MIN_24W, 0, cpu_setOPbase24bew) +#define change_pc29lew(pc) change_pc_generic(pc, ABITS2_29W, ABITS_MIN_29W, 3, cpu_setOPbase29lew) +#define change_pc32bew(pc) change_pc_generic(pc, ABITS2_32W, ABITS_MIN_32W, 0, cpu_setOPbase32bew) +#define change_pc32lew(pc) change_pc_generic(pc, ABITS2_32W, ABITS_MIN_32W, 0, cpu_setOPbase32lew) +#define change_pc24bedw(pc) change_pc_generic(pc, ABITS2_24DW, ABITS_MIN_24DW, 0, cpu_setOPbase24bedw) +#define change_pc26ledw(pc) change_pc_generic(pc, ABITS2_26DW, ABITS_MIN_26DW, 0, cpu_setOPbase26ledw) +#define change_pc32bedw(pc) change_pc_generic(pc, ABITS2_32DW, ABITS_MIN_32DW, 0, cpu_setOPbase32bedw) + +/* backward compatibility */ +#define change_pc(pc) +// change_pc16(pc) + +/* ----- for use OPbaseOverride driver, request override callback to next cpu_setOPbase ----- */ +#define catch_nextBranch() (ophw = 0xff) + +/* ----- bank switching macro ----- */ +#define cpu_setbank(bank, base) \ +{ \ + if (bank >= 1 && bank <= MAX_BANKS) \ + { \ + cpu_bankbase[bank] = (UINT8 *)(base); \ + if (ophw == bank) \ + { \ + ophw = 0xff; \ + cpu_set_op_base(cpu_get_pc()); \ + } \ + } \ +} + + +/*************************************************************************** + + Function prototypes + +***************************************************************************/ + +/* ----- memory setup function ----- */ + +/* ----- memory read functions ----- */ +data8_t cpu_readmem16(offs_t address); +data8_t cpu_readmem20(offs_t address); +data8_t cpu_readmem21(offs_t address); +data8_t cpu_readmem24(offs_t address); + +data16_t cpu_readmem16bew(offs_t address); +data16_t cpu_readmem16bew_word(offs_t address); +data16_t cpu_readmem16lew(offs_t address); +data16_t cpu_readmem16lew_word(offs_t address); +data16_t cpu_readmem24bew(offs_t address); +data16_t cpu_readmem24bew_word(offs_t address); +data16_t cpu_readmem29lew(offs_t address); +data16_t cpu_readmem29lew_word(offs_t address); +data16_t cpu_readmem32bew(offs_t address); +data16_t cpu_readmem32bew_word(offs_t address); +data16_t cpu_readmem32lew(offs_t address); +data16_t cpu_readmem32lew_word(offs_t address); + +data32_t cpu_readmem24bedw(offs_t address); +data32_t cpu_readmem24bedw_word(offs_t address); +data32_t cpu_readmem24bedw_dword(offs_t address); +data32_t cpu_readmem26ledw(offs_t address); +data32_t cpu_readmem26ledw_word(offs_t address); +data32_t cpu_readmem26ledw_dword(offs_t address); +data32_t cpu_readmem27bedw(offs_t address); +data32_t cpu_readmem27bedw_word(offs_t address); +data32_t cpu_readmem27bedw_dword(offs_t address); +data32_t cpu_readmem32bedw(offs_t address); +data32_t cpu_readmem32bedw_word(offs_t address); +data32_t cpu_readmem32bedw_dword(offs_t address); + +/* ----- memory write functions ----- */ +void cpu_writemem16(offs_t address,data8_t data); +void cpu_writemem20(offs_t address,data8_t data); +void cpu_writemem21(offs_t address,data8_t data); +void cpu_writemem24(offs_t address,data8_t data); + +void cpu_writemem16bew(offs_t address,data16_t data); +void cpu_writemem16bew_word(offs_t address,data16_t data); +void cpu_writemem16lew(offs_t address,data16_t data); +void cpu_writemem16lew_word(offs_t address,data16_t data); +void cpu_writemem24bew(offs_t address,data16_t data); +void cpu_writemem24bew_word(offs_t address,data16_t data); +void cpu_writemem29lew(offs_t address,data16_t data); +void cpu_writemem29lew_word(offs_t address,data16_t data); +void cpu_writemem32bew(offs_t address,data16_t data); +void cpu_writemem32bew_word(offs_t address,data16_t data); +void cpu_writemem32lew(offs_t address,data16_t data); +void cpu_writemem32lew_word(offs_t address,data16_t data); + +void cpu_writemem24bedw(offs_t address,data32_t data); +void cpu_writemem24bedw_word(offs_t address,data32_t data); +void cpu_writemem24bedw_dword(offs_t address,data32_t data); +void cpu_writemem26ledw(offs_t address,data32_t data); +void cpu_writemem26ledw_word(offs_t address,data32_t data); +void cpu_writemem26ledw_dword(offs_t address,data32_t data); +void cpu_writemem27bedw(offs_t address,data32_t data); +void cpu_writemem27bedw_word(offs_t address,data32_t data); +void cpu_writemem27bedw_dword(offs_t address,data32_t data); +void cpu_writemem32bedw(offs_t address,data32_t data); +void cpu_writemem32bedw_word(offs_t address,data32_t data); +void cpu_writemem32bedw_dword(offs_t address,data32_t data); + +/* ----- port I/O functions ----- */ +int cpu_readport(int port); +void cpu_writeport(int port, int value); + +/* ----- dynamic memory/port mapping ----- */ +void *install_mem_read_handler(int cpu, int start, int end, mem_read_handler handler); +void *install_mem_read16_handler(int cpu, int start, int end, mem_read16_handler handler); +void *install_mem_read32_handler(int cpu, int start, int end, mem_read32_handler handler); +void *install_mem_write_handler(int cpu, int start, int end, mem_write_handler handler); +void *install_mem_write16_handler(int cpu, int start, int end, mem_write16_handler handler); +void *install_mem_write32_handler(int cpu, int start, int end, mem_write32_handler handler); +void *install_port_read_handler(int cpu, int start, int end, mem_read_handler handler); +void *install_port_write_handler(int cpu, int start, int end, mem_write_handler handler); + +/* ----- dynamic bank handlers ----- */ +void cpu_setbankhandler_r(int bank, mem_read_handler handler); +void cpu_setbankhandler_w(int bank, mem_write_handler handler); + +/* ----- opcode base control ---- */ +void cpu_setOPbase16(offs_t pc); +void cpu_setOPbase20(offs_t pc); +void cpu_setOPbase21(offs_t pc); +void cpu_setOPbase24(offs_t pc); +void cpu_setOPbase16bew(offs_t pc); +void cpu_setOPbase16lew(offs_t pc); +void cpu_setOPbase24bew(offs_t pc); +void cpu_setOPbase24bedw(offs_t pc); +void cpu_setOPbase26ledw(offs_t pc); +void cpu_setOPbase29lew(offs_t pc); +void cpu_setOPbase32bew(offs_t pc); +void cpu_setOPbase32lew(offs_t pc); +void cpu_setOPbaseoverride(int cpu, opbase_handler function); + +/* ----- harder-to-explain functions ---- */ + +/* use this to set the a different opcode base address when using a CPU with + opcodes and data encrypted separately */ +void memory_set_opcode_base(int cpu, void *base); + +/* look up a chunk of memory and get its start/end addresses, and its base. +Pass in the cpu number and the offset. It will find the chunk containing +that offset and return the start and end addresses, along with a pointer to +the base of the memory. +This can be used (carefully!) by drivers that wish to access memory directly +without going through the readmem/writemem accessors (e.g., blitters). */ +void *findmemorychunk(int cpu, int offset, int *chunkstart, int *chunkend); + +#ifdef __cplusplus +} +#endif + +#endif /* !_MEMORY_H */ + diff --git a/plugins/ao/eng_psf/peops/License.txt b/plugins/ao/eng_psf/peops/License.txt new file mode 100644 index 00000000..e51338c2 --- /dev/null +++ b/plugins/ao/eng_psf/peops/License.txt @@ -0,0 +1,282 @@ +######################################################################### + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/plugins/ao/eng_psf/peops/adsr.c b/plugins/ao/eng_psf/peops/adsr.c new file mode 100644 index 00000000..980e97bd --- /dev/null +++ b/plugins/ao/eng_psf/peops/adsr.c @@ -0,0 +1,618 @@ +/*************************************************************************** + adsr.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2003/01/06 - Pete +// - added Neill's ADSR timings +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#define _IN_ADSR + +// will be included from spu.c +#ifdef _IN_SPU + +//////////////////////////////////////////////////////////////////////// +// ADSR func +//////////////////////////////////////////////////////////////////////// + +static u32 RateTable[160]; + +static void InitADSR(void) // INIT ADSR +{ + u32 r,rs,rd;int i; + + memset(RateTable,0,sizeof(u32)*160); // build the rate table according to Neill's rules (see at bottom of file) + + r=3;rs=1;rd=0; + + for(i=32;i<160;i++) // we start at pos 32 with the real values... everything before is 0 + { + if(r<0x3FFFFFFF) + { + r+=rs; + rd++;if(rd==5) {rd=1;rs*=2;} + } + if(r>0x3FFFFFFF) r=0x3FFFFFFF; + + RateTable[i]=r; + } +} + +//////////////////////////////////////////////////////////////////////// + +static INLINE void StartADSR(spu_state_t *spu, int ch) // MIX ADSR +{ + spu->s_chan[ch].ADSRX.lVolume=1; // and init some adsr vars + spu->s_chan[ch].ADSRX.State=0; + spu->s_chan[ch].ADSRX.EnvelopeVol=0; +} + +//////////////////////////////////////////////////////////////////////// + +static INLINE int MixADSR(spu_state_t *spu, int ch) // MIX ADSR +{ + static const int sexytable[8]= + {0,4,6,8,9,10,11,12}; + + if(spu->s_chan[ch].bStop) // should be stopped: + { // do release + if(spu->s_chan[ch].ADSRX.ReleaseModeExp) + { + spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(spu->s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18+32+sexytable[(spu->s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7]]; + } + else + { + spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(spu->s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x0C + 32]; + } + + if(spu->s_chan[ch].ADSRX.EnvelopeVol<0) + { + spu->s_chan[ch].ADSRX.EnvelopeVol=0; + spu->s_chan[ch].bOn=0; + spu->s_chan[ch].bNoise=0; + } + + spu->s_chan[ch].ADSRX.lVolume=spu->s_chan[ch].ADSRX.EnvelopeVol>>21; + return spu->s_chan[ch].ADSRX.lVolume; + } + else // not stopped yet? + { + if(spu->s_chan[ch].ADSRX.State==0) // -> attack + { + if(spu->s_chan[ch].ADSRX.AttackModeExp) + { + if(spu->s_chan[ch].ADSRX.EnvelopeVol<0x60000000) + spu->s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(spu->s_chan[ch].ADSRX.AttackRate^0x7F)-0x10 + 32]; + else + spu->s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(spu->s_chan[ch].ADSRX.AttackRate^0x7F)-0x18 + 32]; + } + else + { + spu->s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(spu->s_chan[ch].ADSRX.AttackRate^0x7F)-0x10 + 32]; + } + + if(spu->s_chan[ch].ADSRX.EnvelopeVol<0) + { + spu->s_chan[ch].ADSRX.EnvelopeVol=0x7FFFFFFF; + spu->s_chan[ch].ADSRX.State=1; + } + + spu->s_chan[ch].ADSRX.lVolume=spu->s_chan[ch].ADSRX.EnvelopeVol>>21; + return spu->s_chan[ch].ADSRX.lVolume; + } + //--------------------------------------------------// + if(spu->s_chan[ch].ADSRX.State==1) // -> decay + { + spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(spu->s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+32+sexytable[(spu->s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7]]; + + if(spu->s_chan[ch].ADSRX.EnvelopeVol<0) spu->s_chan[ch].ADSRX.EnvelopeVol=0; + if(((spu->s_chan[ch].ADSRX.EnvelopeVol>>27)&0xF) <= spu->s_chan[ch].ADSRX.SustainLevel) + { + spu->s_chan[ch].ADSRX.State=2; + } + + spu->s_chan[ch].ADSRX.lVolume=spu->s_chan[ch].ADSRX.EnvelopeVol>>21; + return spu->s_chan[ch].ADSRX.lVolume; + } + //--------------------------------------------------// + if(spu->s_chan[ch].ADSRX.State==2) // -> sustain + { + if(spu->s_chan[ch].ADSRX.SustainIncrease) + { + if(spu->s_chan[ch].ADSRX.SustainModeExp) + { + if(spu->s_chan[ch].ADSRX.EnvelopeVol<0x60000000) + spu->s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(spu->s_chan[ch].ADSRX.SustainRate^0x7F)-0x10 + 32]; + else + spu->s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(spu->s_chan[ch].ADSRX.SustainRate^0x7F)-0x18 + 32]; + } + else + { + spu->s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(spu->s_chan[ch].ADSRX.SustainRate^0x7F)-0x10 + 32]; + } + + if(spu->s_chan[ch].ADSRX.EnvelopeVol<0) + { + spu->s_chan[ch].ADSRX.EnvelopeVol=0x7FFFFFFF; + } + } + else + { + if(spu->s_chan[ch].ADSRX.SustainModeExp) + spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((spu->s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B+32+sexytable[(spu->s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7]]; + else + spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((spu->s_chan[ch].ADSRX.SustainRate^0x7F))-0x0F + 32]; + + if(spu->s_chan[ch].ADSRX.EnvelopeVol<0) + { + spu->s_chan[ch].ADSRX.EnvelopeVol=0; + } + } + spu->s_chan[ch].ADSRX.lVolume=spu->s_chan[ch].ADSRX.EnvelopeVol>>21; + return spu->s_chan[ch].ADSRX.lVolume; + } + } + return 0; +} + +#endif + +/* +James Higgs ADSR investigations: + +PSX SPU Envelope Timings +~~~~~~~~~~~~~~~~~~~~~~~~ + +First, here is an extract from doomed's SPU doc, which explains the basics +of the SPU "volume envelope": + +*** doomed doc extract start *** + +-------------------------------------------------------------------------- +Voices. +-------------------------------------------------------------------------- +The SPU has 24 hardware voices. These voices can be used to reproduce sample +data, noise or can be used as frequency modulator on the next voice. +Each voice has it's own programmable ADSR envelope filter. The main volume +can be programmed independently for left and right output. + +The ADSR envelope filter works as follows: +Ar = Attack rate, which specifies the speed at which the volume increases + from zero to it's maximum value, as soon as the note on is given. The + slope can be set to lineair or exponential. +Dr = Decay rate specifies the speed at which the volume decreases to the + sustain level. Decay is always decreasing exponentially. +Sl = Sustain level, base level from which sustain starts. +Sr = Sustain rate is the rate at which the volume of the sustained note + increases or decreases. This can be either lineair or exponential. +Rr = Release rate is the rate at which the volume of the note decreases + as soon as the note off is given. + + lvl | + ^ | /\Dr __ + Sl _| _ / _ \__--- \ + | / ---__ \ Rr + | /Ar Sr \ \ + | / \\ + |/___________________\________ + ->time + +The overal volume can also be set to sweep up or down lineairly or +exponentially from it's current value. This can be done seperately +for left and right. + +Relevant SPU registers: +------------------------------------------------------------- +$1f801xx8 Attack/Decay/Sustain level +bit |0f|0e 0d 0c 0b 0a 09 08|07 06 05 04|03 02 01 00| +desc.|Am| Ar |Dr |Sl | + +Am 0 Attack mode Linear + 1 Exponential + +Ar 0-7f attack rate +Dr 0-f decay rate +Sl 0-f sustain level +------------------------------------------------------------- +$1f801xxa Sustain rate, Release Rate. +bit |0f|0e|0d|0c 0b 0a 09 08 07 06|05|04 03 02 01 00| +desc.|Sm|Sd| 0| Sr |Rm|Rr | + +Sm 0 sustain rate mode linear + 1 exponential +Sd 0 sustain rate mode increase + 1 decrease +Sr 0-7f Sustain Rate +Rm 0 Linear decrease + 1 Exponential decrease +Rr 0-1f Release Rate + +Note: decay mode is always Expontial decrease, and thus cannot +be set. +------------------------------------------------------------- +$1f801xxc Current ADSR volume +bit |0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00| +desc.|ADSRvol | + +ADSRvol Returns the current envelope volume when + read. +-- James' Note: return range: 0 -> 32767 + +*** doomed doc extract end *** + +By using a small PSX proggie to visualise the envelope as it was played, +the following results for envelope timing were obtained: + +1. Attack rate value (linear mode) + + Attack value range: 0 -> 127 + + Value | 48 | 52 | 56 | 60 | 64 | 68 | 72 | | 80 | + ----------------------------------------------------------------- + Frames | 11 | 21 | 42 | 84 | 169| 338| 676| |2890| + + Note: frames is no. of PAL frames to reach full volume (100% + amplitude) + + Hmm, noticing that the time taken to reach full volume doubles + every time we add 4 to our attack value, we know the equation is + of form: + frames = k * 2 ^ (value / 4) + + (You may ponder about envelope generator hardware at this point, + or maybe not... :) + + By substituting some stuff and running some checks, we get: + + k = 0.00257 (close enuf) + + therefore, + frames = 0.00257 * 2 ^ (value / 4) + If you just happen to be writing an emulator, then you can probably + use an equation like: + + %volume_increase_per_tick = 1 / frames + + + ------------------------------------ + Pete: + ms=((1<<(value>>2))*514)/10000 + ------------------------------------ + +2. Decay rate value (only has log mode) + + Decay value range: 0 -> 15 + + Value | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | + ------------------------------------------------ + frames | | | | | 6 | 12 | 24 | 47 | + + Note: frames here is no. of PAL frames to decay to 50% volume. + + formula: frames = k * 2 ^ (value) + + Substituting, we get: k = 0.00146 + + Further info on logarithmic nature: + frames to decay to sustain level 3 = 3 * frames to decay to + sustain level 9 + + Also no. of frames to 25% volume = roughly 1.85 * no. of frames to + 50% volume. + + Frag it - just use linear approx. + + ------------------------------------ + Pete: + ms=((1<<value)*292)/10000 + ------------------------------------ + + +3. Sustain rate value (linear mode) + + Sustain rate range: 0 -> 127 + + Value | 48 | 52 | 56 | 60 | 64 | 68 | 72 | + ------------------------------------------- + frames | 9 | 19 | 37 | 74 | 147| 293| 587| + + Here, frames = no. of PAL frames for volume amplitude to go from 100% + to 0% (or vice-versa). + + Same formula as for attack value, just a different value for k: + + k = 0.00225 + + ie: frames = 0.00225 * 2 ^ (value / 4) + + For emulation purposes: + + %volume_increase_or_decrease_per_tick = 1 / frames + + ------------------------------------ + Pete: + ms=((1<<(value>>2))*450)/10000 + ------------------------------------ + + +4. Release rate (linear mode) + + Release rate range: 0 -> 31 + + Value | 13 | 14 | 15 | 16 | 17 | + --------------------------------------------------------------- + frames | 18 | 36 | 73 | 146| 292| + + Here, frames = no. of PAL frames to decay from 100% vol to 0% vol + after "note-off" is triggered. + + Formula: frames = k * 2 ^ (value) + + And so: k = 0.00223 + + ------------------------------------ + Pete: + ms=((1<<value)*446)/10000 + ------------------------------------ + + +Other notes: + +Log stuff not figured out. You may get some clues from the "Decay rate" +stuff above. For emu purposes it may not be important - use linear +approx. + +To get timings in millisecs, multiply frames by 20. + + + +- James Higgs 17/6/2000 +james7780@yahoo.com + +//--------------------------------------------------------------- + +OLD adsr mixing according to james' rules... has to be called +every one millisecond + + + i32 v,v2,lT,l1,l2,l3; + + if(spu->s_chan[ch].bStop) // psx wants to stop? -> release phase + { + if(spu->s_chan[ch].ADSR.ReleaseVal!=0) // -> release not 0: do release (if 0: stop right now) + { + if(!spu->s_chan[ch].ADSR.ReleaseVol) // --> release just started? set up the release stuff + { + spu->s_chan[ch].ADSR.ReleaseStartTime=spu->s_chan[ch].ADSR.lTime; + spu->s_chan[ch].ADSR.ReleaseVol=spu->s_chan[ch].ADSR.lVolume; + spu->s_chan[ch].ADSR.ReleaseTime = // --> calc how long does it take to reach the wanted sus level + (spu->s_chan[ch].ADSR.ReleaseTime* + spu->s_chan[ch].ADSR.ReleaseVol)/1024; + } + // -> NO release exp mode used (yet) + v=spu->s_chan[ch].ADSR.ReleaseVol; // -> get last volume + lT=spu->s_chan[ch].ADSR.lTime- // -> how much time is past? + spu->s_chan[ch].ADSR.ReleaseStartTime; + l1=spu->s_chan[ch].ADSR.ReleaseTime; + + if(lT<l1) // -> we still have to release + { + v=v-((v*lT)/l1); // --> calc new volume + } + else // -> release is over: now really stop that sample + {v=0;spu->s_chan[ch].bOn=0;spu->s_chan[ch].ADSR.ReleaseVol=0;spu->s_chan[ch].bNoise=0;} + } + else // -> release IS 0: release at once + { + v=0;spu->s_chan[ch].bOn=0;spu->s_chan[ch].ADSR.ReleaseVol=0;spu->s_chan[ch].bNoise=0; + } + } + else + {//--------------------------------------------------// not in release phase: + v=1024; + lT=spu->s_chan[ch].ADSR.lTime; + l1=spu->s_chan[ch].ADSR.AttackTime; + + if(lT<l1) // attack + { // no exp mode used (yet) +// if(spu->s_chan[ch].ADSR.AttackModeExp) +// { +// v=(v*lT)/l1; +// } +// else + { + v=(v*lT)/l1; + } + if(v==0) v=1; + } + else // decay + { // should be exp, but who cares? ;) + l2=spu->s_chan[ch].ADSR.DecayTime; + v2=spu->s_chan[ch].ADSR.SustainLevel; + + lT-=l1; + if(lT<l2) + { + v-=(((v-v2)*lT)/l2); + } + else // sustain + { // no exp mode used (yet) + l3=spu->s_chan[ch].ADSR.SustainTime; + lT-=l2; + if(spu->s_chan[ch].ADSR.SustainModeDec>0) + { + if(l3!=0) v2+=((v-v2)*lT)/l3; + else v2=v; + } + else + { + if(l3!=0) v2-=(v2*lT)/l3; + else v2=v; + } + + if(v2>v) v2=v; + if(v2<=0) {v2=0;spu->s_chan[ch].bOn=0;spu->s_chan[ch].ADSR.ReleaseVol=0;spu->s_chan[ch].bNoise=0;} + + v=v2; + } + } + } + + //----------------------------------------------------// + // ok, done for this channel, so increase time + + spu->s_chan[ch].ADSR.lTime+=1; // 1 = 1.020408f ms; + + if(v>1024) v=1024; // adjust volume + if(v<0) v=0; + spu->s_chan[ch].ADSR.lVolume=v; // store act volume + + return v; // return the volume factor +*/ + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + + +/* +----------------------------------------------------------------------------- +Neill Corlett +Playstation SPU envelope timing notes +----------------------------------------------------------------------------- + +This is preliminary. This may be wrong. But the model described herein fits +all of my experimental data, and it's just simple enough to sound right. + +ADSR envelope level ranges from 0x00000000 to 0x7FFFFFFF internally. +The value returned by channel reg 0xC is (envelope_level>>16). + +Each sample, an increment or decrement value will be added to or +subtracted from this envelope level. + +Create the rate log table. The values double every 4 entries. + entry #0 = 4 + + 4, 5, 6, 7, + 8,10,12,14, + 16,20,24,28, ... + + entry #40 = 4096... + entry #44 = 8192... + entry #48 = 16384... + entry #52 = 32768... + entry #56 = 65536... + +increments and decrements are in terms of ratelogtable[n] +n may exceed the table bounds (plan on n being between -32 and 127). +table values are all clipped between 0x00000000 and 0x3FFFFFFF + +when you "voice on", the envelope is always fully reset. +(yes, it may click. the real thing does this too.) + +envelope level begins at zero. + +each state happens for at least 1 cycle +(transitions are not instantaneous) +this may result in some oddness: if the decay rate is uberfast, it will cut +the envelope from full down to half in one sample, potentially skipping over +the sustain level + +ATTACK +------ +- if the envelope level has overflowed past the max, clip to 0x7FFFFFFF and + proceed to DECAY. + +Linear attack mode: +- line extends upward to 0x7FFFFFFF +- increment per sample is ratelogtable[(Ar^0x7F)-0x10] + +Logarithmic attack mode: +if envelope_level < 0x60000000: + - line extends upward to 0x60000000 + - increment per sample is ratelogtable[(Ar^0x7F)-0x10] +else: + - line extends upward to 0x7FFFFFFF + - increment per sample is ratelogtable[(Ar^0x7F)-0x18] + +DECAY +----- +- if ((envelope_level>>27)&0xF) <= Sl, proceed to SUSTAIN. + Do not clip to the sustain level. +- current line ends at (envelope_level & 0x07FFFFFF) +- decrement per sample depends on (envelope_level>>28)&0x7 + 0: ratelogtable[(4*(Dr^0x1F))-0x18+0] + 1: ratelogtable[(4*(Dr^0x1F))-0x18+4] + 2: ratelogtable[(4*(Dr^0x1F))-0x18+6] + 3: ratelogtable[(4*(Dr^0x1F))-0x18+8] + 4: ratelogtable[(4*(Dr^0x1F))-0x18+9] + 5: ratelogtable[(4*(Dr^0x1F))-0x18+10] + 6: ratelogtable[(4*(Dr^0x1F))-0x18+11] + 7: ratelogtable[(4*(Dr^0x1F))-0x18+12] + (note that this is the same as the release rate formula, except that + decay rates 10-1F aren't possible... those would be slower in theory) + +SUSTAIN +------- +- no terminating condition except for voice off +- Sd=0 (increase) behavior is identical to ATTACK for both log and linear. +- Sd=1 (decrease) behavior: +Linear sustain decrease: +- line extends to 0x00000000 +- decrement per sample is ratelogtable[(Sr^0x7F)-0x0F] +Logarithmic sustain decrease: +- current line ends at (envelope_level & 0x07FFFFFF) +- decrement per sample depends on (envelope_level>>28)&0x7 + 0: ratelogtable[(Sr^0x7F)-0x1B+0] + 1: ratelogtable[(Sr^0x7F)-0x1B+4] + 2: ratelogtable[(Sr^0x7F)-0x1B+6] + 3: ratelogtable[(Sr^0x7F)-0x1B+8] + 4: ratelogtable[(Sr^0x7F)-0x1B+9] + 5: ratelogtable[(Sr^0x7F)-0x1B+10] + 6: ratelogtable[(Sr^0x7F)-0x1B+11] + 7: ratelogtable[(Sr^0x7F)-0x1B+12] + +RELEASE +------- +- if the envelope level has overflowed to negative, clip to 0 and QUIT. + +Linear release mode: +- line extends to 0x00000000 +- decrement per sample is ratelogtable[(4*(Rr^0x1F))-0x0C] + +Logarithmic release mode: +- line extends to (envelope_level & 0x0FFFFFFF) +- decrement per sample depends on (envelope_level>>28)&0x7 + 0: ratelogtable[(4*(Rr^0x1F))-0x18+0] + 1: ratelogtable[(4*(Rr^0x1F))-0x18+4] + 2: ratelogtable[(4*(Rr^0x1F))-0x18+6] + 3: ratelogtable[(4*(Rr^0x1F))-0x18+8] + 4: ratelogtable[(4*(Rr^0x1F))-0x18+9] + 5: ratelogtable[(4*(Rr^0x1F))-0x18+10] + 6: ratelogtable[(4*(Rr^0x1F))-0x18+11] + 7: ratelogtable[(4*(Rr^0x1F))-0x18+12] + +----------------------------------------------------------------------------- +*/ diff --git a/plugins/ao/eng_psf/peops/adsr.h b/plugins/ao/eng_psf/peops/adsr.h new file mode 100644 index 00000000..5f27586b --- /dev/null +++ b/plugins/ao/eng_psf/peops/adsr.h @@ -0,0 +1,28 @@ +/*************************************************************************** + adsr.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +static INLINE void StartADSR(spu_state_t *spu, int ch); +static INLINE int MixADSR(spu_state_t *spu, int ch); diff --git a/plugins/ao/eng_psf/peops/dma.c b/plugins/ao/eng_psf/peops/dma.c new file mode 100644 index 00000000..15695c72 --- /dev/null +++ b/plugins/ao/eng_psf/peops/dma.c @@ -0,0 +1,77 @@ +/*************************************************************************** + dma.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#include "../peops/stdafx.h" + +#define _IN_DMA + +//////////////////////////////////////////////////////////////////////// +// READ DMA (many values) +//////////////////////////////////////////////////////////////////////// + +void SPUreadDMAMem(mips_cpu_context *cpu, u32 usPSXMem,int iSize) +{ + int i; + u16 *ram16 = (u16 *)&cpu->psx_ram[0]; + + for(i=0;i<iSize;i++) + { + ram16[usPSXMem>>1]=cpu->spu->spuMem[cpu->spu->spuAddr>>1]; // spu addr got by writeregister + usPSXMem+=2; + cpu->spu->spuAddr+=2; // inc spu addr + if(cpu->spu->spuAddr>0x7ffff) cpu->spu->spuAddr=0; // wrap + } +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +// to investigate: do sound data updates by writedma affect spu +// irqs? Will an irq be triggered, if new data is written to +// the memory irq address? + +//////////////////////////////////////////////////////////////////////// +// WRITE DMA (many values) +//////////////////////////////////////////////////////////////////////// + +void SPUwriteDMAMem(mips_cpu_context *cpu, u32 usPSXMem,int iSize) +{ + int i; + u16 *ram16 = (u16 *)&cpu->psx_ram[0]; + + for(i=0;i<iSize;i++) + { +// printf("main RAM %x => SPU %x\n", usPSXMem, spuAddr); + cpu->spu->spuMem[cpu->spu->spuAddr>>1] = ram16[usPSXMem>>1]; + usPSXMem+=2; // spu addr got by writeregister + cpu->spu->spuAddr+=2; // inc spu addr + if(cpu->spu->spuAddr>0x7ffff) cpu->spu->spuAddr=0; // wrap + } +} + +//////////////////////////////////////////////////////////////////////// + diff --git a/plugins/ao/eng_psf/peops/dma.h b/plugins/ao/eng_psf/peops/dma.h new file mode 100644 index 00000000..b8a32751 --- /dev/null +++ b/plugins/ao/eng_psf/peops/dma.h @@ -0,0 +1,32 @@ +/***************************************************************************
+ dma.h - description
+ -------------------
+ begin : Wed May 15 2002
+ copyright : (C) 2002 by Pete Bernert
+ email : BlackDove@addcom.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+//*************************************************************************//
+// History of changes:
+//
+// 2002/05/15 - Pete
+// - generic cleanup for the Peops release
+//
+//*************************************************************************//
+
+#include "../psx.h"
+
+u16 CALLBACK SPUreadDMA(mips_cpu_context *cpu);
+void CALLBACK SPUreadDMAMem(mips_cpu_context *cpu, u16 * pusPSXMem,int iSize);
+void CALLBACK SPUwriteDMA(mips_cpu_context *cpu, u16 val);
+void CALLBACK SPUwriteDMAMem(mips_cpu_context *cpu, u16 * pusPSXMem,int iSize);
diff --git a/plugins/ao/eng_psf/peops/externals.h b/plugins/ao/eng_psf/peops/externals.h new file mode 100644 index 00000000..1c88552c --- /dev/null +++ b/plugins/ao/eng_psf/peops/externals.h @@ -0,0 +1,181 @@ +/*************************************************************************** + externals.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#include "ao.h" + +#ifndef PEOPS_EXTERNALS +#define PEOPS_EXTERNALS + +//*************************************************************************// +// History of changes: +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) + +//////////////////////////////////////////////////////////////////////// +// spu defines +//////////////////////////////////////////////////////////////////////// + +// num of channels +#define MAXCHAN 24 + +/////////////////////////////////////////////////////////// +// struct defines +/////////////////////////////////////////////////////////// + +// ADSR INFOS PER CHANNEL +typedef struct +{ + int AttackModeExp; + s32 AttackTime; + s32 DecayTime; + s32 SustainLevel; + int SustainModeExp; + s32 SustainModeDec; + s32 SustainTime; + int ReleaseModeExp; + u32 ReleaseVal; + s32 ReleaseTime; + s32 ReleaseStartTime; + s32 ReleaseVol; + s32 lTime; + s32 lVolume; +} ADSRInfo; + +typedef struct +{ + int State; + int AttackModeExp; + int AttackRate; + int DecayRate; + int SustainLevel; + int SustainModeExp; + int SustainIncrease; + int SustainRate; + int ReleaseModeExp; + int ReleaseRate; + int EnvelopeVol; + s32 lVolume; + s32 lDummy1; + s32 lDummy2; +} ADSRInfoEx; + +/////////////////////////////////////////////////////////// + +// Tmp Flags + +// used for debug channel muting +#define FLAG_MUTE 1 + +/////////////////////////////////////////////////////////// + +// MAIN CHANNEL STRUCT +typedef struct +{ + int bNew; // start flag + + int iSBPos; // mixing stuff + int spos; + int sinc; + int SB[32+1]; + int sval; + + u8 * pStart; // start ptr into sound mem + u8 * pCurr; // current pos in sound mem + u8 * pLoop; // loop ptr in sound mem + + int bOn; // is channel active (sample playing?) + int bStop; // is channel stopped (sample _can_ still be playing, ADSR Release phase) + int iActFreq; // current psx pitch + int iUsedFreq; // current pc pitch + int iLeftVolume; // left volume + int iLeftVolRaw; // left psx volume value + int bIgnoreLoop; // ignore loop bit, if an external loop address is used + int iRightVolume; // right volume + int iRightVolRaw; // right psx volume value + int iRawPitch; // raw pitch (0...3fff) + int iIrqDone; // debug irq done flag + int s_1; // last decoding infos + int s_2; + int bRVBActive; // reverb active flag + int iRVBOffset; // reverb offset + int iRVBRepeat; // reverb repeat + int bNoise; // noise active flag + int bFMod; // freq mod (0=off, 1=sound channel, 2=freq channel) + int iOldNoise; // old noise val for this channel + ADSRInfo ADSR; // active ADSR settings + ADSRInfoEx ADSRX; // next ADSR settings (will be moved to active on sample start) + +} SPUCHAN; + +/////////////////////////////////////////////////////////// + +typedef struct +{ + int StartAddr; // reverb area start addr in samples + int CurrAddr; // reverb area curr addr in samples + + int Enabled; + int VolLeft; + int VolRight; + int iLastRVBLeft; + int iLastRVBRight; + int iRVBLeft; + int iRVBRight; + + + int FB_SRC_A; // (offset) + int FB_SRC_B; // (offset) + int IIR_ALPHA; // (coef.) + int ACC_COEF_A; // (coef.) + int ACC_COEF_B; // (coef.) + int ACC_COEF_C; // (coef.) + int ACC_COEF_D; // (coef.) + int IIR_COEF; // (coef.) + int FB_ALPHA; // (coef.) + int FB_X; // (coef.) + int IIR_DEST_A0; // (offset) + int IIR_DEST_A1; // (offset) + int ACC_SRC_A0; // (offset) + int ACC_SRC_A1; // (offset) + int ACC_SRC_B0; // (offset) + int ACC_SRC_B1; // (offset) + int IIR_SRC_A0; // (offset) + int IIR_SRC_A1; // (offset) + int IIR_DEST_B0; // (offset) + int IIR_DEST_B1; // (offset) + int ACC_SRC_C0; // (offset) + int ACC_SRC_C1; // (offset) + int ACC_SRC_D0; // (offset) + int ACC_SRC_D1; // (offset) + int IIR_SRC_B1; // (offset) + int IIR_SRC_B0; // (offset) + int MIX_DEST_A0; // (offset) + int MIX_DEST_A1; // (offset) + int MIX_DEST_B0; // (offset) + int MIX_DEST_B1; // (offset) + int IN_COEF_L; // (coef.) + int IN_COEF_R; // (coef.) +} REVERBInfo; + +#endif // PEOPS_EXTERNALS diff --git a/plugins/ao/eng_psf/peops/gauss_i.h b/plugins/ao/eng_psf/peops/gauss_i.h new file mode 100644 index 00000000..37f95245 --- /dev/null +++ b/plugins/ao/eng_psf/peops/gauss_i.h @@ -0,0 +1,163 @@ +/*************************************************************************** + gauss_i.h - description + ----------------------- + begin : Sun Feb 08 2003 + copyright : (C) 2003 by Chris Moeller, eh, whatever + email : chris@kode54.tk + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2003/02/08 - kode54 +// - generated by interleaving table from gauss.h from the libopenspc +// project; a gaussian bell curve table logged from the SPC-700, +// though Neill says he logged the same curve from a PSX SPU. Also +// says that interleaving the coefficients together runs faster. Meh. +// +//*************************************************************************// + +#ifndef GAUSS_H +#define GAUSS_H + +// 1024 entries +const int gauss[]={ + 0x172, 0x519, 0x176, 0x000, 0x16E, 0x519, 0x17A, 0x000, + 0x16A, 0x518, 0x17D, 0x000, 0x166, 0x518, 0x181, 0x000, + 0x162, 0x518, 0x185, 0x000, 0x15F, 0x518, 0x189, 0x000, + 0x15B, 0x518, 0x18D, 0x000, 0x157, 0x517, 0x191, 0x000, + 0x153, 0x517, 0x195, 0x000, 0x150, 0x517, 0x19A, 0x000, + 0x14C, 0x516, 0x19E, 0x000, 0x148, 0x516, 0x1A2, 0x000, + 0x145, 0x515, 0x1A6, 0x000, 0x141, 0x514, 0x1AA, 0x000, + 0x13E, 0x514, 0x1AE, 0x000, 0x13A, 0x513, 0x1B2, 0x000, + 0x137, 0x512, 0x1B7, 0x001, 0x133, 0x511, 0x1BB, 0x001, + 0x130, 0x511, 0x1BF, 0x001, 0x12C, 0x510, 0x1C3, 0x001, + 0x129, 0x50F, 0x1C8, 0x001, 0x125, 0x50E, 0x1CC, 0x001, + 0x122, 0x50D, 0x1D0, 0x001, 0x11E, 0x50C, 0x1D5, 0x001, + 0x11B, 0x50B, 0x1D9, 0x001, 0x118, 0x50A, 0x1DD, 0x001, + 0x114, 0x508, 0x1E2, 0x001, 0x111, 0x507, 0x1E6, 0x002, + 0x10E, 0x506, 0x1EB, 0x002, 0x10B, 0x504, 0x1EF, 0x002, + 0x107, 0x503, 0x1F3, 0x002, 0x104, 0x502, 0x1F8, 0x002, + 0x101, 0x500, 0x1FC, 0x002, 0x0FE, 0x4FF, 0x201, 0x002, + 0x0FB, 0x4FD, 0x205, 0x003, 0x0F8, 0x4FB, 0x20A, 0x003, + 0x0F5, 0x4FA, 0x20F, 0x003, 0x0F2, 0x4F8, 0x213, 0x003, + 0x0EF, 0x4F6, 0x218, 0x003, 0x0EC, 0x4F5, 0x21C, 0x004, + 0x0E9, 0x4F3, 0x221, 0x004, 0x0E6, 0x4F1, 0x226, 0x004, + 0x0E3, 0x4EF, 0x22A, 0x004, 0x0E0, 0x4ED, 0x22F, 0x004, + 0x0DD, 0x4EB, 0x233, 0x005, 0x0DA, 0x4E9, 0x238, 0x005, + 0x0D7, 0x4E7, 0x23D, 0x005, 0x0D4, 0x4E5, 0x241, 0x005, + 0x0D2, 0x4E3, 0x246, 0x006, 0x0CF, 0x4E0, 0x24B, 0x006, + 0x0CC, 0x4DE, 0x250, 0x006, 0x0C9, 0x4DC, 0x254, 0x006, + 0x0C7, 0x4D9, 0x259, 0x007, 0x0C4, 0x4D7, 0x25E, 0x007, + 0x0C1, 0x4D5, 0x263, 0x007, 0x0BF, 0x4D2, 0x267, 0x008, + 0x0BC, 0x4D0, 0x26C, 0x008, 0x0BA, 0x4CD, 0x271, 0x008, + 0x0B7, 0x4CB, 0x276, 0x009, 0x0B4, 0x4C8, 0x27B, 0x009, + 0x0B2, 0x4C5, 0x280, 0x009, 0x0AF, 0x4C3, 0x284, 0x00A, + 0x0AD, 0x4C0, 0x289, 0x00A, 0x0AB, 0x4BD, 0x28E, 0x00A, + 0x0A8, 0x4BA, 0x293, 0x00B, 0x0A6, 0x4B7, 0x298, 0x00B, + 0x0A3, 0x4B5, 0x29D, 0x00B, 0x0A1, 0x4B2, 0x2A2, 0x00C, + 0x09F, 0x4AF, 0x2A6, 0x00C, 0x09C, 0x4AC, 0x2AB, 0x00D, + 0x09A, 0x4A9, 0x2B0, 0x00D, 0x098, 0x4A6, 0x2B5, 0x00E, + 0x096, 0x4A2, 0x2BA, 0x00E, 0x093, 0x49F, 0x2BF, 0x00F, + 0x091, 0x49C, 0x2C4, 0x00F, 0x08F, 0x499, 0x2C9, 0x00F, + 0x08D, 0x496, 0x2CE, 0x010, 0x08B, 0x492, 0x2D3, 0x010, + 0x089, 0x48F, 0x2D8, 0x011, 0x086, 0x48C, 0x2DC, 0x011, + 0x084, 0x488, 0x2E1, 0x012, 0x082, 0x485, 0x2E6, 0x013, + 0x080, 0x481, 0x2EB, 0x013, 0x07E, 0x47E, 0x2F0, 0x014, + 0x07C, 0x47A, 0x2F5, 0x014, 0x07A, 0x477, 0x2FA, 0x015, + 0x078, 0x473, 0x2FF, 0x015, 0x076, 0x470, 0x304, 0x016, + 0x075, 0x46C, 0x309, 0x017, 0x073, 0x468, 0x30E, 0x017, + 0x071, 0x465, 0x313, 0x018, 0x06F, 0x461, 0x318, 0x018, + 0x06D, 0x45D, 0x31D, 0x019, 0x06B, 0x459, 0x322, 0x01A, + 0x06A, 0x455, 0x326, 0x01B, 0x068, 0x452, 0x32B, 0x01B, + 0x066, 0x44E, 0x330, 0x01C, 0x064, 0x44A, 0x335, 0x01D, + 0x063, 0x446, 0x33A, 0x01D, 0x061, 0x442, 0x33F, 0x01E, + 0x05F, 0x43E, 0x344, 0x01F, 0x05E, 0x43A, 0x349, 0x020, + 0x05C, 0x436, 0x34E, 0x020, 0x05A, 0x432, 0x353, 0x021, + 0x059, 0x42E, 0x357, 0x022, 0x057, 0x42A, 0x35C, 0x023, + 0x056, 0x425, 0x361, 0x024, 0x054, 0x421, 0x366, 0x024, + 0x053, 0x41D, 0x36B, 0x025, 0x051, 0x419, 0x370, 0x026, + 0x050, 0x415, 0x374, 0x027, 0x04E, 0x410, 0x379, 0x028, + 0x04D, 0x40C, 0x37E, 0x029, 0x04C, 0x408, 0x383, 0x02A, + 0x04A, 0x403, 0x388, 0x02B, 0x049, 0x3FF, 0x38C, 0x02C, + 0x047, 0x3FB, 0x391, 0x02D, 0x046, 0x3F6, 0x396, 0x02E, + 0x045, 0x3F2, 0x39B, 0x02F, 0x043, 0x3ED, 0x39F, 0x030, + 0x042, 0x3E9, 0x3A4, 0x031, 0x041, 0x3E5, 0x3A9, 0x032, + 0x040, 0x3E0, 0x3AD, 0x033, 0x03E, 0x3DC, 0x3B2, 0x034, + 0x03D, 0x3D7, 0x3B7, 0x035, 0x03C, 0x3D2, 0x3BB, 0x036, + 0x03B, 0x3CE, 0x3C0, 0x037, 0x03A, 0x3C9, 0x3C5, 0x038, + 0x038, 0x3C5, 0x3C9, 0x03A, 0x037, 0x3C0, 0x3CE, 0x03B, + 0x036, 0x3BB, 0x3D2, 0x03C, 0x035, 0x3B7, 0x3D7, 0x03D, + 0x034, 0x3B2, 0x3DC, 0x03E, 0x033, 0x3AD, 0x3E0, 0x040, + 0x032, 0x3A9, 0x3E5, 0x041, 0x031, 0x3A4, 0x3E9, 0x042, + 0x030, 0x39F, 0x3ED, 0x043, 0x02F, 0x39B, 0x3F2, 0x045, + 0x02E, 0x396, 0x3F6, 0x046, 0x02D, 0x391, 0x3FB, 0x047, + 0x02C, 0x38C, 0x3FF, 0x049, 0x02B, 0x388, 0x403, 0x04A, + 0x02A, 0x383, 0x408, 0x04C, 0x029, 0x37E, 0x40C, 0x04D, + 0x028, 0x379, 0x410, 0x04E, 0x027, 0x374, 0x415, 0x050, + 0x026, 0x370, 0x419, 0x051, 0x025, 0x36B, 0x41D, 0x053, + 0x024, 0x366, 0x421, 0x054, 0x024, 0x361, 0x425, 0x056, + 0x023, 0x35C, 0x42A, 0x057, 0x022, 0x357, 0x42E, 0x059, + 0x021, 0x353, 0x432, 0x05A, 0x020, 0x34E, 0x436, 0x05C, + 0x020, 0x349, 0x43A, 0x05E, 0x01F, 0x344, 0x43E, 0x05F, + 0x01E, 0x33F, 0x442, 0x061, 0x01D, 0x33A, 0x446, 0x063, + 0x01D, 0x335, 0x44A, 0x064, 0x01C, 0x330, 0x44E, 0x066, + 0x01B, 0x32B, 0x452, 0x068, 0x01B, 0x326, 0x455, 0x06A, + 0x01A, 0x322, 0x459, 0x06B, 0x019, 0x31D, 0x45D, 0x06D, + 0x018, 0x318, 0x461, 0x06F, 0x018, 0x313, 0x465, 0x071, + 0x017, 0x30E, 0x468, 0x073, 0x017, 0x309, 0x46C, 0x075, + 0x016, 0x304, 0x470, 0x076, 0x015, 0x2FF, 0x473, 0x078, + 0x015, 0x2FA, 0x477, 0x07A, 0x014, 0x2F5, 0x47A, 0x07C, + 0x014, 0x2F0, 0x47E, 0x07E, 0x013, 0x2EB, 0x481, 0x080, + 0x013, 0x2E6, 0x485, 0x082, 0x012, 0x2E1, 0x488, 0x084, + 0x011, 0x2DC, 0x48C, 0x086, 0x011, 0x2D8, 0x48F, 0x089, + 0x010, 0x2D3, 0x492, 0x08B, 0x010, 0x2CE, 0x496, 0x08D, + 0x00F, 0x2C9, 0x499, 0x08F, 0x00F, 0x2C4, 0x49C, 0x091, + 0x00F, 0x2BF, 0x49F, 0x093, 0x00E, 0x2BA, 0x4A2, 0x096, + 0x00E, 0x2B5, 0x4A6, 0x098, 0x00D, 0x2B0, 0x4A9, 0x09A, + 0x00D, 0x2AB, 0x4AC, 0x09C, 0x00C, 0x2A6, 0x4AF, 0x09F, + 0x00C, 0x2A2, 0x4B2, 0x0A1, 0x00B, 0x29D, 0x4B5, 0x0A3, + 0x00B, 0x298, 0x4B7, 0x0A6, 0x00B, 0x293, 0x4BA, 0x0A8, + 0x00A, 0x28E, 0x4BD, 0x0AB, 0x00A, 0x289, 0x4C0, 0x0AD, + 0x00A, 0x284, 0x4C3, 0x0AF, 0x009, 0x280, 0x4C5, 0x0B2, + 0x009, 0x27B, 0x4C8, 0x0B4, 0x009, 0x276, 0x4CB, 0x0B7, + 0x008, 0x271, 0x4CD, 0x0BA, 0x008, 0x26C, 0x4D0, 0x0BC, + 0x008, 0x267, 0x4D2, 0x0BF, 0x007, 0x263, 0x4D5, 0x0C1, + 0x007, 0x25E, 0x4D7, 0x0C4, 0x007, 0x259, 0x4D9, 0x0C7, + 0x006, 0x254, 0x4DC, 0x0C9, 0x006, 0x250, 0x4DE, 0x0CC, + 0x006, 0x24B, 0x4E0, 0x0CF, 0x006, 0x246, 0x4E3, 0x0D2, + 0x005, 0x241, 0x4E5, 0x0D4, 0x005, 0x23D, 0x4E7, 0x0D7, + 0x005, 0x238, 0x4E9, 0x0DA, 0x005, 0x233, 0x4EB, 0x0DD, + 0x004, 0x22F, 0x4ED, 0x0E0, 0x004, 0x22A, 0x4EF, 0x0E3, + 0x004, 0x226, 0x4F1, 0x0E6, 0x004, 0x221, 0x4F3, 0x0E9, + 0x004, 0x21C, 0x4F5, 0x0EC, 0x003, 0x218, 0x4F6, 0x0EF, + 0x003, 0x213, 0x4F8, 0x0F2, 0x003, 0x20F, 0x4FA, 0x0F5, + 0x003, 0x20A, 0x4FB, 0x0F8, 0x003, 0x205, 0x4FD, 0x0FB, + 0x002, 0x201, 0x4FF, 0x0FE, 0x002, 0x1FC, 0x500, 0x101, + 0x002, 0x1F8, 0x502, 0x104, 0x002, 0x1F3, 0x503, 0x107, + 0x002, 0x1EF, 0x504, 0x10B, 0x002, 0x1EB, 0x506, 0x10E, + 0x002, 0x1E6, 0x507, 0x111, 0x001, 0x1E2, 0x508, 0x114, + 0x001, 0x1DD, 0x50A, 0x118, 0x001, 0x1D9, 0x50B, 0x11B, + 0x001, 0x1D5, 0x50C, 0x11E, 0x001, 0x1D0, 0x50D, 0x122, + 0x001, 0x1CC, 0x50E, 0x125, 0x001, 0x1C8, 0x50F, 0x129, + 0x001, 0x1C3, 0x510, 0x12C, 0x001, 0x1BF, 0x511, 0x130, + 0x001, 0x1BB, 0x511, 0x133, 0x001, 0x1B7, 0x512, 0x137, + 0x000, 0x1B2, 0x513, 0x13A, 0x000, 0x1AE, 0x514, 0x13E, + 0x000, 0x1AA, 0x514, 0x141, 0x000, 0x1A6, 0x515, 0x145, + 0x000, 0x1A2, 0x516, 0x148, 0x000, 0x19E, 0x516, 0x14C, + 0x000, 0x19A, 0x517, 0x150, 0x000, 0x195, 0x517, 0x153, + 0x000, 0x191, 0x517, 0x157, 0x000, 0x18D, 0x518, 0x15B, + 0x000, 0x189, 0x518, 0x15F, 0x000, 0x185, 0x518, 0x162, + 0x000, 0x181, 0x518, 0x166, 0x000, 0x17D, 0x518, 0x16A, + 0x000, 0x17A, 0x519, 0x16E, 0x000, 0x176, 0x519, 0x172}; +#endif diff --git a/plugins/ao/eng_psf/peops/registers.c b/plugins/ao/eng_psf/peops/registers.c new file mode 100644 index 00000000..abc13865 --- /dev/null +++ b/plugins/ao/eng_psf/peops/registers.c @@ -0,0 +1,499 @@ +/*************************************************************************** + registers.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +/* ChangeLog + + February 8, 2004 - xodnizel + - Fixed setting of reverb volume. Just typecast val("u16") to s16. + Also adjusted the normal channel volume to be one less than what it was before when the + "phase invert" bit is set. I'm assuming it's just in two's complement. + + 2003/02/09 - kode54 + - removed &0x3fff from reverb volume registers, fixes a few games, + hopefully won't be breaking anything + + 2003/01/19 - Pete + - added Neill's reverb + + 2003/01/06 - Pete + - added Neill's ADSR timings + + 2002/05/15 - Pete + - generic cleanup for the Peops release + +*/ + +#include "stdafx.h" + +#define _IN_REGISTERS + +#include "../peops/externals.h" +#include "../peops/registers.h" +#include "../peops/regs.h" + +static void SoundOn(spu_state_t *spu, int start,int end,u16 val); +static void SoundOff(spu_state_t *spu, int start,int end,u16 val); +static void FModOn(spu_state_t *spu, int start,int end,u16 val); +static void NoiseOn(spu_state_t *spu, int start,int end,u16 val); +static void SetVolumeLR(spu_state_t *spu, int right, u8 ch,s16 vol); +static void SetPitch(spu_state_t *spu, int ch,u16 val); + +//////////////////////////////////////////////////////////////////////// +// WRITE REGISTERS: called by main emu +//////////////////////////////////////////////////////////////////////// + +void SPUwriteRegister(mips_cpu_context *cpu, u32 reg, u16 val) +{ + const u32 r=reg&0xfff; + cpu->spu->regArea[(r-0xc00)>>1] = val; + +// printf("SPUwrite: r %x val %x\n", r, val); + + if(r>=0x0c00 && r<0x0d80) // some channel info? + { + int ch=(r>>4)-0xc0; // calc channel + + //if(ch==20) printf("%08x: %04x\n",reg,val); + + switch(r&0x0f) + { + //------------------------------------------------// r volume + case 0: + SetVolumeLR(cpu->spu, 0,(u8)ch,val); + break; + //------------------------------------------------// l volume + case 2: + SetVolumeLR(cpu->spu, 1,(u8)ch,val); + break; + //------------------------------------------------// pitch + case 4: + SetPitch(cpu->spu, ch,val); + break; + //------------------------------------------------// start + case 6: + cpu->spu->s_chan[ch].pStart=cpu->spu->spuMemC+((u32) val<<3); + break; + //------------------------------------------------// level with pre-calcs + case 8: + { + const u32 lval=val; // DEBUG CHECK + //---------------------------------------------// + cpu->spu->s_chan[ch].ADSRX.AttackModeExp=(lval&0x8000)?1:0; + cpu->spu->s_chan[ch].ADSRX.AttackRate=(lval>>8) & 0x007f; + cpu->spu->s_chan[ch].ADSRX.DecayRate=(lval>>4) & 0x000f; + cpu->spu->s_chan[ch].ADSRX.SustainLevel=lval & 0x000f; + //---------------------------------------------// + } + break; + //------------------------------------------------// adsr times with pre-calcs + case 10: + { + const u32 lval=val; // DEBUG CHECK + + //----------------------------------------------// + cpu->spu->s_chan[ch].ADSRX.SustainModeExp = (lval&0x8000)?1:0; + cpu->spu->s_chan[ch].ADSRX.SustainIncrease= (lval&0x4000)?0:1; + cpu->spu->s_chan[ch].ADSRX.SustainRate = (lval>>6) & 0x007f; + cpu->spu->s_chan[ch].ADSRX.ReleaseModeExp = (lval&0x0020)?1:0; + cpu->spu->s_chan[ch].ADSRX.ReleaseRate = lval & 0x001f; + //----------------------------------------------// + } + break; + //------------------------------------------------// adsr volume... mmm have to investigate this + //case 0xC: + // break; + //------------------------------------------------// + case 0xE: // loop? + cpu->spu->s_chan[ch].pLoop=cpu->spu->spuMemC+((u32) val<<3); + cpu->spu->s_chan[ch].bIgnoreLoop=1; + break; + //------------------------------------------------// + } + return; + } + + switch(r) + { + //-------------------------------------------------// + case H_SPUaddr: + cpu->spu->spuAddr = (u32) val<<3; + break; + //-------------------------------------------------// + case H_SPUdata: + cpu->spu->spuMem[cpu->spu->spuAddr>>1] = BFLIP16(val); + cpu->spu->spuAddr+=2; + if(cpu->spu->spuAddr>0x7ffff) cpu->spu->spuAddr=0; + break; + //-------------------------------------------------// + case H_SPUctrl: + cpu->spu->spuCtrl=val; + break; + //-------------------------------------------------// + case H_SPUstat: + cpu->spu->spuStat=val & 0xf800; + break; + //-------------------------------------------------// + case H_SPUReverbAddr: + if(val==0xFFFF || val<=0x200) + {cpu->spu->rvb.StartAddr=cpu->spu->rvb.CurrAddr=0;} + else + { + const s32 iv=(u32)val<<2; + if(cpu->spu->rvb.StartAddr!=iv) + { + cpu->spu->rvb.StartAddr=(u32)val<<2; + cpu->spu->rvb.CurrAddr=cpu->spu->rvb.StartAddr; + } + } + break; + //-------------------------------------------------// + case H_SPUirqAddr: + cpu->spu->spuIrq = val; + cpu->spu->pSpuIrq=cpu->spu->spuMemC+((u32) val<<3); + break; + //-------------------------------------------------// + /* Volume settings appear to be at least 15-bit unsigned in this case. + Definitely NOT 15-bit signed. Probably 16-bit signed, so s16 type cast. + Check out "Chrono Cross: Shadow's End Forest" + */ + case H_SPUrvolL: + cpu->spu->rvb.VolLeft=(s16)val; + //printf("%d\n",val); + break; + //-------------------------------------------------// + case H_SPUrvolR: + cpu->spu->rvb.VolRight=(s16)val; + //printf("%d\n",val); + break; + //-------------------------------------------------// + +/* + case H_ExtLeft: + //auxprintf("EL %d\n",val); + break; + //-------------------------------------------------// + case H_ExtRight: + //auxprintf("ER %d\n",val); + break; + //-------------------------------------------------// + case H_SPUmvolL: + //auxprintf("ML %d\n",val); + break; + //-------------------------------------------------// + case H_SPUmvolR: + //auxprintf("MR %d\n",val); + break; + //-------------------------------------------------// + case H_SPUMute1: + //printf("M0 %04x\n",val); + break; + //-------------------------------------------------// + case H_SPUMute2: + // printf("M1 %04x\n",val); + break; +*/ + //-------------------------------------------------// + case H_SPUon1: + SoundOn(cpu->spu, 0,16,val); + break; + //-------------------------------------------------// + case H_SPUon2: + // printf("Boop: %08x: %04x\n",reg,val); + SoundOn(cpu->spu, 16,24,val); + break; + //-------------------------------------------------// + case H_SPUoff1: + SoundOff(cpu->spu, 0,16,val); + break; + //-------------------------------------------------// + case H_SPUoff2: + SoundOff(cpu->spu, 16,24,val); + // printf("Boop: %08x: %04x\n",reg,val); + break; + //-------------------------------------------------// + case H_FMod1: + FModOn(cpu->spu, 0,16,val); + break; + //-------------------------------------------------// + case H_FMod2: + FModOn(cpu->spu, 16,24,val); + break; + //-------------------------------------------------// + case H_Noise1: + NoiseOn(cpu->spu, 0,16,val); + break; + //-------------------------------------------------// + case H_Noise2: + NoiseOn(cpu->spu, 16,24,val); + break; + //-------------------------------------------------// + case H_RVBon1: + cpu->spu->rvb.Enabled&=~0xFFFF; + cpu->spu->rvb.Enabled|=val; + break; + + //-------------------------------------------------// + case H_RVBon2: + cpu->spu->rvb.Enabled&=0xFFFF; + cpu->spu->rvb.Enabled|=val<<16; + break; + + //-------------------------------------------------// + case H_Reverb+0: + cpu->spu->rvb.FB_SRC_A=val; + break; + + case H_Reverb+2 : cpu->spu->rvb.FB_SRC_B=(s16)val; break; + case H_Reverb+4 : cpu->spu->rvb.IIR_ALPHA=(s16)val; break; + case H_Reverb+6 : cpu->spu->rvb.ACC_COEF_A=(s16)val; break; + case H_Reverb+8 : cpu->spu->rvb.ACC_COEF_B=(s16)val; break; + case H_Reverb+10 : cpu->spu->rvb.ACC_COEF_C=(s16)val; break; + case H_Reverb+12 : cpu->spu->rvb.ACC_COEF_D=(s16)val; break; + case H_Reverb+14 : cpu->spu->rvb.IIR_COEF=(s16)val; break; + case H_Reverb+16 : cpu->spu->rvb.FB_ALPHA=(s16)val; break; + case H_Reverb+18 : cpu->spu->rvb.FB_X=(s16)val; break; + case H_Reverb+20 : cpu->spu->rvb.IIR_DEST_A0=(s16)val; break; + case H_Reverb+22 : cpu->spu->rvb.IIR_DEST_A1=(s16)val; break; + case H_Reverb+24 : cpu->spu->rvb.ACC_SRC_A0=(s16)val; break; + case H_Reverb+26 : cpu->spu->rvb.ACC_SRC_A1=(s16)val; break; + case H_Reverb+28 : cpu->spu->rvb.ACC_SRC_B0=(s16)val; break; + case H_Reverb+30 : cpu->spu->rvb.ACC_SRC_B1=(s16)val; break; + case H_Reverb+32 : cpu->spu->rvb.IIR_SRC_A0=(s16)val; break; + case H_Reverb+34 : cpu->spu->rvb.IIR_SRC_A1=(s16)val; break; + case H_Reverb+36 : cpu->spu->rvb.IIR_DEST_B0=(s16)val; break; + case H_Reverb+38 : cpu->spu->rvb.IIR_DEST_B1=(s16)val; break; + case H_Reverb+40 : cpu->spu->rvb.ACC_SRC_C0=(s16)val; break; + case H_Reverb+42 : cpu->spu->rvb.ACC_SRC_C1=(s16)val; break; + case H_Reverb+44 : cpu->spu->rvb.ACC_SRC_D0=(s16)val; break; + case H_Reverb+46 : cpu->spu->rvb.ACC_SRC_D1=(s16)val; break; + case H_Reverb+48 : cpu->spu->rvb.IIR_SRC_B1=(s16)val; break; + case H_Reverb+50 : cpu->spu->rvb.IIR_SRC_B0=(s16)val; break; + case H_Reverb+52 : cpu->spu->rvb.MIX_DEST_A0=(s16)val; break; + case H_Reverb+54 : cpu->spu->rvb.MIX_DEST_A1=(s16)val; break; + case H_Reverb+56 : cpu->spu->rvb.MIX_DEST_B0=(s16)val; break; + case H_Reverb+58 : cpu->spu->rvb.MIX_DEST_B1=(s16)val; break; + case H_Reverb+60 : cpu->spu->rvb.IN_COEF_L=(s16)val; break; + case H_Reverb+62 : cpu->spu->rvb.IN_COEF_R=(s16)val; break; + } + +} + +//////////////////////////////////////////////////////////////////////// +// READ REGISTER: called by main emu +//////////////////////////////////////////////////////////////////////// + +u16 SPUreadRegister(mips_cpu_context *cpu, u32 reg) +{ + const u32 r=reg&0xfff; + + if(r>=0x0c00 && r<0x0d80) + { + switch(r&0x0f) + { + case 0xC: // get adsr vol + { + const int ch=(r>>4)-0xc0; + if(cpu->spu->s_chan[ch].bNew) return 1; // we are started, but not processed? return 1 + if(cpu->spu->s_chan[ch].ADSRX.lVolume && // same here... we haven't decoded one sample yet, so no envelope yet. return 1 as well + !cpu->spu->s_chan[ch].ADSRX.EnvelopeVol) + return 1; + return (u16)(cpu->spu->s_chan[ch].ADSRX.EnvelopeVol>>16); + } + + case 0xE: // get loop address + { + const int ch=(r>>4)-0xc0; + if(cpu->spu->s_chan[ch].pLoop==NULL) return 0; + return (u16)((cpu->spu->s_chan[ch].pLoop-cpu->spu->spuMemC)>>3); + } + } + } + + switch(r) + { + case H_SPUctrl: + return cpu->spu->spuCtrl; + + case H_SPUstat: + return cpu->spu->spuStat; + + case H_SPUaddr: + return (u16)(cpu->spu->spuAddr>>3); + + case H_SPUdata: + { + u16 s=BFLIP16(cpu->spu->spuMem[cpu->spu->spuAddr>>1]); + cpu->spu->spuAddr+=2; + if(cpu->spu->spuAddr>0x7ffff) cpu->spu->spuAddr=0; + return s; + } + + case H_SPUirqAddr: + return cpu->spu->spuIrq; + + //case H_SPUIsOn1: + // return IsSoundOn(0,16); + + //case H_SPUIsOn2: + // return IsSoundOn(16,24); + + } + + return cpu->spu->regArea[(r-0xc00)>>1]; +} + +//////////////////////////////////////////////////////////////////////// +// SOUND ON register write +//////////////////////////////////////////////////////////////////////// + +static void SoundOn(spu_state_t *spu, int start,int end,u16 val) // SOUND ON PSX COMAND +{ + int ch; + + for(ch=start;ch<end;ch++,val>>=1) // loop channels + { + if((val&1) && spu->s_chan[ch].pStart) // mmm... start has to be set before key on !?! + { + spu->s_chan[ch].bIgnoreLoop=0; + spu->s_chan[ch].bNew=1; + } + } +} + +//////////////////////////////////////////////////////////////////////// +// SOUND OFF register write +//////////////////////////////////////////////////////////////////////// + +static void SoundOff(spu_state_t *spu, int start,int end,u16 val) // SOUND OFF PSX COMMAND +{ + int ch; + for(ch=start;ch<end;ch++,val>>=1) // loop channels + { + if(val&1) // && cpu->spu->s_chan[i].bOn) mmm... + { + spu->s_chan[ch].bStop=1; + } + } +} + +//////////////////////////////////////////////////////////////////////// +// FMOD register write +//////////////////////////////////////////////////////////////////////// + +static void FModOn(spu_state_t *spu, int start,int end,u16 val) // FMOD ON PSX COMMAND +{ + int ch; + + for(ch=start;ch<end;ch++,val>>=1) // loop channels + { + if(val&1) // -> fmod on/off + { + if(ch>0) + { + spu->s_chan[ch].bFMod=1; // --> sound channel + spu->s_chan[ch-1].bFMod=2; // --> freq channel + } + } + else + { + spu->s_chan[ch].bFMod=0; // --> turn off fmod + } + } +} + +//////////////////////////////////////////////////////////////////////// +// NOISE register write +//////////////////////////////////////////////////////////////////////// + +static void NoiseOn(spu_state_t *spu, int start,int end,u16 val) // NOISE ON PSX COMMAND +{ + int ch; + + for(ch=start;ch<end;ch++,val>>=1) // loop channels + { + if(val&1) // -> noise on/off + { + spu->s_chan[ch].bNoise=1; + } + else + { + spu->s_chan[ch].bNoise=0; + } + } +} + +//////////////////////////////////////////////////////////////////////// +// LEFT VOLUME register write +//////////////////////////////////////////////////////////////////////// + +// please note: sweep is wrong. + +static void SetVolumeLR(spu_state_t *spu, int right, u8 ch,s16 vol) // LEFT VOLUME +{ + //if(vol&0xc000) + //printf("%d %08x\n",right,vol); + if(right) + spu->s_chan[ch].iRightVolRaw=vol; + else + spu->s_chan[ch].iLeftVolRaw=vol; + + if(vol&0x8000) // sweep? + { + s16 sInc=1; // -> sweep up? + if(vol&0x2000) sInc=-1; // -> or down? + if(vol&0x1000) vol^=0xffff; // -> mmm... phase inverted? have to investigate this + vol=((vol&0x7f)+1)/2; // -> sweep: 0..127 -> 0..64 + vol+=vol/(2*sInc); // -> HACK: we don't sweep right now, so we just raise/lower the volume by the half! + vol*=128; + vol&=0x3fff; + //puts("Sweep"); + } + else // no sweep: + { + if(vol&0x4000) + vol=(vol&0x3FFF)-0x4000; + else + vol&=0x3FFF; + + //if(vol&0x4000) // -> mmm... phase inverted? have to investigate this + // vol=0-(0x3fff-(vol&0x3fff)); + //else + // vol&=0x3fff; + } + if(right) + spu->s_chan[ch].iRightVolume=vol; + else + spu->s_chan[ch].iLeftVolume=vol; // store volume +} + +//////////////////////////////////////////////////////////////////////// +// PITCH register write +//////////////////////////////////////////////////////////////////////// + +static void SetPitch(spu_state_t *spu, int ch,u16 val) // SET PITCH +{ + int NP; + if(val>0x3fff) NP=0x3fff; // get pitch val + else NP=val; + + spu->s_chan[ch].iRawPitch=NP; + + NP=(44100L*NP)/4096L; // calc frequency + if(NP<1) NP=1; // some security + spu->s_chan[ch].iActFreq=NP; // store frequency +} diff --git a/plugins/ao/eng_psf/peops/registers.h b/plugins/ao/eng_psf/peops/registers.h new file mode 100644 index 00000000..dc453cfa --- /dev/null +++ b/plugins/ao/eng_psf/peops/registers.h @@ -0,0 +1,153 @@ +/***************************************************************************
+ registers.h - description
+ -------------------
+ begin : Wed May 15 2002
+ copyright : (C) 2002 by Pete Bernert
+ email : BlackDove@addcom.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+//*************************************************************************//
+// History of changes:
+//
+// 2002/05/15 - Pete
+// - generic cleanup for the Peops release
+//
+//*************************************************************************//
+
+#define H_SPUReverbAddr 0x0da2
+#define H_SPUirqAddr 0x0da4
+#define H_SPUaddr 0x0da6
+#define H_SPUdata 0x0da8
+#define H_SPUctrl 0x0daa
+#define H_SPUstat 0x0dae
+#define H_SPUmvolL 0x0d80
+#define H_SPUmvolR 0x0d82
+#define H_SPUrvolL 0x0d84
+#define H_SPUrvolR 0x0d86
+#define H_SPUon1 0x0d88
+#define H_SPUon2 0x0d8a
+#define H_SPUoff1 0x0d8c
+#define H_SPUoff2 0x0d8e
+#define H_FMod1 0x0d90
+#define H_FMod2 0x0d92
+#define H_Noise1 0x0d94
+#define H_Noise2 0x0d96
+#define H_RVBon1 0x0d98
+#define H_RVBon2 0x0d9a
+#define H_SPUMute1 0x0d9c
+#define H_SPUMute2 0x0d9e
+#define H_CDLeft 0x0db0
+#define H_CDRight 0x0db2
+#define H_ExtLeft 0x0db4
+#define H_ExtRight 0x0db6
+#define H_Reverb 0x0dc0
+#define H_SPUPitch0 0x0c04
+#define H_SPUPitch1 0x0c14
+#define H_SPUPitch2 0x0c24
+#define H_SPUPitch3 0x0c34
+#define H_SPUPitch4 0x0c44
+#define H_SPUPitch5 0x0c54
+#define H_SPUPitch6 0x0c64
+#define H_SPUPitch7 0x0c74
+#define H_SPUPitch8 0x0c84
+#define H_SPUPitch9 0x0c94
+#define H_SPUPitch10 0x0ca4
+#define H_SPUPitch11 0x0cb4
+#define H_SPUPitch12 0x0cc4
+#define H_SPUPitch13 0x0cd4
+#define H_SPUPitch14 0x0ce4
+#define H_SPUPitch15 0x0cf4
+#define H_SPUPitch16 0x0d04
+#define H_SPUPitch17 0x0d14
+#define H_SPUPitch18 0x0d24
+#define H_SPUPitch19 0x0d34
+#define H_SPUPitch20 0x0d44
+#define H_SPUPitch21 0x0d54
+#define H_SPUPitch22 0x0d64
+#define H_SPUPitch23 0x0d74
+
+#define H_SPUStartAdr0 0x0c06
+#define H_SPUStartAdr1 0x0c16
+#define H_SPUStartAdr2 0x0c26
+#define H_SPUStartAdr3 0x0c36
+#define H_SPUStartAdr4 0x0c46
+#define H_SPUStartAdr5 0x0c56
+#define H_SPUStartAdr6 0x0c66
+#define H_SPUStartAdr7 0x0c76
+#define H_SPUStartAdr8 0x0c86
+#define H_SPUStartAdr9 0x0c96
+#define H_SPUStartAdr10 0x0ca6
+#define H_SPUStartAdr11 0x0cb6
+#define H_SPUStartAdr12 0x0cc6
+#define H_SPUStartAdr13 0x0cd6
+#define H_SPUStartAdr14 0x0ce6
+#define H_SPUStartAdr15 0x0cf6
+#define H_SPUStartAdr16 0x0d06
+#define H_SPUStartAdr17 0x0d16
+#define H_SPUStartAdr18 0x0d26
+#define H_SPUStartAdr19 0x0d36
+#define H_SPUStartAdr20 0x0d46
+#define H_SPUStartAdr21 0x0d56
+#define H_SPUStartAdr22 0x0d66
+#define H_SPUStartAdr23 0x0d76
+
+#define H_SPULoopAdr0 0x0c0e
+#define H_SPULoopAdr1 0x0c1e
+#define H_SPULoopAdr2 0x0c2e
+#define H_SPULoopAdr3 0x0c3e
+#define H_SPULoopAdr4 0x0c4e
+#define H_SPULoopAdr5 0x0c5e
+#define H_SPULoopAdr6 0x0c6e
+#define H_SPULoopAdr7 0x0c7e
+#define H_SPULoopAdr8 0x0c8e
+#define H_SPULoopAdr9 0x0c9e
+#define H_SPULoopAdr10 0x0cae
+#define H_SPULoopAdr11 0x0cbe
+#define H_SPULoopAdr12 0x0cce
+#define H_SPULoopAdr13 0x0cde
+#define H_SPULoopAdr14 0x0cee
+#define H_SPULoopAdr15 0x0cfe
+#define H_SPULoopAdr16 0x0d0e
+#define H_SPULoopAdr17 0x0d1e
+#define H_SPULoopAdr18 0x0d2e
+#define H_SPULoopAdr19 0x0d3e
+#define H_SPULoopAdr20 0x0d4e
+#define H_SPULoopAdr21 0x0d5e
+#define H_SPULoopAdr22 0x0d6e
+#define H_SPULoopAdr23 0x0d7e
+
+#define H_SPU_ADSRLevel0 0x0c08
+#define H_SPU_ADSRLevel1 0x0c18
+#define H_SPU_ADSRLevel2 0x0c28
+#define H_SPU_ADSRLevel3 0x0c38
+#define H_SPU_ADSRLevel4 0x0c48
+#define H_SPU_ADSRLevel5 0x0c58
+#define H_SPU_ADSRLevel6 0x0c68
+#define H_SPU_ADSRLevel7 0x0c78
+#define H_SPU_ADSRLevel8 0x0c88
+#define H_SPU_ADSRLevel9 0x0c98
+#define H_SPU_ADSRLevel10 0x0ca8
+#define H_SPU_ADSRLevel11 0x0cb8
+#define H_SPU_ADSRLevel12 0x0cc8
+#define H_SPU_ADSRLevel13 0x0cd8
+#define H_SPU_ADSRLevel14 0x0ce8
+#define H_SPU_ADSRLevel15 0x0cf8
+#define H_SPU_ADSRLevel16 0x0d08
+#define H_SPU_ADSRLevel17 0x0d18
+#define H_SPU_ADSRLevel18 0x0d28
+#define H_SPU_ADSRLevel19 0x0d38
+#define H_SPU_ADSRLevel20 0x0d48
+#define H_SPU_ADSRLevel21 0x0d58
+#define H_SPU_ADSRLevel22 0x0d68
+#define H_SPU_ADSRLevel23 0x0d78
+
diff --git a/plugins/ao/eng_psf/peops/regs.h b/plugins/ao/eng_psf/peops/regs.h new file mode 100644 index 00000000..ffa11606 --- /dev/null +++ b/plugins/ao/eng_psf/peops/regs.h @@ -0,0 +1,29 @@ +/*************************************************************************** + regs.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#include "../psx.h" + +void SPUwriteRegister(mips_cpu_context *cpu, u32 reg, u16 val); diff --git a/plugins/ao/eng_psf/peops/reverb.c b/plugins/ao/eng_psf/peops/reverb.c new file mode 100644 index 00000000..0cc09243 --- /dev/null +++ b/plugins/ao/eng_psf/peops/reverb.c @@ -0,0 +1,383 @@ +/*************************************************************************** + reverb.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2003/03/17 - xodnizel +// - Implemented Neill's 44.1Khz-22050Hz downsampling data +// I also need to check if the ~4 sample delay doesn't screw any sounds +// up by making things too out of phase. It could be fixed easily(elsewhere). +// +// 2003/01/19 - Pete +// - added Neill's reverb (see at the end of file) +// +// 2002/12/26 - Pete +// - adjusted reverb handling +// +// 2002/08/14 - Pete +// - added extra reverb +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#define _IN_REVERB + +// will be included from spu.c +#ifdef _IN_SPU + +//////////////////////////////////////////////////////////////////////// +// globals +//////////////////////////////////////////////////////////////////////// + +// REVERB info and timing vars... + +//////////////////////////////////////////////////////////////////////// + +static INLINE s64 g_buffer(spu_state_t *spu, int iOff) // get_buffer content helper: takes care about wraps +{ + s16 * p=(s16 *)spu->spuMem; + iOff=(iOff*4)+spu->rvb.CurrAddr; + while(iOff>0x3FFFF) iOff=spu->rvb.StartAddr+(iOff-0x40000); + while(iOff<spu->rvb.StartAddr) iOff=0x3ffff-(spu->rvb.StartAddr-iOff); + return (int)(s16)BFLIP16(*(p+iOff)); +} + +//////////////////////////////////////////////////////////////////////// + +static INLINE void s_buffer(spu_state_t *spu, int iOff,int iVal) // set_buffer content helper: takes care about wraps and clipping +{ + s16 * p=(s16 *)spu->spuMem; + iOff=(iOff*4)+spu->rvb.CurrAddr; + while(iOff>0x3FFFF) iOff=spu->rvb.StartAddr+(iOff-0x40000); + while(iOff<spu->rvb.StartAddr) iOff=0x3ffff-(spu->rvb.StartAddr-iOff); + if(iVal<-32768L) iVal=-32768L; + if(iVal>32767L) iVal=32767L; + *(p+iOff)=(s16)BFLIP16((s16)iVal); +} + +//////////////////////////////////////////////////////////////////////// + +static INLINE void s_buffer1(spu_state_t *spu, int iOff,int iVal) // set_buffer (+1 sample) content helper: takes care about wraps and clipping +{ + s16 * p=(s16 *)spu->spuMem; + iOff=(iOff*4)+spu->rvb.CurrAddr+1; + while(iOff>0x3FFFF) iOff=spu->rvb.StartAddr+(iOff-0x40000); + while(iOff<spu->rvb.StartAddr) iOff=0x3ffff-(spu->rvb.StartAddr-iOff); + if(iVal<-32768L) iVal=-32768L;if(iVal>32767L) iVal=32767L; + *(p+iOff)=(s16)BFLIP16((s16)iVal); +} + +static INLINE void MixREVERBLeftRight(spu_state_t *spu, s32 *oleft, s32 *oright, s32 inleft, s32 inright) +{ + static s32 downbuf[2][8]; + static s32 upbuf[2][8]; + static int dbpos=0,ubpos=0; + static s32 downcoeffs[8]={ /* Symmetry is sexy. */ + 1283,5344,10895,15243, + 15243,10895,5344,1283 + }; + int x; + + if(!spu->rvb.StartAddr) // reverb is off + { + spu->rvb.iRVBLeft=spu->rvb.iRVBRight=0; + return; + } + + //if(inleft<-32767 || inleft>32767) printf("%d\n",inleft); + //if(inright<-32767 || inright>32767) printf("%d\n",inright); + downbuf[0][dbpos]=inleft; + downbuf[1][dbpos]=inright; + dbpos=(dbpos+1)&7; + + if(dbpos&1) // we work on every second left value: downsample to 22 khz + { + if(spu->spuCtrl&0x80) // -> reverb on? oki + { + int ACC0,ACC1,FB_A0,FB_A1,FB_B0,FB_B1; + s32 INPUT_SAMPLE_L=0; + s32 INPUT_SAMPLE_R=0; + + for(x=0;x<8;x++) + { + INPUT_SAMPLE_L+=(downbuf[0][(dbpos+x)&7]*downcoeffs[x])>>8; /* Lose insignificant + digits to prevent + overflow(check this) */ + INPUT_SAMPLE_R+=(downbuf[1][(dbpos+x)&7]*downcoeffs[x])>>8; + } + + INPUT_SAMPLE_L>>=(16-8); + INPUT_SAMPLE_R>>=(16-8); + { + const s64 IIR_INPUT_A0 = ((g_buffer(spu, spu->rvb.IIR_SRC_A0) * spu->rvb.IIR_COEF)>>15) + ((INPUT_SAMPLE_L * spu->rvb.IN_COEF_L)>>15); + const s64 IIR_INPUT_A1 = ((g_buffer(spu, spu->rvb.IIR_SRC_A1) * spu->rvb.IIR_COEF)>>15) + ((INPUT_SAMPLE_R * spu->rvb.IN_COEF_R)>>15); + const s64 IIR_INPUT_B0 = ((g_buffer(spu, spu->rvb.IIR_SRC_B0) * spu->rvb.IIR_COEF)>>15) + ((INPUT_SAMPLE_L * spu->rvb.IN_COEF_L)>>15); + const s64 IIR_INPUT_B1 = ((g_buffer(spu, spu->rvb.IIR_SRC_B1) * spu->rvb.IIR_COEF)>>15) + ((INPUT_SAMPLE_R * spu->rvb.IN_COEF_R)>>15); + const s64 IIR_A0 = ((IIR_INPUT_A0 * spu->rvb.IIR_ALPHA)>>15) + ((g_buffer(spu, spu->rvb.IIR_DEST_A0) * (32768L - spu->rvb.IIR_ALPHA))>>15); + const s64 IIR_A1 = ((IIR_INPUT_A1 * spu->rvb.IIR_ALPHA)>>15) + ((g_buffer(spu, spu->rvb.IIR_DEST_A1) * (32768L - spu->rvb.IIR_ALPHA))>>15); + const s64 IIR_B0 = ((IIR_INPUT_B0 * spu->rvb.IIR_ALPHA)>>15) + ((g_buffer(spu, spu->rvb.IIR_DEST_B0) * (32768L - spu->rvb.IIR_ALPHA))>>15); + const s64 IIR_B1 = ((IIR_INPUT_B1 * spu->rvb.IIR_ALPHA)>>15) + ((g_buffer(spu, spu->rvb.IIR_DEST_B1) * (32768L - spu->rvb.IIR_ALPHA))>>15); + + s_buffer1(spu, spu->rvb.IIR_DEST_A0, IIR_A0); + s_buffer1(spu, spu->rvb.IIR_DEST_A1, IIR_A1); + s_buffer1(spu, spu->rvb.IIR_DEST_B0, IIR_B0); + s_buffer1(spu, spu->rvb.IIR_DEST_B1, IIR_B1); + + ACC0 = ((g_buffer(spu, spu->rvb.ACC_SRC_A0) * spu->rvb.ACC_COEF_A)>>15) + + ((g_buffer(spu, spu->rvb.ACC_SRC_B0) * spu->rvb.ACC_COEF_B)>>15) + + ((g_buffer(spu, spu->rvb.ACC_SRC_C0) * spu->rvb.ACC_COEF_C)>>15) + + ((g_buffer(spu, spu->rvb.ACC_SRC_D0) * spu->rvb.ACC_COEF_D)>>15); + ACC1 = ((g_buffer(spu, spu->rvb.ACC_SRC_A1) * spu->rvb.ACC_COEF_A)>>15) + + ((g_buffer(spu, spu->rvb.ACC_SRC_B1) * spu->rvb.ACC_COEF_B)>>15) + + ((g_buffer(spu, spu->rvb.ACC_SRC_C1) * spu->rvb.ACC_COEF_C)>>15) + + ((g_buffer(spu, spu->rvb.ACC_SRC_D1) * spu->rvb.ACC_COEF_D)>>15); + + FB_A0 = g_buffer(spu, spu->rvb.MIX_DEST_A0 - spu->rvb.FB_SRC_A); + FB_A1 = g_buffer(spu, spu->rvb.MIX_DEST_A1 - spu->rvb.FB_SRC_A); + FB_B0 = g_buffer(spu, spu->rvb.MIX_DEST_B0 - spu->rvb.FB_SRC_B); + FB_B1 = g_buffer(spu, spu->rvb.MIX_DEST_B1 - spu->rvb.FB_SRC_B); + + s_buffer(spu, spu->rvb.MIX_DEST_A0, ACC0 - ((FB_A0 * spu->rvb.FB_ALPHA)>>15)); + s_buffer(spu, spu->rvb.MIX_DEST_A1, ACC1 - ((FB_A1 * spu->rvb.FB_ALPHA)>>15)); + + s_buffer(spu, spu->rvb.MIX_DEST_B0, ((spu->rvb.FB_ALPHA * ACC0)>>15) - ((FB_A0 * (int)(spu->rvb.FB_ALPHA^0xFFFF8000))>>15) - ((FB_B0 * spu->rvb.FB_X)>>15)); + s_buffer(spu, spu->rvb.MIX_DEST_B1, ((spu->rvb.FB_ALPHA * ACC1)>>15) - ((FB_A1 * (int)(spu->rvb.FB_ALPHA^0xFFFF8000))>>15) - ((FB_B1 * spu->rvb.FB_X)>>15)); + + spu->rvb.iRVBLeft = (g_buffer(spu, spu->rvb.MIX_DEST_A0)+g_buffer(spu, spu->rvb.MIX_DEST_B0))/3; + spu->rvb.iRVBRight = (g_buffer(spu, spu->rvb.MIX_DEST_A1)+g_buffer(spu, spu->rvb.MIX_DEST_B1))/3; + + spu->rvb.iRVBLeft = ((s64)spu->rvb.iRVBLeft * spu->rvb.VolLeft) >> 14; + spu->rvb.iRVBRight = ((s64)spu->rvb.iRVBRight * spu->rvb.VolRight) >> 14; + + upbuf[0][ubpos]=spu->rvb.iRVBLeft; + upbuf[1][ubpos]=spu->rvb.iRVBRight; + ubpos=(ubpos+1)&7; + } // Bracket hack(et). + } + else // -> reverb off + { + spu->rvb.iRVBLeft=spu->rvb.iRVBRight=0; + return; + } + spu->rvb.CurrAddr++; + if(spu->rvb.CurrAddr>0x3ffff) spu->rvb.CurrAddr=spu->rvb.StartAddr; + } + else + { + upbuf[0][ubpos]=0; + upbuf[1][ubpos]=0; + ubpos=(ubpos+1)&7; + } + { + s32 retl=0,retr=0; + for(x=0;x<8;x++) + { + retl+=(upbuf[0][(ubpos+x)&7]*downcoeffs[x])>>8; + retr+=(upbuf[1][(ubpos+x)&7]*downcoeffs[x])>>8; + } + retl>>=(16-8-1); /* -1 To adjust for the null padding. */ + retr>>=(16-8-1); + + *oleft+=retl; + *oright+=retr; + } +} + +//////////////////////////////////////////////////////////////////////// + +#endif + +/* +----------------------------------------------------------------------------- +PSX reverb hardware notes +by Neill Corlett +----------------------------------------------------------------------------- + +Yadda yadda disclaimer yadda probably not perfect yadda well it's okay anyway +yadda yadda. + +----------------------------------------------------------------------------- + +Basics +------ + +- The reverb buffer is 22khz 16-bit mono PCM. +- It starts at the reverb address given by 1DA2, extends to + the end of sound RAM, and wraps back to the 1DA2 address. + +Setting the address at 1DA2 resets the current reverb work address. + +This work address ALWAYS increments every 1/22050 sec., regardless of +whether reverb is enabled (bit 7 of 1DAA set). + +And the contents of the reverb buffer ALWAYS play, scaled by the +"reverberation depth left/right" volumes (1D84/1D86). +(which, by the way, appear to be scaled so 3FFF=approx. 1.0, 4000=-1.0) + +----------------------------------------------------------------------------- + +Register names +-------------- + +These are probably not their real names. +These are probably not even correct names. +We will use them anyway, because we can. + +1DC0: FB_SRC_A (offset) +1DC2: FB_SRC_B (offset) +1DC4: IIR_ALPHA (coef.) +1DC6: ACC_COEF_A (coef.) +1DC8: ACC_COEF_B (coef.) +1DCA: ACC_COEF_C (coef.) +1DCC: ACC_COEF_D (coef.) +1DCE: IIR_COEF (coef.) +1DD0: FB_ALPHA (coef.) +1DD2: FB_X (coef.) +1DD4: IIR_DEST_A0 (offset) +1DD6: IIR_DEST_A1 (offset) +1DD8: ACC_SRC_A0 (offset) +1DDA: ACC_SRC_A1 (offset) +1DDC: ACC_SRC_B0 (offset) +1DDE: ACC_SRC_B1 (offset) +1DE0: IIR_SRC_A0 (offset) +1DE2: IIR_SRC_A1 (offset) +1DE4: IIR_DEST_B0 (offset) +1DE6: IIR_DEST_B1 (offset) +1DE8: ACC_SRC_C0 (offset) +1DEA: ACC_SRC_C1 (offset) +1DEC: ACC_SRC_D0 (offset) +1DEE: ACC_SRC_D1 (offset) +1DF0: IIR_SRC_B1 (offset) +1DF2: IIR_SRC_B0 (offset) +1DF4: MIX_DEST_A0 (offset) +1DF6: MIX_DEST_A1 (offset) +1DF8: MIX_DEST_B0 (offset) +1DFA: MIX_DEST_B1 (offset) +1DFC: IN_COEF_L (coef.) +1DFE: IN_COEF_R (coef.) + +The coefficients are signed fractional values. +-32768 would be -1.0 + 32768 would be 1.0 (if it were possible... the highest is of course 32767) + +The offsets are (byte/8) offsets into the reverb buffer. +i.e. you multiply them by 8, you get byte offsets. +You can also think of them as (samples/4) offsets. +They appear to be signed. They can be negative. +None of the documented presets make them negative, though. + +Yes, 1DF0 and 1DF2 appear to be backwards. Not a typo. + +----------------------------------------------------------------------------- + +What it does +------------ + +We take all reverb sources: +- regular channels that have the reverb bit on +- cd and external sources, if their reverb bits are on +and mix them into one stereo 44100hz signal. + +Lowpass/downsample that to 22050hz. The PSX uses a proper bandlimiting +algorithm here, but I haven't figured out the hysterically exact specifics. +I use an 8-tap filter with these coefficients, which are nice but probably +not the real ones: + +0.037828187894 +0.157538631280 +0.321159685278 +0.449322115345 +0.449322115345 +0.321159685278 +0.157538631280 +0.037828187894 + +So we have two input samples (INPUT_SAMPLE_L, INPUT_SAMPLE_R) every 22050hz. + +* IN MY EMULATION, I divide these by 2 to make it clip less. + (and of course the L/R output coefficients are adjusted to compensate) + The real thing appears to not do this. + +At every 22050hz tick: +- If the reverb bit is enabled (bit 7 of 1DAA), execute the reverb + steady-state algorithm described below +- AFTERWARDS, retrieve the "wet out" L and R samples from the reverb buffer + (This part may not be exactly right and I guessed at the coefs. TODO: check later.) + L is: 0.333 * (buffer[MIX_DEST_A0] + buffer[MIX_DEST_B0]) + R is: 0.333 * (buffer[MIX_DEST_A1] + buffer[MIX_DEST_B1]) +- Advance the current buffer position by 1 sample + +The wet out L and R are then upsampled to 44100hz and played at the +"reverberation depth left/right" (1D84/1D86) volume, independent of the main +volume. + +----------------------------------------------------------------------------- + +Reverb steady-state +------------------- + +The reverb steady-state algorithm is fairly clever, and of course by +"clever" I mean "batshit insane". + +buffer[x] is relative to the current buffer position, not the beginning of +the buffer. Note that all buffer offsets must wrap around so they're +contained within the reverb work area. + +Clipping is performed at the end... maybe also sooner, but definitely at +the end. + +IIR_INPUT_A0 = buffer[IIR_SRC_A0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L; +IIR_INPUT_A1 = buffer[IIR_SRC_A1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R; +IIR_INPUT_B0 = buffer[IIR_SRC_B0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L; +IIR_INPUT_B1 = buffer[IIR_SRC_B1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R; + +IIR_A0 = IIR_INPUT_A0 * IIR_ALPHA + buffer[IIR_DEST_A0] * (1.0 - IIR_ALPHA); +IIR_A1 = IIR_INPUT_A1 * IIR_ALPHA + buffer[IIR_DEST_A1] * (1.0 - IIR_ALPHA); +IIR_B0 = IIR_INPUT_B0 * IIR_ALPHA + buffer[IIR_DEST_B0] * (1.0 - IIR_ALPHA); +IIR_B1 = IIR_INPUT_B1 * IIR_ALPHA + buffer[IIR_DEST_B1] * (1.0 - IIR_ALPHA); + +buffer[IIR_DEST_A0 + 1sample] = IIR_A0; +buffer[IIR_DEST_A1 + 1sample] = IIR_A1; +buffer[IIR_DEST_B0 + 1sample] = IIR_B0; +buffer[IIR_DEST_B1 + 1sample] = IIR_B1; + +ACC0 = buffer[ACC_SRC_A0] * ACC_COEF_A + + buffer[ACC_SRC_B0] * ACC_COEF_B + + buffer[ACC_SRC_C0] * ACC_COEF_C + + buffer[ACC_SRC_D0] * ACC_COEF_D; +ACC1 = buffer[ACC_SRC_A1] * ACC_COEF_A + + buffer[ACC_SRC_B1] * ACC_COEF_B + + buffer[ACC_SRC_C1] * ACC_COEF_C + + buffer[ACC_SRC_D1] * ACC_COEF_D; + +FB_A0 = buffer[MIX_DEST_A0 - FB_SRC_A]; +FB_A1 = buffer[MIX_DEST_A1 - FB_SRC_A]; +FB_B0 = buffer[MIX_DEST_B0 - FB_SRC_B]; +FB_B1 = buffer[MIX_DEST_B1 - FB_SRC_B]; + +buffer[MIX_DEST_A0] = ACC0 - FB_A0 * FB_ALPHA; +buffer[MIX_DEST_A1] = ACC1 - FB_A1 * FB_ALPHA; +buffer[MIX_DEST_B0] = (FB_ALPHA * ACC0) - FB_A0 * (FB_ALPHA^0x8000) - FB_B0 * FB_X; +buffer[MIX_DEST_B1] = (FB_ALPHA * ACC1) - FB_A1 * (FB_ALPHA^0x8000) - FB_B1 * FB_X; + +----------------------------------------------------------------------------- +*/ + diff --git a/plugins/ao/eng_psf/peops/spu.c b/plugins/ao/eng_psf/peops/spu.c new file mode 100644 index 00000000..75f3c845 --- /dev/null +++ b/plugins/ao/eng_psf/peops/spu.c @@ -0,0 +1,623 @@ +/*************************************************************************** + spu.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2003/03/01 - linuzappz +// - libraryName changes using ALSA +// +// 2003/02/28 - Pete +// - added option for type of interpolation +// - adjusted spu irqs again (Thousant Arms, Valkyrie Profile) +// - added MONO support for MSWindows DirectSound +// +// 2003/02/20 - kode54 +// - amended interpolation code, goto GOON could skip initialization of gpos and cause segfault +// +// 2003/02/19 - kode54 +// - moved SPU IRQ handler and changed sample flag processing +// +// 2003/02/18 - kode54 +// - moved ADSR calculation outside of the sample decode loop, somehow I doubt that +// ADSR timing is relative to the frequency at which a sample is played... I guess +// this remains to be seen, and I don't know whether ADSR is applied to noise channels... +// +// 2003/02/09 - kode54 +// - one-shot samples now process the end block before stopping +// - in light of removing fmod hack, now processing ADSR on frequency channel as well +// +// 2003/02/08 - kode54 +// - replaced easy interpolation with gaussian +// - removed fmod averaging hack +// - changed .sinc to be updated from .iRawPitch, no idea why it wasn't done this way already (<- Pete: because I sometimes fail to see the obvious, haharhar :) +// +// 2003/02/08 - linuzappz +// - small bugfix for one usleep that was 1 instead of 1000 +// - added iDisStereo for no stereo (Linux) +// +// 2003/01/22 - Pete +// - added easy interpolation & small noise adjustments +// +// 2003/01/19 - Pete +// - added Neill's reverb +// +// 2003/01/12 - Pete +// - added recording window handlers +// +// 2003/01/06 - Pete +// - added Neill's ADSR timings +// +// 2002/12/28 - Pete +// - adjusted spu irq handling, fmod handling and loop handling +// +// 2002/08/14 - Pete +// - added extra reverb +// +// 2002/06/08 - linuzappz +// - SPUupdate changed for SPUasync +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#define _IN_SPU + +#include "../peops/stdafx.h" +#include "../peops/externals.h" +#include "../peops/regs.h" +#include "../peops/registers.h" +#include "../peops/spu.h" + +void SPUirq(void) ; + +//#include "PsxMem.h" +//#include "driver.h" + +//////////////////////////////////////////////////////////////////////// +// globals +//////////////////////////////////////////////////////////////////////// +static const int f[5][2] = { + { 0, 0 }, + { 60, 0 }, + { 115, -52 }, + { 98, -55 }, + { 122, -60 } }; + +//////////////////////////////////////////////////////////////////////// +// CODE AREA +//////////////////////////////////////////////////////////////////////// + +// dirty inline func includes + +#include "ao.h" + +#include "../peops/reverb.c" +#include "../peops/adsr.c" + +// Try this to increase speed. +#include "../peops/registers.c" +#include "../peops/dma.c" + +//////////////////////////////////////////////////////////////////////// +// helpers for so-called "gauss interpolation" + +#define gval0 (((int *)(&spu->s_chan[ch].SB[29]))[gpos]) +#define gval(x) (((int *)(&spu->s_chan[ch].SB[29]))[(gpos+x)&3]) + +#include "gauss_i.h" + +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// START SOUND... called by main thread to setup a new sound on a channel +//////////////////////////////////////////////////////////////////////// + +static INLINE void StartSound(spu_state_t *spu, int ch) +{ + StartADSR(spu, ch); + + spu->s_chan[ch].pCurr=spu->s_chan[ch].pStart; // set sample start + + spu->s_chan[ch].s_1=0; // init mixing vars + spu->s_chan[ch].s_2=0; + spu->s_chan[ch].iSBPos=28; + + spu->s_chan[ch].bNew=0; // init channel flags + spu->s_chan[ch].bStop=0; + spu->s_chan[ch].bOn=1; + + spu->s_chan[ch].SB[29]=0; // init our interpolation helpers + spu->s_chan[ch].SB[30]=0; + + spu->s_chan[ch].spos=0x40000L;spu->s_chan[ch].SB[28]=0; // -> start with more decoding +} + +//////////////////////////////////////////////////////////////////////// +// MAIN SPU FUNCTION +// here is the main job handler... thread, timer or direct func call +// basically the whole sound processing is done in this fat func! +//////////////////////////////////////////////////////////////////////// + +// Counting to 65536 results in full volume offage. +void setlength(spu_state_t *spu, s32 stop, s32 fade) +{ + if(stop==~0) + { + spu->decaybegin=~0; + } + else + { + stop=(stop*441)/10; + fade=(fade*441)/10; + + spu->decaybegin=stop; + spu->decayend=stop+fade; + } +} + +#define CLIP(_x) {if(_x>32767) _x=32767; if(_x<-32767) _x=-32767;} +int SPUasync(mips_cpu_context *cpu, u32 cycles) +{ + spu_state_t *spu = cpu->spu; + int volmul=spu->iVolume; + s32 temp; + + spu->ttemp+=cycles; + spu->dosampies=spu->ttemp/384; + if(!spu->dosampies) return(1); + spu->ttemp-=spu->dosampies*384; + temp=spu->dosampies; + + while(temp) + { + s32 revLeft=0, revRight=0; + s32 sl=0, sr=0; + int ch,fa; + + temp--; + //--------------------------------------------------// + //- main channel loop -// + //--------------------------------------------------// + { + for(ch=0;ch<MAXCHAN;ch++) // loop em all. + { + if(spu->s_chan[ch].bNew) StartSound(spu, ch); // start new sound + if(!spu->s_chan[ch].bOn) continue; // channel not playing? next + + + if(spu->s_chan[ch].iActFreq!=spu->s_chan[ch].iUsedFreq) // new psx frequency? + { + spu->s_chan[ch].iUsedFreq=spu->s_chan[ch].iActFreq; // -> take it and calc steps + spu->s_chan[ch].sinc=spu->s_chan[ch].iRawPitch<<4; + if(!spu->s_chan[ch].sinc) spu->s_chan[ch].sinc=1; + } + + while(spu->s_chan[ch].spos>=0x10000L) + { + if(spu->s_chan[ch].iSBPos==28) // 28 reached? + { + int predict_nr,shift_factor,flags,d,s; + u8* start;unsigned int nSample; + int s_1,s_2; + + start=spu->s_chan[ch].pCurr; // set up the current pos + + if (start == (u8*)-1) // special "stop" sign + { + spu->s_chan[ch].bOn=0; // -> turn everything off + spu->s_chan[ch].ADSRX.lVolume=0; + spu->s_chan[ch].ADSRX.EnvelopeVol=0; + goto ENDX; // -> and done for this channel + } + + spu->s_chan[ch].iSBPos=0; // Reset buffer play index. + + //////////////////////////////////////////// spu irq handler here? mmm... do it later + + s_1=spu->s_chan[ch].s_1; + s_2=spu->s_chan[ch].s_2; + + predict_nr=(int)*start;start++; + shift_factor=predict_nr&0xf; + predict_nr >>= 4; + flags=(int)*start;start++; + + // -------------------------------------- // + // Decode new samples into spu->s_chan[ch].SB[0 through 27] + for (nSample=0;nSample<28;start++) + { + d=(int)*start; + s=((d&0xf)<<12); + if(s&0x8000) s|=0xffff0000; + + fa=(s >> shift_factor); + fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6); + s_2=s_1;s_1=fa; + s=((d & 0xf0) << 8); + + spu->s_chan[ch].SB[nSample++]=fa; + + if(s&0x8000) s|=0xffff0000; + fa=(s>>shift_factor); + fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6); + s_2=s_1;s_1=fa; + + spu->s_chan[ch].SB[nSample++]=fa; + } + + //////////////////////////////////////////// irq check + + if(spu->spuCtrl&0x40) // irq active? + { + if((spu->pSpuIrq > start-16 && // irq address reached? + spu->pSpuIrq <= start) || + ((flags&1) && // special: irq on looping addr, when stop/loop flag is set + (spu->pSpuIrq > spu->s_chan[ch].pLoop-16 && + spu->pSpuIrq <= spu->s_chan[ch].pLoop))) + { + //extern s32 spuirqvoodoo; + spu->s_chan[ch].iIrqDone=1; // -> debug flag + SPUirq(); + //puts("IRQ"); + //if(spuirqvoodoo!=-1) + //{ + // spuirqvoodoo=temp*384; + // temp=0; + //} + } + } + + //////////////////////////////////////////// flag handler + + if((flags&4) && (!spu->s_chan[ch].bIgnoreLoop)) + spu->s_chan[ch].pLoop=start-16; // loop adress + + if(flags&1) // 1: stop/loop + { + // We play this block out first... + //if(!(flags&2)) // 1+2: do loop... otherwise: stop + if(flags!=3 || spu->s_chan[ch].pLoop==NULL) // PETE: if we don't check exactly for 3, loop hang ups will happen (DQ4, for example) + { // and checking if pLoop is set avoids crashes, yeah + start = (u8*)-1; + } + else + { + start = spu->s_chan[ch].pLoop; + } + } + + spu->s_chan[ch].pCurr=start; // store values for next cycle + spu->s_chan[ch].s_1=s_1; + spu->s_chan[ch].s_2=s_2; + + //////////////////////////////////////////// + } + + fa=spu->s_chan[ch].SB[spu->s_chan[ch].iSBPos++]; // get sample data + + if((spu->spuCtrl&0x4000)==0) fa=0; // muted? + else CLIP(fa); + + { + int gpos; + gpos = spu->s_chan[ch].SB[28]; + gval0 = fa; + gpos = (gpos+1) & 3; + spu->s_chan[ch].SB[28] = gpos; + } + spu->s_chan[ch].spos -= 0x10000L; + } + + //////////////////////////////////////////////// + // noise handler... just produces some noise data + // surely wrong... and no noise frequency (spuCtrl&0x3f00) will be used... + // and sometimes the noise will be used as fmod modulation... pfff + + if(spu->s_chan[ch].bNoise) + { + //puts("Noise"); + if((spu->dwNoiseVal<<=1)&0x80000000L) + { + spu->dwNoiseVal^=0x0040001L; + fa=((spu->dwNoiseVal>>2)&0x7fff); + fa=-fa; + } + else fa=(spu->dwNoiseVal>>2)&0x7fff; + + // mmm... depending on the noise freq we allow bigger/smaller changes to the previous val + fa=spu->s_chan[ch].iOldNoise+((fa-spu->s_chan[ch].iOldNoise)/((0x001f-((spu->spuCtrl&0x3f00)>>9))+1)); + if(fa>32767L) fa=32767L; + if(fa<-32767L) fa=-32767L; + spu->s_chan[ch].iOldNoise=fa; + + } //---------------------------------------- + else // NO NOISE (NORMAL SAMPLE DATA) HERE + { + int vl, vr, gpos; + vl = (spu->s_chan[ch].spos >> 6) & ~3; + gpos = spu->s_chan[ch].SB[28]; + vr=(gauss[vl]*gval0)>>9; + vr+=(gauss[vl+1]*gval(1))>>9; + vr+=(gauss[vl+2]*gval(2))>>9; + vr+=(gauss[vl+3]*gval(3))>>9; + fa = vr>>2; + } + + spu->s_chan[ch].sval = (MixADSR(spu, ch) * fa)>>10; // / 1023; // add adsr + if(spu->s_chan[ch].bFMod==2) // fmod freq channel + { + int NP=spu->s_chan[ch+1].iRawPitch; + NP=((32768L+spu->s_chan[ch].sval)*NP)>>15; ///32768L; + + if(NP>0x3fff) NP=0x3fff; + if(NP<0x1) NP=0x1; + + // mmmm... if I do this, all is screwed + // spu->s_chan[ch+1].iRawPitch=NP; + + NP=(44100L*NP)/(4096L); // calc frequency + + spu->s_chan[ch+1].iActFreq=NP; + spu->s_chan[ch+1].iUsedFreq=NP; + spu->s_chan[ch+1].sinc=(((NP/10)<<16)/4410); + if(!spu->s_chan[ch+1].sinc) spu->s_chan[ch+1].sinc=1; + + // mmmm... set up freq decoding positions? + // spu->s_chan[ch+1].iSBPos=28; + // spu->s_chan[ch+1].spos=0x10000L; + } + else + { + ////////////////////////////////////////////// + // ok, left/right sound volume (psx volume goes from 0 ... 0x3fff) + int tmpl,tmpr; + + if (1) //ao_channel_enable[ch+PSF_1]) { + { + tmpl=(spu->s_chan[ch].sval*spu->s_chan[ch].iLeftVolume)>>14; + tmpr=(spu->s_chan[ch].sval*spu->s_chan[ch].iRightVolume)>>14; + } else { + tmpl = 0; + tmpr = 0; + } + sl+=tmpl; + sr+=tmpr; + + if(((spu->rvb.Enabled>>ch)&1) && (spu->spuCtrl&0x80)) + { + revLeft+=tmpl; + revRight+=tmpr; + } + } + + spu->s_chan[ch].spos += spu->s_chan[ch].sinc; + ENDX: ; + } + } + + /////////////////////////////////////////////////////// + // mix all channels (including reverb) into one buffer + MixREVERBLeftRight(spu, &sl,&sr,revLeft,revRight); +// printf("sampcount %d decaybegin %d decayend %d\n", sampcount, decaybegin, decayend); + if(spu->sampcount>=spu->decaybegin) + { + s32 dmul; + if(spu->decaybegin!=~0) // Is anyone REALLY going to be playing a song + // for 13 hours? + { + if(spu->sampcount>=spu->decayend) + { +// ao_song_done = 1; + return(0); + } + dmul=256-(256*(spu->sampcount-spu->decaybegin)/(spu->decayend-spu->decaybegin)); + sl=(sl*dmul)>>8; + sr=(sr*dmul)>>8; + } + } + + spu->sampcount++; + sl=(sl*volmul)>>8; + sr=(sr*volmul)>>8; + + //{ + // static double asl=0; + // static double asr=0; + + // asl+=(sl-asl)/5; + // asr+=(sl-asr)/5; + + //sl-=asl; + //sr-=asr; + + // if(sl>32767 || sl < -32767) printf("Left: %d, %f\n",sl,asl); + // if(sr>32767 || sr < -32767) printf("Right: %d, %f\n",sl,asl); + //} + + if(sl>32767) sl=32767; if(sl<-32767) sl=-32767; + if(sr>32767) sr=32767; if(sr<-32767) sr=-32767; + + *spu->pS++=sl; + *spu->pS++=sr; + } + + return(1); +} + +void SPU_flushboot(mips_cpu_context *cpu) +{ + spu_state_t *spu = cpu->spu; + if((u8*)spu->pS>((u8*)spu->pSpuBuffer+1024)) + { + //spu_update(cpu, (u8*)pSpuBuffer,(u8*)pS-(u8*)pSpuBuffer); + cpu->spu_callback ((u8*)spu->pSpuBuffer,(u8*)spu->pS-(u8*)spu->pSpuBuffer, cpu->spu_callback_data); + spu->pS=(s16 *)spu->pSpuBuffer; + } +} + +#ifdef TIMEO +static u64 begintime; +static u64 gettime64(void) +{ + struct timeval tv; + u64 ret; + + gettimeofday(&tv,0); + ret=tv.tv_sec; + ret*=1000000; + ret+=tv.tv_usec; + return(ret); +} +#endif +//////////////////////////////////////////////////////////////////////// +// INIT/EXIT STUFF +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// SPUINIT: this func will be called first by the main emu +//////////////////////////////////////////////////////////////////////// + +int SPUinit(mips_cpu_context *cpu, void (*update_cb)(unsigned char *pSound, long lBytes, void *data), void *data) +{ + cpu->spu_callback = update_cb; + cpu->spu_callback_data = data; + cpu->spu = malloc (sizeof (spu_state_t)); + memset (cpu->spu, 0, sizeof (spu_state_t)); + cpu->spu->dwNoiseVal = 1; + cpu->spu->spuAddr = 0xffffffff; + cpu->spu->spuMemC=(u8*)cpu->spu->spuMem; // just small setup + memset((void *)cpu->spu->s_chan,0,MAXCHAN*sizeof(SPUCHAN)); + memset((void *)&cpu->spu->rvb,0,sizeof(REVERBInfo)); + memset(cpu->spu->regArea,0,sizeof(cpu->spu->regArea)); + memset(cpu->spu->spuMem,0,sizeof(cpu->spu->spuMem)); + InitADSR(); + cpu->spu->sampcount = cpu->spu->ttemp=0; + #ifdef TIMEO + begintime=gettime64(); + #endif + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// SETUPSTREAMS: init most of the spu buffers +//////////////////////////////////////////////////////////////////////// + +void SetupStreams(spu_state_t *spu) +{ + int i; + + spu->pSpuBuffer=(u8*)malloc(32768); // alloc mixing buffer + spu->pS=(s16 *)spu->pSpuBuffer; + + for(i=0;i<MAXCHAN;i++) // loop sound channels + { + spu->s_chan[i].ADSRX.SustainLevel = 1024; // -> init sustain + spu->s_chan[i].iIrqDone=0; + spu->s_chan[i].pLoop=spu->spuMemC; + spu->s_chan[i].pStart=spu->spuMemC; + spu->s_chan[i].pCurr=spu->spuMemC; + } +} + +//////////////////////////////////////////////////////////////////////// +// REMOVESTREAMS: free most buffer +//////////////////////////////////////////////////////////////////////// + +void RemoveStreams(spu_state_t *spu) +{ + free(spu->pSpuBuffer); // free mixing buffer + spu->pSpuBuffer=NULL; + + #ifdef TIMEO + { + u64 tmp; + tmp=gettime64(); + tmp-=begintime; + if(tmp) + tmp=(u64)sampcount*1000000/tmp; + printf("%lld samples per second\n",tmp); + } + #endif +} + + +//////////////////////////////////////////////////////////////////////// +// SPUOPEN: called by main emu after init +//////////////////////////////////////////////////////////////////////// + +int SPUopen(mips_cpu_context *cpu) +{ + spu_state_t *spu = cpu->spu; + if(spu->bSPUIsOpen) return 0; // security for some stupid main emus + spu->spuIrq=0; + + spu->spuStat=spu->spuCtrl=0; + spu->spuAddr=0xffffffff; + spu->dwNoiseVal=1; + + spu->spuMemC=(u8*)spu->spuMem; + memset((void *)spu->s_chan,0,(MAXCHAN+1)*sizeof(SPUCHAN)); + spu->pSpuIrq=0; + + spu->iVolume=255; //85; + SetupStreams(spu); // prepare streaming + + spu->bSPUIsOpen=1; + + return 1; +} + +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// SPUCLOSE: called before shutdown +//////////////////////////////////////////////////////////////////////// + +int SPUclose(mips_cpu_context *cpu) +{ + spu_state_t *spu = cpu->spu; + if(!spu->bSPUIsOpen) return 0; // some security + + spu->bSPUIsOpen=0; // no more open + + RemoveStreams(spu); // no more streaming + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// SPUSHUTDOWN: called by main emu on final exit +//////////////////////////////////////////////////////////////////////// + +int SPUshutdown(mips_cpu_context *cpu) +{ + return 0; +} + +void SPUinjectRAMImage(mips_cpu_context *cpu, u16 *pIncoming) +{ + spu_state_t *spu = cpu->spu; + int i; + + for (i = 0; i < (256*1024); i++) + { + spu->spuMem[i] = pIncoming[i]; + } +} diff --git a/plugins/ao/eng_psf/peops/spu.h b/plugins/ao/eng_psf/peops/spu.h new file mode 100644 index 00000000..7e1ea9b7 --- /dev/null +++ b/plugins/ao/eng_psf/peops/spu.h @@ -0,0 +1,74 @@ +/*************************************************************************** + spu.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#include "externals.h" +#include "../psx.h" +void sexyd_update(unsigned char* pSound,long lBytes); + +typedef struct spu_state_s { + // psx buffer / addresses + u16 regArea[0x200]; + u16 spuMem[256*1024]; + u8 * spuMemC; + u8 * pSpuIrq; + u8 * pSpuBuffer; + + // user settings + int iVolume; + + // MAIN infos struct for each channel + + SPUCHAN s_chan[MAXCHAN+1]; // channel + 1 infos (1 is security for fmod handling) + REVERBInfo rvb; + + u32 dwNoiseVal;//=1; // global noise generator + + u16 spuCtrl; // some vars to store psx reg infos + u16 spuStat; + u16 spuIrq; + u32 spuAddr; //=0xffffffff; // address into spu mem + int bSPUIsOpen; + + s16 * pS; + s32 ttemp; + u32 sampcount; + u32 decaybegin; + u32 decayend; + + s32 dosampies; +} spu_state_t; + +int SPUasync(mips_cpu_context *cpu, u32 cycles); +void SPU_flushboot(mips_cpu_context *cpu); +int SPUinit(mips_cpu_context *cpu, void (*update_cb)(unsigned char *pSound, long lBytes, void *data), void *data); +int SPUopen(mips_cpu_context *cpu); +int SPUclose(mips_cpu_context *cpu); +int SPUshutdown(mips_cpu_context *cpu); +void SPUinjectRAMImage(mips_cpu_context *cpu, u16 *pIncoming); +void SPUreadDMAMem(mips_cpu_context *cpu, u32 usPSXMem,int iSize); +void SPUwriteDMAMem(mips_cpu_context *cpu, u32 usPSXMem,int iSize); +u16 SPUreadRegister(mips_cpu_context *cpu, u32 reg); + diff --git a/plugins/ao/eng_psf/peops/stdafx.h b/plugins/ao/eng_psf/peops/stdafx.h new file mode 100644 index 00000000..6506f324 --- /dev/null +++ b/plugins/ao/eng_psf/peops/stdafx.h @@ -0,0 +1,29 @@ +/*************************************************************************** + StdAfx.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#include <stdlib.h> +#include <string.h> +#include <math.h> diff --git a/plugins/ao/eng_psf/peops2/License.txt b/plugins/ao/eng_psf/peops2/License.txt new file mode 100644 index 00000000..e51338c2 --- /dev/null +++ b/plugins/ao/eng_psf/peops2/License.txt @@ -0,0 +1,282 @@ +######################################################################### + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/plugins/ao/eng_psf/peops2/adsr.h b/plugins/ao/eng_psf/peops2/adsr.h new file mode 100644 index 00000000..777a0d84 --- /dev/null +++ b/plugins/ao/eng_psf/peops2/adsr.h @@ -0,0 +1,28 @@ +/***************************************************************************
+ adsr.h - description
+ -------------------
+ begin : Wed May 15 2002
+ copyright : (C) 2002 by Pete Bernert
+ email : BlackDove@addcom.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+//*************************************************************************//
+// History of changes:
+//
+// 2002/05/15 - Pete
+// - generic cleanup for the Peops release
+//
+//*************************************************************************//
+
+INLINE void StartADSR(int ch);
+INLINE int MixADSR(int ch);
diff --git a/plugins/ao/eng_psf/peops2/adsr2.c b/plugins/ao/eng_psf/peops2/adsr2.c new file mode 100644 index 00000000..470069c6 --- /dev/null +++ b/plugins/ao/eng_psf/peops2/adsr2.c @@ -0,0 +1,656 @@ +/***************************************************************************
+ adsr.c - description
+ -------------------
+ begin : Wed May 15 2002
+ copyright : (C) 2002 by Pete Bernert
+ email : BlackDove@addcom.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+//*************************************************************************//
+// History of changes:
+//
+// 2003/05/14 - xodnizel
+// - removed stopping of reverb on sample end
+//
+// 2003/01/06 - Pete
+// - added Neill's ADSR timings
+//
+// 2002/05/15 - Pete
+// - generic cleanup for the Peops release
+//
+//*************************************************************************//
+
+#include "stdafx.h"
+
+#define _IN_ADSR
+
+// will be included from spu.c
+#ifdef _IN_SPU
+
+////////////////////////////////////////////////////////////////////////
+// ADSR func
+////////////////////////////////////////////////////////////////////////
+
+unsigned long RateTable[160];
+
+void InitADSR(void) // INIT ADSR
+{
+ unsigned long r,rs,rd;int i;
+
+ memset(RateTable,0,sizeof(unsigned long)*160); // build the rate table according to Neill's rules (see at bottom of file)
+
+ r=3;rs=1;rd=0;
+
+ for(i=32;i<160;i++) // we start at pos 32 with the real values... everything before is 0
+ {
+ if(r<0x3FFFFFFF)
+ {
+ r+=rs;
+ rd++;if(rd==5) {rd=1;rs*=2;}
+ }
+ if(r>0x3FFFFFFF) r=0x3FFFFFFF;
+
+ RateTable[i]=r;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+
+INLINE void StartADSR(spu2_state_t *spu, int ch) // MIX ADSR
+{
+ spu->s_chan[ch].ADSRX.lVolume=1; // and init some adsr vars
+ spu->s_chan[ch].ADSRX.State=0;
+ spu->s_chan[ch].ADSRX.EnvelopeVol=0;
+}
+
+////////////////////////////////////////////////////////////////////////
+
+INLINE int MixADSR(spu2_state_t *spu, int ch) // MIX ADSR
+{
+ if(spu->s_chan[ch].bStop) // should be stopped:
+ { // do release
+ if(spu->s_chan[ch].ADSRX.ReleaseModeExp)
+ {
+ switch((spu->s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7)
+ {
+ case 0: spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(spu->s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +0 + 32]; break;
+ case 1: spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(spu->s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +4 + 32]; break;
+ case 2: spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(spu->s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +6 + 32]; break;
+ case 3: spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(spu->s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +8 + 32]; break;
+ case 4: spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(spu->s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +9 + 32]; break;
+ case 5: spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(spu->s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +10+ 32]; break;
+ case 6: spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(spu->s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +11+ 32]; break;
+ case 7: spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(spu->s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +12+ 32]; break;
+ }
+ }
+ else
+ {
+ spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(spu->s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x0C + 32];
+ }
+
+ if(spu->s_chan[ch].ADSRX.EnvelopeVol<0)
+ {
+ spu->s_chan[ch].ADSRX.EnvelopeVol=0;
+ spu->s_chan[ch].bOn=0;
+ //spu->s_chan[ch].bReverb=0;
+ //spu->s_chan[ch].bNoise=0;
+ }
+
+ spu->s_chan[ch].ADSRX.lVolume=spu->s_chan[ch].ADSRX.EnvelopeVol>>21;
+ return spu->s_chan[ch].ADSRX.lVolume;
+ }
+ else // not stopped yet?
+ {
+ if(spu->s_chan[ch].ADSRX.State==0) // -> attack
+ {
+ if(spu->s_chan[ch].ADSRX.AttackModeExp)
+ {
+ if(spu->s_chan[ch].ADSRX.EnvelopeVol<0x60000000)
+ spu->s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(spu->s_chan[ch].ADSRX.AttackRate^0x7F)-0x10 + 32];
+ else
+ spu->s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(spu->s_chan[ch].ADSRX.AttackRate^0x7F)-0x18 + 32];
+ }
+ else
+ {
+ spu->s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(spu->s_chan[ch].ADSRX.AttackRate^0x7F)-0x10 + 32];
+ }
+
+ if(spu->s_chan[ch].ADSRX.EnvelopeVol<0)
+ {
+ spu->s_chan[ch].ADSRX.EnvelopeVol=0x7FFFFFFF;
+ spu->s_chan[ch].ADSRX.State=1;
+ }
+
+ spu->s_chan[ch].ADSRX.lVolume=spu->s_chan[ch].ADSRX.EnvelopeVol>>21;
+ return spu->s_chan[ch].ADSRX.lVolume;
+ }
+ //--------------------------------------------------//
+ if(spu->s_chan[ch].ADSRX.State==1) // -> decay
+ {
+ switch((spu->s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7)
+ {
+ case 0: spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(spu->s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+0 + 32]; break;
+ case 1: spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(spu->s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+4 + 32]; break;
+ case 2: spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(spu->s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+6 + 32]; break;
+ case 3: spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(spu->s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+8 + 32]; break;
+ case 4: spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(spu->s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+9 + 32]; break;
+ case 5: spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(spu->s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+10+ 32]; break;
+ case 6: spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(spu->s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+11+ 32]; break;
+ case 7: spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(spu->s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+12+ 32]; break;
+ }
+
+ if(spu->s_chan[ch].ADSRX.EnvelopeVol<0) spu->s_chan[ch].ADSRX.EnvelopeVol=0;
+ if(((spu->s_chan[ch].ADSRX.EnvelopeVol>>27)&0xF) <= spu->s_chan[ch].ADSRX.SustainLevel)
+ {
+ spu->s_chan[ch].ADSRX.State=2;
+ }
+
+ spu->s_chan[ch].ADSRX.lVolume=spu->s_chan[ch].ADSRX.EnvelopeVol>>21;
+ return spu->s_chan[ch].ADSRX.lVolume;
+ }
+ //--------------------------------------------------//
+ if(spu->s_chan[ch].ADSRX.State==2) // -> sustain
+ {
+ if(spu->s_chan[ch].ADSRX.SustainIncrease)
+ {
+ if(spu->s_chan[ch].ADSRX.SustainModeExp)
+ {
+ if(spu->s_chan[ch].ADSRX.EnvelopeVol<0x60000000)
+ spu->s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(spu->s_chan[ch].ADSRX.SustainRate^0x7F)-0x10 + 32];
+ else
+ spu->s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(spu->s_chan[ch].ADSRX.SustainRate^0x7F)-0x18 + 32];
+ }
+ else
+ {
+ spu->s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(spu->s_chan[ch].ADSRX.SustainRate^0x7F)-0x10 + 32];
+ }
+
+ if(spu->s_chan[ch].ADSRX.EnvelopeVol<0)
+ {
+ spu->s_chan[ch].ADSRX.EnvelopeVol=0x7FFFFFFF;
+ }
+ }
+ else
+ {
+ if(spu->s_chan[ch].ADSRX.SustainModeExp)
+ {
+ switch((spu->s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7)
+ {
+ case 0: spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((spu->s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +0 + 32];break;
+ case 1: spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((spu->s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +4 + 32];break;
+ case 2: spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((spu->s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +6 + 32];break;
+ case 3: spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((spu->s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +8 + 32];break;
+ case 4: spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((spu->s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +9 + 32];break;
+ case 5: spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((spu->s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +10+ 32];break;
+ case 6: spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((spu->s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +11+ 32];break;
+ case 7: spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((spu->s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +12+ 32];break;
+ }
+ }
+ else
+ {
+ spu->s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((spu->s_chan[ch].ADSRX.SustainRate^0x7F))-0x0F + 32];
+ }
+
+ if(spu->s_chan[ch].ADSRX.EnvelopeVol<0)
+ {
+ spu->s_chan[ch].ADSRX.EnvelopeVol=0;
+ }
+ }
+ spu->s_chan[ch].ADSRX.lVolume=spu->s_chan[ch].ADSRX.EnvelopeVol>>21;
+ return spu->s_chan[ch].ADSRX.lVolume;
+ }
+ }
+ return 0;
+}
+
+#endif
+
+/*
+James Higgs ADSR investigations:
+
+PSX SPU Envelope Timings
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+First, here is an extract from doomed's SPU doc, which explains the basics
+of the SPU "volume envelope":
+
+*** doomed doc extract start ***
+
+--------------------------------------------------------------------------
+Voices.
+--------------------------------------------------------------------------
+The SPU has 24 hardware voices. These voices can be used to reproduce sample
+data, noise or can be used as frequency modulator on the next voice.
+Each voice has it's own programmable ADSR envelope filter. The main volume
+can be programmed independently for left and right output.
+
+The ADSR envelope filter works as follows:
+Ar = Attack rate, which specifies the speed at which the volume increases
+ from zero to it's maximum value, as soon as the note on is given. The
+ slope can be set to lineair or exponential.
+Dr = Decay rate specifies the speed at which the volume decreases to the
+ sustain level. Decay is always decreasing exponentially.
+Sl = Sustain level, base level from which sustain starts.
+Sr = Sustain rate is the rate at which the volume of the sustained note
+ increases or decreases. This can be either lineair or exponential.
+Rr = Release rate is the rate at which the volume of the note decreases
+ as soon as the note off is given.
+
+ lvl |
+ ^ | /\Dr __
+ Sl _| _ / _ \__--- \
+ | / ---__ \ Rr
+ | /Ar Sr \ \
+ | / \\
+ |/___________________\________
+ ->time
+
+The overal volume can also be set to sweep up or down lineairly or
+exponentially from it's current value. This can be done seperately
+for left and right.
+
+Relevant SPU registers:
+-------------------------------------------------------------
+$1f801xx8 Attack/Decay/Sustain level
+bit |0f|0e 0d 0c 0b 0a 09 08|07 06 05 04|03 02 01 00|
+desc.|Am| Ar |Dr |Sl |
+
+Am 0 Attack mode Linear
+ 1 Exponential
+
+Ar 0-7f attack rate
+Dr 0-f decay rate
+Sl 0-f sustain level
+-------------------------------------------------------------
+$1f801xxa Sustain rate, Release Rate.
+bit |0f|0e|0d|0c 0b 0a 09 08 07 06|05|04 03 02 01 00|
+desc.|Sm|Sd| 0| Sr |Rm|Rr |
+
+Sm 0 sustain rate mode linear
+ 1 exponential
+Sd 0 sustain rate mode increase
+ 1 decrease
+Sr 0-7f Sustain Rate
+Rm 0 Linear decrease
+ 1 Exponential decrease
+Rr 0-1f Release Rate
+
+Note: decay mode is always Expontial decrease, and thus cannot
+be set.
+-------------------------------------------------------------
+$1f801xxc Current ADSR volume
+bit |0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00|
+desc.|ADSRvol |
+
+ADSRvol Returns the current envelope volume when
+ read.
+-- James' Note: return range: 0 -> 32767
+
+*** doomed doc extract end ***
+
+By using a small PSX proggie to visualise the envelope as it was played,
+the following results for envelope timing were obtained:
+
+1. Attack rate value (linear mode)
+
+ Attack value range: 0 -> 127
+
+ Value | 48 | 52 | 56 | 60 | 64 | 68 | 72 | | 80 |
+ -----------------------------------------------------------------
+ Frames | 11 | 21 | 42 | 84 | 169| 338| 676| |2890|
+
+ Note: frames is no. of PAL frames to reach full volume (100%
+ amplitude)
+
+ Hmm, noticing that the time taken to reach full volume doubles
+ every time we add 4 to our attack value, we know the equation is
+ of form:
+ frames = k * 2 ^ (value / 4)
+
+ (You may ponder about envelope generator hardware at this point,
+ or maybe not... :)
+
+ By substituting some stuff and running some checks, we get:
+
+ k = 0.00257 (close enuf)
+
+ therefore,
+ frames = 0.00257 * 2 ^ (value / 4)
+ If you just happen to be writing an emulator, then you can probably
+ use an equation like:
+
+ %volume_increase_per_tick = 1 / frames
+
+
+ ------------------------------------
+ Pete:
+ ms=((1<<(value>>2))*514)/10000
+ ------------------------------------
+
+2. Decay rate value (only has log mode)
+
+ Decay value range: 0 -> 15
+
+ Value | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
+ ------------------------------------------------
+ frames | | | | | 6 | 12 | 24 | 47 |
+
+ Note: frames here is no. of PAL frames to decay to 50% volume.
+
+ formula: frames = k * 2 ^ (value)
+
+ Substituting, we get: k = 0.00146
+
+ Further info on logarithmic nature:
+ frames to decay to sustain level 3 = 3 * frames to decay to
+ sustain level 9
+
+ Also no. of frames to 25% volume = roughly 1.85 * no. of frames to
+ 50% volume.
+
+ Frag it - just use linear approx.
+
+ ------------------------------------
+ Pete:
+ ms=((1<<value)*292)/10000
+ ------------------------------------
+
+
+3. Sustain rate value (linear mode)
+
+ Sustain rate range: 0 -> 127
+
+ Value | 48 | 52 | 56 | 60 | 64 | 68 | 72 |
+ -------------------------------------------
+ frames | 9 | 19 | 37 | 74 | 147| 293| 587|
+
+ Here, frames = no. of PAL frames for volume amplitude to go from 100%
+ to 0% (or vice-versa).
+
+ Same formula as for attack value, just a different value for k:
+
+ k = 0.00225
+
+ ie: frames = 0.00225 * 2 ^ (value / 4)
+
+ For emulation purposes:
+
+ %volume_increase_or_decrease_per_tick = 1 / frames
+
+ ------------------------------------
+ Pete:
+ ms=((1<<(value>>2))*450)/10000
+ ------------------------------------
+
+
+4. Release rate (linear mode)
+
+ Release rate range: 0 -> 31
+
+ Value | 13 | 14 | 15 | 16 | 17 |
+ ---------------------------------------------------------------
+ frames | 18 | 36 | 73 | 146| 292|
+
+ Here, frames = no. of PAL frames to decay from 100% vol to 0% vol
+ after "note-off" is triggered.
+
+ Formula: frames = k * 2 ^ (value)
+
+ And so: k = 0.00223
+
+ ------------------------------------
+ Pete:
+ ms=((1<<value)*446)/10000
+ ------------------------------------
+
+
+Other notes:
+
+Log stuff not figured out. You may get some clues from the "Decay rate"
+stuff above. For emu purposes it may not be important - use linear
+approx.
+
+To get timings in millisecs, multiply frames by 20.
+
+
+
+- James Higgs 17/6/2000
+james7780@yahoo.com
+
+//---------------------------------------------------------------
+
+OLD adsr mixing according to james' rules... has to be called
+every one millisecond
+
+
+ long v,v2,lT,l1,l2,l3;
+
+ if(spu->s_chan[ch].bStop) // psx wants to stop? -> release phase
+ {
+ if(spu->s_chan[ch].ADSR.ReleaseVal!=0) // -> release not 0: do release (if 0: stop right now)
+ {
+ if(!spu->s_chan[ch].ADSR.ReleaseVol) // --> release just started? set up the release stuff
+ {
+ spu->s_chan[ch].ADSR.ReleaseStartTime=spu->s_chan[ch].ADSR.lTime;
+ spu->s_chan[ch].ADSR.ReleaseVol=spu->s_chan[ch].ADSR.lVolume;
+ spu->s_chan[ch].ADSR.ReleaseTime = // --> calc how long does it take to reach the wanted sus level
+ (spu->s_chan[ch].ADSR.ReleaseTime*
+ spu->s_chan[ch].ADSR.ReleaseVol)/1024;
+ }
+ // -> NO release exp mode used (yet)
+ v=spu->s_chan[ch].ADSR.ReleaseVol; // -> get last volume
+ lT=spu->s_chan[ch].ADSR.lTime- // -> how much time is past?
+ spu->s_chan[ch].ADSR.ReleaseStartTime;
+ l1=spu->s_chan[ch].ADSR.ReleaseTime;
+
+ if(lT<l1) // -> we still have to release
+ {
+ v=v-((v*lT)/l1); // --> calc new volume
+ }
+ else // -> release is over: now really stop that sample
+ {v=0;spu->s_chan[ch].bOn=0;spu->s_chan[ch].ADSR.ReleaseVol=0;spu->s_chan[ch].bNoise=0;}
+ }
+ else // -> release IS 0: release at once
+ {
+ v=0;spu->s_chan[ch].bOn=0;spu->s_chan[ch].ADSR.ReleaseVol=0;spu->s_chan[ch].bNoise=0;
+ }
+ }
+ else
+ {//--------------------------------------------------// not in release phase:
+ v=1024;
+ lT=spu->s_chan[ch].ADSR.lTime;
+ l1=spu->s_chan[ch].ADSR.AttackTime;
+
+ if(lT<l1) // attack
+ { // no exp mode used (yet)
+// if(spu->s_chan[ch].ADSR.AttackModeExp)
+// {
+// v=(v*lT)/l1;
+// }
+// else
+ {
+ v=(v*lT)/l1;
+ }
+ if(v==0) v=1;
+ }
+ else // decay
+ { // should be exp, but who cares? ;)
+ l2=spu->s_chan[ch].ADSR.DecayTime;
+ v2=spu->s_chan[ch].ADSR.SustainLevel;
+
+ lT-=l1;
+ if(lT<l2)
+ {
+ v-=(((v-v2)*lT)/l2);
+ }
+ else // sustain
+ { // no exp mode used (yet)
+ l3=spu->s_chan[ch].ADSR.SustainTime;
+ lT-=l2;
+ if(spu->s_chan[ch].ADSR.SustainModeDec>0)
+ {
+ if(l3!=0) v2+=((v-v2)*lT)/l3;
+ else v2=v;
+ }
+ else
+ {
+ if(l3!=0) v2-=(v2*lT)/l3;
+ else v2=v;
+ }
+
+ if(v2>v) v2=v;
+ if(v2<=0) {v2=0;spu->s_chan[ch].bOn=0;spu->s_chan[ch].ADSR.ReleaseVol=0;spu->s_chan[ch].bNoise=0;}
+
+ v=v2;
+ }
+ }
+ }
+
+ //----------------------------------------------------//
+ // ok, done for this channel, so increase time
+
+ spu->s_chan[ch].ADSR.lTime+=1; // 1 = 1.020408f ms;
+
+ if(v>1024) v=1024; // adjust volume
+ if(v<0) v=0;
+ spu->s_chan[ch].ADSR.lVolume=v; // store act volume
+
+ return v; // return the volume factor
+*/
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+
+/*
+-----------------------------------------------------------------------------
+Neill Corlett
+Playstation SPU envelope timing notes
+-----------------------------------------------------------------------------
+
+This is preliminary. This may be wrong. But the model described herein fits
+all of my experimental data, and it's just simple enough to sound right.
+
+ADSR envelope level ranges from 0x00000000 to 0x7FFFFFFF internally.
+The value returned by channel reg 0xC is (envelope_level>>16).
+
+Each sample, an increment or decrement value will be added to or
+subtracted from this envelope level.
+
+Create the rate log table. The values double every 4 entries.
+ entry #0 = 4
+
+ 4, 5, 6, 7,
+ 8,10,12,14,
+ 16,20,24,28, ...
+
+ entry #40 = 4096...
+ entry #44 = 8192...
+ entry #48 = 16384...
+ entry #52 = 32768...
+ entry #56 = 65536...
+
+increments and decrements are in terms of ratelogtable[n]
+n may exceed the table bounds (plan on n being between -32 and 127).
+table values are all clipped between 0x00000000 and 0x3FFFFFFF
+
+when you "voice on", the envelope is always fully reset.
+(yes, it may click. the real thing does this too.)
+
+envelope level begins at zero.
+
+each state happens for at least 1 cycle
+(transitions are not instantaneous)
+this may result in some oddness: if the decay rate is uberfast, it will cut
+the envelope from full down to half in one sample, potentially skipping over
+the sustain level
+
+ATTACK
+------
+- if the envelope level has overflowed past the max, clip to 0x7FFFFFFF and
+ proceed to DECAY.
+
+Linear attack mode:
+- line extends upward to 0x7FFFFFFF
+- increment per sample is ratelogtable[(Ar^0x7F)-0x10]
+
+Logarithmic attack mode:
+if envelope_level < 0x60000000:
+ - line extends upward to 0x60000000
+ - increment per sample is ratelogtable[(Ar^0x7F)-0x10]
+else:
+ - line extends upward to 0x7FFFFFFF
+ - increment per sample is ratelogtable[(Ar^0x7F)-0x18]
+
+DECAY
+-----
+- if ((envelope_level>>27)&0xF) <= Sl, proceed to SUSTAIN.
+ Do not clip to the sustain level.
+- current line ends at (envelope_level & 0x07FFFFFF)
+- decrement per sample depends on (envelope_level>>28)&0x7
+ 0: ratelogtable[(4*(Dr^0x1F))-0x18+0]
+ 1: ratelogtable[(4*(Dr^0x1F))-0x18+4]
+ 2: ratelogtable[(4*(Dr^0x1F))-0x18+6]
+ 3: ratelogtable[(4*(Dr^0x1F))-0x18+8]
+ 4: ratelogtable[(4*(Dr^0x1F))-0x18+9]
+ 5: ratelogtable[(4*(Dr^0x1F))-0x18+10]
+ 6: ratelogtable[(4*(Dr^0x1F))-0x18+11]
+ 7: ratelogtable[(4*(Dr^0x1F))-0x18+12]
+ (note that this is the same as the release rate formula, except that
+ decay rates 10-1F aren't possible... those would be slower in theory)
+
+SUSTAIN
+-------
+- no terminating condition except for voice off
+- Sd=0 (increase) behavior is identical to ATTACK for both log and linear.
+- Sd=1 (decrease) behavior:
+Linear sustain decrease:
+- line extends to 0x00000000
+- decrement per sample is ratelogtable[(Sr^0x7F)-0x0F]
+Logarithmic sustain decrease:
+- current line ends at (envelope_level & 0x07FFFFFF)
+- decrement per sample depends on (envelope_level>>28)&0x7
+ 0: ratelogtable[(Sr^0x7F)-0x1B+0]
+ 1: ratelogtable[(Sr^0x7F)-0x1B+4]
+ 2: ratelogtable[(Sr^0x7F)-0x1B+6]
+ 3: ratelogtable[(Sr^0x7F)-0x1B+8]
+ 4: ratelogtable[(Sr^0x7F)-0x1B+9]
+ 5: ratelogtable[(Sr^0x7F)-0x1B+10]
+ 6: ratelogtable[(Sr^0x7F)-0x1B+11]
+ 7: ratelogtable[(Sr^0x7F)-0x1B+12]
+
+RELEASE
+-------
+- if the envelope level has overflowed to negative, clip to 0 and QUIT.
+
+Linear release mode:
+- line extends to 0x00000000
+- decrement per sample is ratelogtable[(4*(Rr^0x1F))-0x0C]
+
+Logarithmic release mode:
+- line extends to (envelope_level & 0x0FFFFFFF)
+- decrement per sample depends on (envelope_level>>28)&0x7
+ 0: ratelogtable[(4*(Rr^0x1F))-0x18+0]
+ 1: ratelogtable[(4*(Rr^0x1F))-0x18+4]
+ 2: ratelogtable[(4*(Rr^0x1F))-0x18+6]
+ 3: ratelogtable[(4*(Rr^0x1F))-0x18+8]
+ 4: ratelogtable[(4*(Rr^0x1F))-0x18+9]
+ 5: ratelogtable[(4*(Rr^0x1F))-0x18+10]
+ 6: ratelogtable[(4*(Rr^0x1F))-0x18+11]
+ 7: ratelogtable[(4*(Rr^0x1F))-0x18+12]
+
+-----------------------------------------------------------------------------
+*/
+
diff --git a/plugins/ao/eng_psf/peops2/dma.h b/plugins/ao/eng_psf/peops2/dma.h new file mode 100644 index 00000000..8a68a24a --- /dev/null +++ b/plugins/ao/eng_psf/peops2/dma.h @@ -0,0 +1,29 @@ +/***************************************************************************
+ dma.h - description
+ -------------------
+ begin : Wed May 15 2002
+ copyright : (C) 2002 by Pete Bernert
+ email : BlackDove@addcom.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+//*************************************************************************//
+// History of changes:
+//
+// 2002/05/15 - Pete
+// - generic cleanup for the Peops release
+//
+//*************************************************************************//
+
+void InterruptDMA4(mips_cpu_context *cpu);
+void InterruptDMA7(mips_cpu_context *cpu);
+
diff --git a/plugins/ao/eng_psf/peops2/dma2.c b/plugins/ao/eng_psf/peops2/dma2.c new file mode 100644 index 00000000..6c977429 --- /dev/null +++ b/plugins/ao/eng_psf/peops2/dma2.c @@ -0,0 +1,183 @@ +/*************************************************************************** + dma.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2004/04/04 - Pete +// - changed plugin to emulate PS2 spu +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#include "../peops2/stdafx.h" + +#define _IN_DMA + +#include "../peops2/externals.h" +#include "../peops2/registers.h" +//#include "debug.h" +#include "../psx.h" +#include "../peops2/spu.h" + +//extern uint32 psx_ram[(2*1024*1024)/4]; + +//////////////////////////////////////////////////////////////////////// +// READ DMA (many values) +//////////////////////////////////////////////////////////////////////// + +EXPORT_GCC void CALLBACK SPU2readDMA4Mem(mips_cpu_context *cpu, u32 usPSXMem,int iSize) +{ + spu2_state_t *spu = cpu->spu2; + int i; + u16 *ram16 = (u16 *)&cpu->psx_ram[0]; + + for(i=0;i<iSize;i++) + { + ram16[usPSXMem>>1]=spu->spuMem[spu->spuAddr2[0]]; // spu addr 0 got by writeregister + usPSXMem+=2; + spu->spuAddr2[0]++; // inc spu addr + if(spu->spuAddr2[0]>0xfffff) spu->spuAddr2[0]=0; // wrap + } + + spu->spuAddr2[0]+=0x20; //????? + + + spu->iSpuAsyncWait=0; + + // got from J.F. and Kanodin... is it needed? + spu->regArea[(PS2_C0_ADMAS)>>1]=0; // Auto DMA complete + spu->spuStat2[0]=0x80; // DMA complete +} + +EXPORT_GCC void CALLBACK SPU2readDMA7Mem(mips_cpu_context *cpu, u32 usPSXMem,int iSize) +{ + spu2_state_t *spu = cpu->spu2; + int i; + u16 *ram16 = (u16 *)&cpu->psx_ram[0]; + + for(i=0;i<iSize;i++) + { + ram16[usPSXMem>>1]=spu->spuMem[spu->spuAddr2[1]]; // spu addr 1 got by writeregister + usPSXMem+=2; + spu->spuAddr2[1]++; // inc spu addr + if(spu->spuAddr2[1]>0xfffff) spu->spuAddr2[1]=0; // wrap + } + + spu->spuAddr2[1]+=0x20; //????? + + spu->iSpuAsyncWait=0; + + // got from J.F. and Kanodin... is it needed? + spu->regArea[(PS2_C1_ADMAS)>>1]=0; // Auto DMA complete + spu->spuStat2[1]=0x80; // DMA complete +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +// to investigate: do sound data updates by writedma affect spu +// irqs? Will an irq be triggered, if new data is written to +// the memory irq address? + +//////////////////////////////////////////////////////////////////////// +// WRITE DMA (many values) +//////////////////////////////////////////////////////////////////////// + +EXPORT_GCC void CALLBACK SPU2writeDMA4Mem(mips_cpu_context *cpu, u32 usPSXMem,int iSize) +{ + spu2_state_t *spu = cpu->spu2; + int i; + u16 *ram16 = (u16 *)&cpu->psx_ram[0]; + + for(i=0;i<iSize;i++) + { + spu->spuMem[spu->spuAddr2[0]] = ram16[usPSXMem>>1]; // spu addr 0 got by writeregister + usPSXMem+=2; + spu->spuAddr2[0]++; // inc spu addr + if(spu->spuAddr2[0]>0xfffff) spu->spuAddr2[0]=0; // wrap + } + + spu->iSpuAsyncWait=0; + + // got from J.F. and Kanodin... is it needed? + spu->spuStat2[0]=0x80; // DMA complete +} + +EXPORT_GCC void CALLBACK SPU2writeDMA7Mem(mips_cpu_context *cpu, u32 usPSXMem,int iSize) +{ + spu2_state_t *spu = cpu->spu2; + int i; + u16 *ram16 = (u16 *)&cpu->psx_ram[0]; + + for(i=0;i<iSize;i++) + { + spu->spuMem[spu->spuAddr2[1]] = ram16[usPSXMem>>1]; // spu addr 1 got by writeregister + spu->spuAddr2[1]++; // inc spu addr + if(spu->spuAddr2[1]>0xfffff) spu->spuAddr2[1]=0; // wrap + } + + spu->iSpuAsyncWait=0; + + // got from J.F. and Kanodin... is it needed? + spu->spuStat2[1]=0x80; // DMA complete +} + +//////////////////////////////////////////////////////////////////////// +// INTERRUPTS +//////////////////////////////////////////////////////////////////////// + +void InterruptDMA4(mips_cpu_context *cpu) +{ + spu2_state_t *spu = cpu->spu2; +// taken from linuzappz NULL spu2 +// spu2Rs16(CORE0_ATTR)&= ~0x30; +// spu2Rs16(REG__1B0) = 0; +// spu2Rs16(SPU2_STATX_WRDY_M)|= 0x80; + + spu->spuCtrl2[0]&=~0x30; + spu->regArea[(PS2_C0_ADMAS)>>1]=0; + spu->spuStat2[0]|=0x80; +} + +EXPORT_GCC void CALLBACK SPU2interruptDMA4(mips_cpu_context *cpu) +{ + InterruptDMA4(cpu); +} + +void InterruptDMA7(mips_cpu_context *cpu) +{ + spu2_state_t *spu = cpu->spu2; +// taken from linuzappz NULL spu2 +// spu2Rs16(CORE1_ATTR)&= ~0x30; +// spu2Rs16(REG__5B0) = 0; +// spu2Rs16(SPU2_STATX_DREQ)|= 0x80; + + spu->spuCtrl2[1]&=~0x30; + spu->regArea[(PS2_C1_ADMAS)>>1]=0; + spu->spuStat2[1]|=0x80; +} + +EXPORT_GCC void CALLBACK SPU2interruptDMA7(mips_cpu_context *cpu) +{ + InterruptDMA7(cpu); +} + diff --git a/plugins/ao/eng_psf/peops2/externals.h b/plugins/ao/eng_psf/peops2/externals.h new file mode 100644 index 00000000..67958149 --- /dev/null +++ b/plugins/ao/eng_psf/peops2/externals.h @@ -0,0 +1,307 @@ +/*************************************************************************** + externals.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2004/04/04 - Pete +// - changed plugin to emulate PS2 spu +// +// 2002/04/04 - Pete +// - increased channel struct for interpolation +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#ifndef PEOPS2_EXTERNALS +#define PEOPS2_EXTERNALS + +#include "ao.h" + +//#if LSB_FIRST +//static INLINE u16 BFLIP16(u16 x) +//{ +// return x; +//} +//#else +//static INLINE u16 BFLIP16(u16 x) +//{ +// return( ((x>>8)&0xFF)| ((x&0xFF)<<8) ); +//} +//#endif + +///////////////////////////////////////////////////////// +// generic defines +///////////////////////////////////////////////////////// + +//#define PSE_LT_SPU 4 +//#define PSE_SPU_ERR_SUCCESS 0 +//#define PSE_SPU_ERR -60 +//#define PSE_SPU_ERR_NOTCONFIGURED PSE_SPU_ERR - 1 +//#define PSE_SPU_ERR_INIT PSE_SPU_ERR - 2 + +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +//////////////////////////////////////////////////////////////////////// +// spu defines +//////////////////////////////////////////////////////////////////////// + +// sound buffer sizes +// 400 ms complete sound buffer +#define SOUNDSIZE 76800 +// 137 ms test buffer... if less than that is buffered, a new upload will happen +#define TESTSIZE 26304 + +// num of channels +#define MAXCHAN 48 +#define HLFCHAN 24 + +// ~ 1 ms of data (was 45) +#define NSSIZE 1 +//45 + +/////////////////////////////////////////////////////////// +// struct defines +/////////////////////////////////////////////////////////// + +// ADSR INFOS PER CHANNEL +typedef struct +{ + int AttackModeExp; + long AttackTime; + long DecayTime; + long SustainLevel; + int SustainModeExp; + long SustainModeDec; + long SustainTime; + int ReleaseModeExp; + unsigned long ReleaseVal; + long ReleaseTime; + long ReleaseStartTime; + long ReleaseVol; + long lTime; + long lVolume; +} ADSRInfo; + +typedef struct +{ + int State; + int AttackModeExp; + int AttackRate; + int DecayRate; + int SustainLevel; + int SustainModeExp; + int SustainIncrease; + int SustainRate; + int ReleaseModeExp; + int ReleaseRate; + int EnvelopeVol; + long lVolume; + long lDummy1; + long lDummy2; +} ADSRInfoEx; + +/////////////////////////////////////////////////////////// + +// Tmp Flags + +// used for debug channel muting +#define FLAG_MUTE 1 + +// used for simple interpolation +#define FLAG_IPOL0 2 +#define FLAG_IPOL1 4 + +/////////////////////////////////////////////////////////// + +// MAIN CHANNEL STRUCT +typedef struct +{ + // no mutexes used anymore... don't need them to sync access + //HANDLE hMutex; + + int bNew; // start flag + + int iSBPos; // mixing stuff + int spos; + int sinc; + int SB[32+32]; // Pete added another 32 dwords in 1.6 ... prevents overflow issues with gaussian/cubic interpolation (thanx xodnizel!), and can be used for even better interpolations, eh? :) + int sval; + + unsigned char * pStart; // start ptr into sound mem + unsigned char * pCurr; // current pos in sound mem + unsigned char * pLoop; // loop ptr in sound mem + + int iStartAdr; + int iLoopAdr; + int iNextAdr; + + int bOn; // is channel active (sample playing?) + int bStop; // is channel stopped (sample _can_ still be playing, ADSR Release phase) + int bEndPoint; // end point reached + int bReverbL; // can we do reverb on this channel? must have ctrl register bit, to get active + int bReverbR; + + int bVolumeL; // Volume on/off + int bVolumeR; + + int iActFreq; // current psx pitch + int iUsedFreq; // current pc pitch + int iLeftVolume; // left volume + int iLeftVolRaw; // left psx volume value + int bIgnoreLoop; // ignore loop bit, if an external loop address is used + int iMute; // mute mode + int iRightVolume; // right volume + int iRightVolRaw; // right psx volume value + int iRawPitch; // raw pitch (0...3fff) + int iIrqDone; // debug irq done flag + int s_1; // last decoding infos + int s_2; + int bRVBActive; // reverb active flag + int bNoise; // noise active flag + int bFMod; // freq mod (0=off, 1=sound channel, 2=freq channel) + int iOldNoise; // old noise val for this channel + ADSRInfo ADSR; // active ADSR settings + ADSRInfoEx ADSRX; // next ADSR settings (will be moved to active on sample start) + +} SPUCHAN; + +/////////////////////////////////////////////////////////// + +typedef struct +{ + int StartAddr; // reverb area start addr in samples + int EndAddr; // reverb area end addr in samples + int CurrAddr; // reverb area curr addr in samples + + int VolLeft; + int VolRight; + int iLastRVBLeft; + int iLastRVBRight; + int iRVBLeft; + int iRVBRight; + int iCnt; + + int FB_SRC_A; // (offset) + int FB_SRC_B; // (offset) + int IIR_ALPHA; // (coef.) + int ACC_COEF_A; // (coef.) + int ACC_COEF_B; // (coef.) + int ACC_COEF_C; // (coef.) + int ACC_COEF_D; // (coef.) + int IIR_COEF; // (coef.) + int FB_ALPHA; // (coef.) + int FB_X; // (coef.) + int IIR_DEST_A0; // (offset) + int IIR_DEST_A1; // (offset) + int ACC_SRC_A0; // (offset) + int ACC_SRC_A1; // (offset) + int ACC_SRC_B0; // (offset) + int ACC_SRC_B1; // (offset) + int IIR_SRC_A0; // (offset) + int IIR_SRC_A1; // (offset) + int IIR_DEST_B0; // (offset) + int IIR_DEST_B1; // (offset) + int ACC_SRC_C0; // (offset) + int ACC_SRC_C1; // (offset) + int ACC_SRC_D0; // (offset) + int ACC_SRC_D1; // (offset) + int IIR_SRC_B1; // (offset) + int IIR_SRC_B0; // (offset) + int MIX_DEST_A0; // (offset) + int MIX_DEST_A1; // (offset) + int MIX_DEST_B0; // (offset) + int MIX_DEST_B1; // (offset) + int IN_COEF_L; // (coef.) + int IN_COEF_R; // (coef.) +} REVERBInfo; + +#ifdef _WINDOWS +//extern HINSTANCE hInst; +//#define WM_MUTE (WM_USER+543) +#endif + +/////////////////////////////////////////////////////////// +// SPU.C globals +/////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////// +// CFG.C globals +/////////////////////////////////////////////////////////// + +#ifndef _IN_CFG + +#ifndef _WINDOWS +extern char * pConfigFile; +#endif + +#endif + +/////////////////////////////////////////////////////////// +// DSOUND.C globals +/////////////////////////////////////////////////////////// + +#ifndef _IN_DSOUND + +#ifdef _WINDOWS +extern unsigned long LastWrite; +extern unsigned long LastPlay; +#endif + +#endif + +/////////////////////////////////////////////////////////// +// RECORD.C globals +/////////////////////////////////////////////////////////// + +#ifndef _IN_RECORD + +#ifdef _WINDOWS +extern int iDoRecord; +#endif + +#endif + +/////////////////////////////////////////////////////////// +// XA.C globals +/////////////////////////////////////////////////////////// + +#ifndef _IN_XA + +extern xa_decode_t * xapGlobal; + +extern unsigned long * XAFeed; +extern unsigned long * XAPlay; +extern unsigned long * XAStart; +extern unsigned long * XAEnd; + +extern unsigned long XARepeat; +extern unsigned long XALastVal; + +extern int iLeftXAVol; +extern int iRightXAVol; + +#endif + +#endif // PEOPS2_EXTERNALS diff --git a/plugins/ao/eng_psf/peops2/gauss_i.h b/plugins/ao/eng_psf/peops2/gauss_i.h new file mode 100644 index 00000000..83ecf5b7 --- /dev/null +++ b/plugins/ao/eng_psf/peops2/gauss_i.h @@ -0,0 +1,162 @@ +/***************************************************************************
+ gauss_i.h - description
+ -----------------------
+ begin : Sun Feb 08 2003
+ copyright : (C) 2003 by Chris Moeller, eh, whatever
+ email : chris@kode54.tk
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+//*************************************************************************//
+// History of changes:
+//
+// 2003/02/08 - kode54
+// - generated by interleaving table from gauss.h from the libopenspc
+// project; a gaussian bell curve table logged from the SPC-700,
+// though Neill says he logged the same curve from a PSX SPU. Also
+// says that interleaving the coefficients together runs faster. Meh.
+//
+//*************************************************************************//
+
+#ifndef GAUSS_H
+#define GAUSS_H
+
+static const int gauss[]={
+ 0x172, 0x519, 0x176, 0x000, 0x16E, 0x519, 0x17A, 0x000,
+ 0x16A, 0x518, 0x17D, 0x000, 0x166, 0x518, 0x181, 0x000,
+ 0x162, 0x518, 0x185, 0x000, 0x15F, 0x518, 0x189, 0x000,
+ 0x15B, 0x518, 0x18D, 0x000, 0x157, 0x517, 0x191, 0x000,
+ 0x153, 0x517, 0x195, 0x000, 0x150, 0x517, 0x19A, 0x000,
+ 0x14C, 0x516, 0x19E, 0x000, 0x148, 0x516, 0x1A2, 0x000,
+ 0x145, 0x515, 0x1A6, 0x000, 0x141, 0x514, 0x1AA, 0x000,
+ 0x13E, 0x514, 0x1AE, 0x000, 0x13A, 0x513, 0x1B2, 0x000,
+ 0x137, 0x512, 0x1B7, 0x001, 0x133, 0x511, 0x1BB, 0x001,
+ 0x130, 0x511, 0x1BF, 0x001, 0x12C, 0x510, 0x1C3, 0x001,
+ 0x129, 0x50F, 0x1C8, 0x001, 0x125, 0x50E, 0x1CC, 0x001,
+ 0x122, 0x50D, 0x1D0, 0x001, 0x11E, 0x50C, 0x1D5, 0x001,
+ 0x11B, 0x50B, 0x1D9, 0x001, 0x118, 0x50A, 0x1DD, 0x001,
+ 0x114, 0x508, 0x1E2, 0x001, 0x111, 0x507, 0x1E6, 0x002,
+ 0x10E, 0x506, 0x1EB, 0x002, 0x10B, 0x504, 0x1EF, 0x002,
+ 0x107, 0x503, 0x1F3, 0x002, 0x104, 0x502, 0x1F8, 0x002,
+ 0x101, 0x500, 0x1FC, 0x002, 0x0FE, 0x4FF, 0x201, 0x002,
+ 0x0FB, 0x4FD, 0x205, 0x003, 0x0F8, 0x4FB, 0x20A, 0x003,
+ 0x0F5, 0x4FA, 0x20F, 0x003, 0x0F2, 0x4F8, 0x213, 0x003,
+ 0x0EF, 0x4F6, 0x218, 0x003, 0x0EC, 0x4F5, 0x21C, 0x004,
+ 0x0E9, 0x4F3, 0x221, 0x004, 0x0E6, 0x4F1, 0x226, 0x004,
+ 0x0E3, 0x4EF, 0x22A, 0x004, 0x0E0, 0x4ED, 0x22F, 0x004,
+ 0x0DD, 0x4EB, 0x233, 0x005, 0x0DA, 0x4E9, 0x238, 0x005,
+ 0x0D7, 0x4E7, 0x23D, 0x005, 0x0D4, 0x4E5, 0x241, 0x005,
+ 0x0D2, 0x4E3, 0x246, 0x006, 0x0CF, 0x4E0, 0x24B, 0x006,
+ 0x0CC, 0x4DE, 0x250, 0x006, 0x0C9, 0x4DC, 0x254, 0x006,
+ 0x0C7, 0x4D9, 0x259, 0x007, 0x0C4, 0x4D7, 0x25E, 0x007,
+ 0x0C1, 0x4D5, 0x263, 0x007, 0x0BF, 0x4D2, 0x267, 0x008,
+ 0x0BC, 0x4D0, 0x26C, 0x008, 0x0BA, 0x4CD, 0x271, 0x008,
+ 0x0B7, 0x4CB, 0x276, 0x009, 0x0B4, 0x4C8, 0x27B, 0x009,
+ 0x0B2, 0x4C5, 0x280, 0x009, 0x0AF, 0x4C3, 0x284, 0x00A,
+ 0x0AD, 0x4C0, 0x289, 0x00A, 0x0AB, 0x4BD, 0x28E, 0x00A,
+ 0x0A8, 0x4BA, 0x293, 0x00B, 0x0A6, 0x4B7, 0x298, 0x00B,
+ 0x0A3, 0x4B5, 0x29D, 0x00B, 0x0A1, 0x4B2, 0x2A2, 0x00C,
+ 0x09F, 0x4AF, 0x2A6, 0x00C, 0x09C, 0x4AC, 0x2AB, 0x00D,
+ 0x09A, 0x4A9, 0x2B0, 0x00D, 0x098, 0x4A6, 0x2B5, 0x00E,
+ 0x096, 0x4A2, 0x2BA, 0x00E, 0x093, 0x49F, 0x2BF, 0x00F,
+ 0x091, 0x49C, 0x2C4, 0x00F, 0x08F, 0x499, 0x2C9, 0x00F,
+ 0x08D, 0x496, 0x2CE, 0x010, 0x08B, 0x492, 0x2D3, 0x010,
+ 0x089, 0x48F, 0x2D8, 0x011, 0x086, 0x48C, 0x2DC, 0x011,
+ 0x084, 0x488, 0x2E1, 0x012, 0x082, 0x485, 0x2E6, 0x013,
+ 0x080, 0x481, 0x2EB, 0x013, 0x07E, 0x47E, 0x2F0, 0x014,
+ 0x07C, 0x47A, 0x2F5, 0x014, 0x07A, 0x477, 0x2FA, 0x015,
+ 0x078, 0x473, 0x2FF, 0x015, 0x076, 0x470, 0x304, 0x016,
+ 0x075, 0x46C, 0x309, 0x017, 0x073, 0x468, 0x30E, 0x017,
+ 0x071, 0x465, 0x313, 0x018, 0x06F, 0x461, 0x318, 0x018,
+ 0x06D, 0x45D, 0x31D, 0x019, 0x06B, 0x459, 0x322, 0x01A,
+ 0x06A, 0x455, 0x326, 0x01B, 0x068, 0x452, 0x32B, 0x01B,
+ 0x066, 0x44E, 0x330, 0x01C, 0x064, 0x44A, 0x335, 0x01D,
+ 0x063, 0x446, 0x33A, 0x01D, 0x061, 0x442, 0x33F, 0x01E,
+ 0x05F, 0x43E, 0x344, 0x01F, 0x05E, 0x43A, 0x349, 0x020,
+ 0x05C, 0x436, 0x34E, 0x020, 0x05A, 0x432, 0x353, 0x021,
+ 0x059, 0x42E, 0x357, 0x022, 0x057, 0x42A, 0x35C, 0x023,
+ 0x056, 0x425, 0x361, 0x024, 0x054, 0x421, 0x366, 0x024,
+ 0x053, 0x41D, 0x36B, 0x025, 0x051, 0x419, 0x370, 0x026,
+ 0x050, 0x415, 0x374, 0x027, 0x04E, 0x410, 0x379, 0x028,
+ 0x04D, 0x40C, 0x37E, 0x029, 0x04C, 0x408, 0x383, 0x02A,
+ 0x04A, 0x403, 0x388, 0x02B, 0x049, 0x3FF, 0x38C, 0x02C,
+ 0x047, 0x3FB, 0x391, 0x02D, 0x046, 0x3F6, 0x396, 0x02E,
+ 0x045, 0x3F2, 0x39B, 0x02F, 0x043, 0x3ED, 0x39F, 0x030,
+ 0x042, 0x3E9, 0x3A4, 0x031, 0x041, 0x3E5, 0x3A9, 0x032,
+ 0x040, 0x3E0, 0x3AD, 0x033, 0x03E, 0x3DC, 0x3B2, 0x034,
+ 0x03D, 0x3D7, 0x3B7, 0x035, 0x03C, 0x3D2, 0x3BB, 0x036,
+ 0x03B, 0x3CE, 0x3C0, 0x037, 0x03A, 0x3C9, 0x3C5, 0x038,
+ 0x038, 0x3C5, 0x3C9, 0x03A, 0x037, 0x3C0, 0x3CE, 0x03B,
+ 0x036, 0x3BB, 0x3D2, 0x03C, 0x035, 0x3B7, 0x3D7, 0x03D,
+ 0x034, 0x3B2, 0x3DC, 0x03E, 0x033, 0x3AD, 0x3E0, 0x040,
+ 0x032, 0x3A9, 0x3E5, 0x041, 0x031, 0x3A4, 0x3E9, 0x042,
+ 0x030, 0x39F, 0x3ED, 0x043, 0x02F, 0x39B, 0x3F2, 0x045,
+ 0x02E, 0x396, 0x3F6, 0x046, 0x02D, 0x391, 0x3FB, 0x047,
+ 0x02C, 0x38C, 0x3FF, 0x049, 0x02B, 0x388, 0x403, 0x04A,
+ 0x02A, 0x383, 0x408, 0x04C, 0x029, 0x37E, 0x40C, 0x04D,
+ 0x028, 0x379, 0x410, 0x04E, 0x027, 0x374, 0x415, 0x050,
+ 0x026, 0x370, 0x419, 0x051, 0x025, 0x36B, 0x41D, 0x053,
+ 0x024, 0x366, 0x421, 0x054, 0x024, 0x361, 0x425, 0x056,
+ 0x023, 0x35C, 0x42A, 0x057, 0x022, 0x357, 0x42E, 0x059,
+ 0x021, 0x353, 0x432, 0x05A, 0x020, 0x34E, 0x436, 0x05C,
+ 0x020, 0x349, 0x43A, 0x05E, 0x01F, 0x344, 0x43E, 0x05F,
+ 0x01E, 0x33F, 0x442, 0x061, 0x01D, 0x33A, 0x446, 0x063,
+ 0x01D, 0x335, 0x44A, 0x064, 0x01C, 0x330, 0x44E, 0x066,
+ 0x01B, 0x32B, 0x452, 0x068, 0x01B, 0x326, 0x455, 0x06A,
+ 0x01A, 0x322, 0x459, 0x06B, 0x019, 0x31D, 0x45D, 0x06D,
+ 0x018, 0x318, 0x461, 0x06F, 0x018, 0x313, 0x465, 0x071,
+ 0x017, 0x30E, 0x468, 0x073, 0x017, 0x309, 0x46C, 0x075,
+ 0x016, 0x304, 0x470, 0x076, 0x015, 0x2FF, 0x473, 0x078,
+ 0x015, 0x2FA, 0x477, 0x07A, 0x014, 0x2F5, 0x47A, 0x07C,
+ 0x014, 0x2F0, 0x47E, 0x07E, 0x013, 0x2EB, 0x481, 0x080,
+ 0x013, 0x2E6, 0x485, 0x082, 0x012, 0x2E1, 0x488, 0x084,
+ 0x011, 0x2DC, 0x48C, 0x086, 0x011, 0x2D8, 0x48F, 0x089,
+ 0x010, 0x2D3, 0x492, 0x08B, 0x010, 0x2CE, 0x496, 0x08D,
+ 0x00F, 0x2C9, 0x499, 0x08F, 0x00F, 0x2C4, 0x49C, 0x091,
+ 0x00F, 0x2BF, 0x49F, 0x093, 0x00E, 0x2BA, 0x4A2, 0x096,
+ 0x00E, 0x2B5, 0x4A6, 0x098, 0x00D, 0x2B0, 0x4A9, 0x09A,
+ 0x00D, 0x2AB, 0x4AC, 0x09C, 0x00C, 0x2A6, 0x4AF, 0x09F,
+ 0x00C, 0x2A2, 0x4B2, 0x0A1, 0x00B, 0x29D, 0x4B5, 0x0A3,
+ 0x00B, 0x298, 0x4B7, 0x0A6, 0x00B, 0x293, 0x4BA, 0x0A8,
+ 0x00A, 0x28E, 0x4BD, 0x0AB, 0x00A, 0x289, 0x4C0, 0x0AD,
+ 0x00A, 0x284, 0x4C3, 0x0AF, 0x009, 0x280, 0x4C5, 0x0B2,
+ 0x009, 0x27B, 0x4C8, 0x0B4, 0x009, 0x276, 0x4CB, 0x0B7,
+ 0x008, 0x271, 0x4CD, 0x0BA, 0x008, 0x26C, 0x4D0, 0x0BC,
+ 0x008, 0x267, 0x4D2, 0x0BF, 0x007, 0x263, 0x4D5, 0x0C1,
+ 0x007, 0x25E, 0x4D7, 0x0C4, 0x007, 0x259, 0x4D9, 0x0C7,
+ 0x006, 0x254, 0x4DC, 0x0C9, 0x006, 0x250, 0x4DE, 0x0CC,
+ 0x006, 0x24B, 0x4E0, 0x0CF, 0x006, 0x246, 0x4E3, 0x0D2,
+ 0x005, 0x241, 0x4E5, 0x0D4, 0x005, 0x23D, 0x4E7, 0x0D7,
+ 0x005, 0x238, 0x4E9, 0x0DA, 0x005, 0x233, 0x4EB, 0x0DD,
+ 0x004, 0x22F, 0x4ED, 0x0E0, 0x004, 0x22A, 0x4EF, 0x0E3,
+ 0x004, 0x226, 0x4F1, 0x0E6, 0x004, 0x221, 0x4F3, 0x0E9,
+ 0x004, 0x21C, 0x4F5, 0x0EC, 0x003, 0x218, 0x4F6, 0x0EF,
+ 0x003, 0x213, 0x4F8, 0x0F2, 0x003, 0x20F, 0x4FA, 0x0F5,
+ 0x003, 0x20A, 0x4FB, 0x0F8, 0x003, 0x205, 0x4FD, 0x0FB,
+ 0x002, 0x201, 0x4FF, 0x0FE, 0x002, 0x1FC, 0x500, 0x101,
+ 0x002, 0x1F8, 0x502, 0x104, 0x002, 0x1F3, 0x503, 0x107,
+ 0x002, 0x1EF, 0x504, 0x10B, 0x002, 0x1EB, 0x506, 0x10E,
+ 0x002, 0x1E6, 0x507, 0x111, 0x001, 0x1E2, 0x508, 0x114,
+ 0x001, 0x1DD, 0x50A, 0x118, 0x001, 0x1D9, 0x50B, 0x11B,
+ 0x001, 0x1D5, 0x50C, 0x11E, 0x001, 0x1D0, 0x50D, 0x122,
+ 0x001, 0x1CC, 0x50E, 0x125, 0x001, 0x1C8, 0x50F, 0x129,
+ 0x001, 0x1C3, 0x510, 0x12C, 0x001, 0x1BF, 0x511, 0x130,
+ 0x001, 0x1BB, 0x511, 0x133, 0x001, 0x1B7, 0x512, 0x137,
+ 0x000, 0x1B2, 0x513, 0x13A, 0x000, 0x1AE, 0x514, 0x13E,
+ 0x000, 0x1AA, 0x514, 0x141, 0x000, 0x1A6, 0x515, 0x145,
+ 0x000, 0x1A2, 0x516, 0x148, 0x000, 0x19E, 0x516, 0x14C,
+ 0x000, 0x19A, 0x517, 0x150, 0x000, 0x195, 0x517, 0x153,
+ 0x000, 0x191, 0x517, 0x157, 0x000, 0x18D, 0x518, 0x15B,
+ 0x000, 0x189, 0x518, 0x15F, 0x000, 0x185, 0x518, 0x162,
+ 0x000, 0x181, 0x518, 0x166, 0x000, 0x17D, 0x518, 0x16A,
+ 0x000, 0x17A, 0x519, 0x16E, 0x000, 0x176, 0x519, 0x172};
+#endif
diff --git a/plugins/ao/eng_psf/peops2/psemuxa.h b/plugins/ao/eng_psf/peops2/psemuxa.h new file mode 100755 index 00000000..84c62604 --- /dev/null +++ b/plugins/ao/eng_psf/peops2/psemuxa.h @@ -0,0 +1,28 @@ +//============================================
+//=== Audio XA decoding
+//=== Kazzuya
+//============================================
+
+#ifndef DECODEXA_H
+#define DECODEXA_H
+
+typedef struct
+{
+ long y0, y1;
+} ADPCM_Decode_t;
+
+typedef struct
+{
+ int freq;
+ int nbits;
+ int stereo;
+ int nsamples;
+ ADPCM_Decode_t left, right;
+ short pcm[16384];
+} xa_decode_t;
+
+long xa_decode_sector( xa_decode_t *xdp,
+ unsigned char *sectorp,
+ int is_first_sector );
+
+#endif
diff --git a/plugins/ao/eng_psf/peops2/registers.h b/plugins/ao/eng_psf/peops2/registers.h new file mode 100644 index 00000000..75e1c395 --- /dev/null +++ b/plugins/ao/eng_psf/peops2/registers.h @@ -0,0 +1,845 @@ +/***************************************************************************
+ registers.h - description
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+//*************************************************************************//
+// History of changes:
+//
+// 2004/04/04 - Pete
+// - generic cleanup for the Peops release... register values by Kanodin &
+// his team
+//
+//*************************************************************************//
+
+//###########################################################################
+
+#define PS2_C0_SPUaddr_Hi (0x000 + 0x1A8)
+#define PS2_C0_SPUaddr_Lo (0x000 + 0x1AA)
+#define PS2_C1_SPUaddr_Hi (0x400 + 0x1A8)
+#define PS2_C1_SPUaddr_Lo (0x400 + 0x1AA)
+#define PS2_C0_SPUdata (0x000 + 0x1AC)
+#define PS2_C1_SPUdata (0x400 + 0x1AC)
+
+#define PS2_C0_SPUDMActrl (0x000 + 0x1AE)
+#define PS2_C1_SPUDMActrl (0x400 + 0x1AE)
+
+#define PS2_C0_SPUstat (0x000 + 0x344)
+#define PS2_C1_SPUstat (0x400 + 0x344)
+#define PS2_C0_ReverbAddr_Hi (0x000 + 0x2E0)
+#define PS2_C0_ReverbAddr_Lo (0x000 + 0x2E2)
+#define PS2_C1_ReverbAddr_Hi (0x400 + 0x2E0)
+#define PS2_C1_ReverbAddr_Lo (0x400 + 0x2E2)
+
+#define PS2_C0_ReverbAEnd_Hi (0x000 + 0x33C)
+#define PS2_C0_ReverbAEnd_Lo (0x000 + 0x33E)
+#define PS2_C1_ReverbAEnd_Hi (0x400 + 0x33C)
+#define PS2_C1_ReverbAEnd_Lo (0x400 + 0x33E)
+
+#define PS2_C0_DryL1 (0x000 + 0x188)
+#define PS2_C1_DryL1 (0x400 + 0x188)
+#define PS2_C0_DryL2 (0x000 + 0x18A)
+#define PS2_C1_DryL2 (0x400 + 0x18A)
+
+#define PS2_C0_DryR1 (0x000 + 0x190)
+#define PS2_C1_DryR1 (0x400 + 0x190)
+#define PS2_C0_DryR2 (0x000 + 0x192)
+#define PS2_C1_DryR2 (0x400 + 0x192)
+
+#define PS2_C0_ATTR (0x000 + 0x19A)
+#define PS2_C1_ATTR (0x400 + 0x19A)
+#define PS2_C0_ADMAS (0x000 + 0x1B0)
+#define PS2_C1_ADMAS (0x400 + 0x1B0)
+
+#define PS2_C0_SPUirqAddr_Hi (0x000 + 0x19C)
+#define PS2_C0_SPUirqAddr_Lo (0x000 + 0x19D)
+#define PS2_C1_SPUirqAddr_Hi (0x400 + 0x19C)
+#define PS2_C1_SPUirqAddr_Lo (0x400 + 0x19D)
+#define PS2_C0_SPUrvolL (0x000 + 0x764)
+#define PS2_C0_SPUrvolR (0x000 + 0x766)
+#define PS2_C1_SPUrvolL (0x028 + 0x764)
+#define PS2_C1_SPUrvolR (0x028 + 0x766)
+#define PS2_C0_SPUon1 (0x000 + 0x1A0)
+#define PS2_C0_SPUon2 (0x000 + 0x1A2)
+#define PS2_C1_SPUon1 (0x400 + 0x1A0)
+#define PS2_C1_SPUon2 (0x400 + 0x1A2)
+#define PS2_C0_SPUoff1 (0x000 + 0x1A4)
+#define PS2_C0_SPUoff2 (0x000 + 0x1A6)
+#define PS2_C1_SPUoff1 (0x400 + 0x1A4)
+#define PS2_C1_SPUoff2 (0x400 + 0x1A6)
+#define PS2_C0_FMod1 (0x000 + 0x180)
+#define PS2_C0_FMod2 (0x000 + 0x182)
+#define PS2_C1_FMod1 (0x400 + 0x180)
+#define PS2_C1_FMod2 (0x400 + 0x182)
+#define PS2_C0_Noise1 (0x000 + 0x184)
+#define PS2_C0_Noise2 (0x000 + 0x186)
+#define PS2_C1_Noise1 (0x400 + 0x184)
+#define PS2_C1_Noise2 (0x400 + 0x186)
+
+#define PS2_C0_RVBon1_L (0x000 + 0x18C)
+#define PS2_C0_RVBon2_L (0x000 + 0x18E)
+#define PS2_C0_RVBon1_R (0x000 + 0x194)
+#define PS2_C0_RVBon2_R (0x000 + 0x196)
+
+#define PS2_C1_RVBon1_L (0x400 + 0x18C)
+#define PS2_C1_RVBon2_L (0x400 + 0x18E)
+#define PS2_C1_RVBon1_R (0x400 + 0x194)
+#define PS2_C1_RVBon2_R (0x400 + 0x196)
+#define PS2_C0_Reverb (0x000 + 0x2E4)
+#define PS2_C1_Reverb (0x400 + 0x2E4)
+#define PS2_C0_ReverbX (0x000 + 0x774)
+#define PS2_C1_ReverbX (0x028 + 0x774)
+#define PS2_C0_SPUend1 (0x000 + 0x340)
+#define PS2_C0_SPUend2 (0x000 + 0x342)
+#define PS2_C1_SPUend1 (0x400 + 0x340)
+#define PS2_C1_SPUend2 (0x400 + 0x342)
+
+#define H_SPUReverbAddr 0x0da2
+
+#define H_SPUirqAddr 0x0da4
+
+#define H_SPUaddr 0x0da6
+
+#define H_SPUdata 0x0da8
+
+#define H_SPUctrl 0x0daa
+
+#define H_SPUstat 0x0dae
+
+#define H_SPUmvolL 0x0d80
+
+#define H_SPUmvolR 0x0d82
+
+#define H_SPUrvolL 0x0d84
+
+#define H_SPUrvolR 0x0d86
+
+#define H_SPUon1 0x0d88
+
+#define H_SPUon2 0x0d8a
+
+#define H_SPUoff1 0x0d8c
+
+#define H_SPUoff2 0x0d8e
+
+#define H_FMod1 0x0d90
+
+#define H_FMod2 0x0d92
+
+#define H_Noise1 0x0d94
+
+#define H_Noise2 0x0d96
+
+#define H_RVBon1 0x0d98
+
+#define H_RVBon2 0x0d9a
+#define H_SPUMute1 0x0d9c
+#define H_SPUMute2 0x0d9e
+#define H_CDLeft 0x0db0
+#define H_CDRight 0x0db2
+#define H_ExtLeft 0x0db4
+#define H_ExtRight 0x0db6
+#define H_Reverb 0x0dc0
+
+
+//###########################################################################
+
+/*
+ Included the info received in Regs.txt list by Neill Corlett - Kanodin
+
+ Voice parameters:
+ SD_VP_VOLL, SD_VP_VOLR - Volume left/right per voice. Assuming identical to PS1.
+ SD_VP_PITCH - Pitch scaler 0000-3FFF. Assuming identical to PS1.
+ SD_VP_ADSR1, SD_VP_ADSR1 - Envelope data. Bitfields are documented as identical to PS1.
+ SD_VP_ENVX - Current envelope value. Assuming identical to PS1.
+ SD_VP_VOLXL, SD_VP_VOLXR - Current voice volume left/right. Does not exist on the PS1.
+ Guessing that this is handy for the increase/decrease modes.
+
+ Voice addresses:
+
+ SD_VA_SSA - Sample start address; assuming identical to PS1
+ SD_VA_LSAX - Loop start address; assuming identical to PS1
+ SD_VA_NAX - Seems to be documented as the current playing address.
+ Does not exist on PS1.
+
+ Switches:
+
+ SD_S_PMON - Pitch mod; assuming identical to PS1
+ SD_S_NON - Noise; assuming identical to PS1
+ SD_S_VMIXL, SD_S_VMIXR - Voice mix L/R. Guessing this is just a separate L/R version
+ of the "voice enable" bits on the PS1.
+ SD_S_VMIXEL, SD_S_VMIXER - Voice effect mix L/R. Guessing this is just a separate L/R
+ version of the "voice reverb enable" bits on the PS1.
+ SD_S_KON, SD_S_KOFF - Key on/off; assuming identical to PS1
+
+
+ Addresses:
+
+ SD_A_TSA - Transfer start address; assuming identical to PS1
+ SD_A_ESA - Effect start address - this is probably analogous to the
+ PS1's reverb work area start address
+ SD_A_EEA - Effect end address - this would've been fixed to 0x7FFFF on
+ the PS1; settable in 128K increments on the PS2.
+ SD_A_IRQA - IRQ address; assuming identical to PS1
+
+ Volume parameters:
+
+ SD_P_MVOLL, SD_P_MVOLR - Master volume L/R; assuming identical to PS1
+ SD_P_EVOLL, SD_P_EVOLR - Effect volume L/R; assuming analogous to RVOL on the PS1
+ SD_P_AVOLL, SD_P_AVOLR - External input volume L/R
+ This is probably where CORE0 connects to CORE1
+ SD_P_BVOLL, SD_P_BVOLR - Sound data input volume - perhaps this is the volume of
+ the raw PCM auto-DMA input? analogous to CD input volume?
+ SD_P_MVOLXL, SD_P_MVOLXR - Current master volume L/R; seems self-explanatory
+
+ SD_P_MMIX - Mixer / effect enable bits.
+ bit 11 = MSNDL = voice output dry L
+ 10 = MSNDR = voice output dry R
+ 9 = MSNDEL = voice output wet L
+ 8 = MSNDER = voice output wet R
+ 7 = MINL = sound data input dry L
+ 6 = MINR = sound data input dry R
+ 5 = MINEL = sound data input wet L
+ 4 = MINER = sound data input wet R
+ 3 = SINL = core external input dry L
+ 2 = SINR = core external input dry R
+ 1 = SINEL = core external input wet L
+ 0 = SINER = core external input wet R
+
+Core attributes (SD_C)
+
+ bit 4..5 - DMA related
+ bit 6 - IRQ enable
+ bit 7 - effect enable (reverb enable)
+ bit 13..8 - noise clock
+ bit 14 - mute
+
+ - if you READ the two DMA related bits, if either are set, the channel is
+ considered "busy" by sceSdVoiceTrans
+
+
+
+Reverb parameters:
+
+ Same as PS1 reverb (I used the names from my reverb doc).
+
+
+Other PS2 IOP notes
+
+ There's two DMA controllers:
+ The original one at 1F801080-1F8010FF (channels 0-6)
+ A new one at 1F801500-1F80157F (channels 7-13)
+
+ They appear to function the same way - 7 channels each.
+
+ SPU CORE0's DMA channel is 4 as per usual
+ SPU CORE1's DMA channel is 7
+
+DMA channel 10 is SIF
+
+ Original INTR controller at 1F801000-1F80107F
+
+ All interrupt handling seems to be done using the old INTR, but
+ with some new bits defined:
+
+
+
+ Reading from 1F801078 masks interrupts and returns 1 if they weren't
+ masked before. Writing 1 to 1F801078 re-enables interrupts.
+ Writing 0 doesn't. Maybe it was like that on the original PS1 too.
+
+Six root counters:
+
+ RTC# address sources size prescale interrupt#
+0 0x1F801100 sysclock,pixel 16 bit 1 only 4
+1 0x1F801110 sysclock,hline 16 bit 1 only 5
+2 0x1F801120 sysclock 16 bit 1,8 6
+3 0x1F801480 sysclock,hline 32 bit 1 only 14
+4 0x1F801490 sysclock 32 bit 1,8,16,256 15
+5 0x1F8014A0 sysclock 32 bit 1,8,16,256 16
+
+Count (0x0) and Compare (0x8) registers work as before, only with more bits
+in the new counters.
+
+Mode (0x4) works like this when written:
+
+ bits 0..2 gate
+ bit 3 reset on target
+ bit 4 target interrupt enable
+ bit 5 overflow interrupt enable
+ bit 6 master enable (?)
+ bit 7 ?
+ bit 8 clock select
+ bit 9 prescale (OLD)
+ bit 10..12 ?
+ bit 13..14 prescale (NEW)
+ bit 15 ? always set to 1
+
+Gate:
+ TM_NO_GATE 000
+ TM_GATE_ON_Count 001
+ TM_GATE_ON_ClearStart 011
+ TM_GATE_ON_Clear_OFF_Start 101
+ TM_GATE_ON_Start 111
+
+ V-blank ----+ +----------------------------+ +------
+ | | | |
+ | | | |
+ +----+ +----+
+ TM_NO_GATE:
+
+ 0================================>============
+
+ TM_GATE_ON_Count:
+
+ <---->0==========================><---->0=====
+
+ TM_GATE_ON_ClearStart:
+
+ 0====>0================================>0=====
+
+ TM_GATE_ON_Clear_OFF_Start:
+
+ 0====><-------------------------->0====><-----
+
+ TM_GATE_ON_Start:
+
+ <---->0==========================>============
+
+ reset on target: if set, counter resets to 0 when Compare value is reached
+
+ target interrupt enable: if set, interrupt when Compare value is reached
+ overflow interrupt enable: if set, interrupt when counter overflows
+
+ master enable: if this bit is clear, the timer should do nothing.
+
+ clock select: for counters 0, 1, and 3, setting this will select the alternate
+ counter (pixel or hline)
+
+ prescale (OLD): for counter 2 only. set this to prescale (divide) by 8.
+
+ prescale (NEW): for counters 4 and 5 only:
+
+ 00 = prescale by 1
+ 01 = prescale by 8
+ 10 = prescale by 16
+ 11 = prescale by 256
+
+Writing 0x4 also clears the counter. (I think.)
+
+When 0x4 is read, it becomes Status:
+
+ bit 0..10 ?
+ bit 11 compare value was reached
+ bit 12 count overflowed
+ bit 13..15 ?
+
+Reading probably clears these bits.
+
+
+
+ 1F8014B0 (word) - timer-related but otherwise unknown
+ 1F8014C0 (word) - timer-related but otherwise unknown
+
+
+ don't currently know how the interrupts work for DMA ch7 yet
+
+ 1F801060 (word) - address of some kind.
+
+ 1F801450 (word) -
+ if bit 3 is SET, we're in PS1 mode.
+ if bit 3 is CLEAR, we're in PS2 IOP mode.
+
+ 1F802070 (byte) - unknown. status byte of some kind? visible to EE?
+
+ 1D000000-1D00007F (?) - SIF related
+
+ 1D000020 (word) - read counter of some sort?
+ sceSifInit waits for bit 0x10000 of this to be set.
+ 1D000030 (word) - read counter of some sort?
+ 1D000040 (word) - read bits 0x20, 0x40 mean something
+ 1D000060 (word) - used to detect whether the SIF interface exists
+ read must be 0x1D000060, or the top 20 bits must be zero
+*/
+
+/*
+
+// DirectX Audio SPU2 Driver for PCSX2
+// audio.c by J.F. and Kanodin (hooper1@cox.net)
+//
+// Copyright 2003 J.F. and Kanodin, and distributed under the
+// terms of the GNU General Public License, v2 or later.
+// http://www.gnu.org/copyleft/gpl.html.
+
+Included these just in case you need them J.F. - Kanodin
+
+// Core Start Addresses
+#define CORE0 0x1f900000
+#define CORE1 0x1f900400
+
+
+ #define IOP_INT_VBLANK (1<<0)
+ #define IOP_INT_GM (1<<1)
+ #define IOP_INT_CDROM (1<<2)
+ #define IOP_INT_DMA (1<<3)
+ #define IOP_INT_RTC0 (1<<4)
+ #define IOP_INT_RTC1 (1<<5)
+ #define IOP_INT_RTC2 (1<<6)
+ #define IOP_INT_SIO0 (1<<7)
+ #define IOP_INT_SIO1 (1<<8)
+ #define IOP_INT_SPU (1<<9)
+ #define IOP_INT_PIO (1<<10)
+ #define IOP_INT_EVBLANK (1<<11)
+ #define IOP_INT_DVD (1<<12)
+ #define IOP_INT_PCMCIA (1<<13)
+ #define IOP_INT_RTC3 (1<<14)
+ #define IOP_INT_RTC4 (1<<15)
+ #define IOP_INT_RTC5 (1<<16)
+ #define IOP_INT_SIO2 (1<<17)
+ #define IOP_INT_HTR0 (1<<18)
+ #define IOP_INT_HTR1 (1<<19)
+ #define IOP_INT_HTR2 (1<<20)
+ #define IOP_INT_HTR3 (1<<21)
+ #define IOP_INT_USB (1<<22)
+ #define IOP_INT_EXTR (1<<23)
+ #define IOP_INT_FWRE (1<<24)
+ #define IOP_INT_FDMA (1<<25)
+
+// CORE0 => +0x000, CORE1 => +0x400
+
+// individual voice parameter regs
+
+#define VP_VOLL(cr, vc) (0x400 * cr + 0x000 + (vc << 4)) // voice volume (left)
+#define VP_VOLR(cr, vc) (0x400 * cr + 0x002 + (vc << 4)) // voice volume (right)
+#define VP_PITCH(cr, vc) (0x400 * cr + 0x004 + (vc << 4)) // voice pitch
+#define VP_ADSR1(cr, vc) (0x400 * cr + 0x006 + (vc << 4)) // voice envelope (AR, DR, SL)
+#define VP_ADSR2(cr, vc) (0x400 * cr + 0x008 + (vc << 4)) // voice envelope (SR, RR)
+#define VP_ENVX(cr, vc) (0x400 * cr + 0x00A + (vc << 4)) // voice envelope (current value)
+#define VP_VOLXL(cr, vc) (0x400 * cr + 0x00C + (vc << 4)) // voice volume (current value left)
+#define VP_VOLXR(cr, vc) (0x400 * cr + 0x00E + (vc << 4)) // voice volume (current value right)
+
+#define VA_SSA(cr, vc) (0x400 * cr + 0x1C0 + (vc * 12)) // voice waveform data start address
+#define VA_LSAX(cr, vc) (0x400 * cr + 0x1C4 + (vc * 12)) // voice waveform data loop address
+#define VA_NAX(cr, vc) (0x400 * cr + 0x1C8 + (vc * 12)) // voice waveform data next address
+
+// common settings
+
+#define S_PMON(cr) (0x400 * cr + 0x180) // pitch modulation on
+#define S_NON(cr) (0x400 * cr + 0x184) // noise generator on
+#define S_VMIXL(cr) (0x400 * cr + 0x188) // voice output mixing (dry left)
+#define S_VMIXEL(cr) (0x400 * cr + 0x18C) // voice output mixing (wet left)
+#define S_VMIXR(cr) (0x400 * cr + 0x190) // voice output mixing (dry right)
+#define S_VMIXER(cr) (0x400 * cr + 0x194) // voice output mixing (wet right)
+#define P_MMIX(cr) (0x400 * cr + 0x198) // output type after voice mixing (See paragraph below)
+#define P_ATTR(cr) (0x400 * cr + 0x19A) // core attributes (See paragraph below)
+#define A_IRQA(cr) (0x400 * cr + 0x19C) // IRQ address
+#define S_KON(cr) (0x400 * cr + 0x1A0) // key on (start voice sound generation)
+#define S_KOFF(cr) (0x400 * cr + 0x1A4) // key off (end voice sound generation)
+#define A_TSA(cr) (0x400 * cr + 0x1A8) // DMA transfer start address
+#define P_DATA(cr) (0x400 * cr + 0x1AC) // DMA data register
+#define P_CTRL(cr) (0x400 * cr + 0x1AE) // DMA control register
+#define P_ADMAS(cr) (0x400 * cr + 0x1B0) // AutoDMA status
+
+#define A_ESA(cr) (0x400 * cr + 0x2E0) // effects work area start address
+
+#define FB_SRC_A(cr) (0x400 * cr + 0x2E4)
+#define FB_SRC_B(cr) (0x400 * cr + 0x2E8)
+#define IIR_DEST_A0(cr) (0x400 * cr + 0x2EC)
+#define IIR_DEST_A1(cr) (0x400 * cr + 0x2F0)
+#define ACC_SRC_A0(cr) (0x400 * cr + 0x2F4)
+#define ACC_SRC_A1(cr) (0x400 * cr + 0x2F8)
+#define ACC_SRC_B0(cr) (0x400 * cr + 0x2FC)
+
+#define ACC_SRC_B1(cr) (0x400 * cr + 0x300)
+#define IIR_SRC_A0(cr) (0x400 * cr + 0x304)
+#define IIR_SRC_A1(cr) (0x400 * cr + 0x308)
+#define IIR_DEST_B0(cr) (0x400 * cr + 0x30C)
+#define IIR_DEST_B1(cr) (0x400 * cr + 0x310)
+#define ACC_SRC_C0(cr) (0x400 * cr + 0x314)
+#define ACC_SRC_C1(cr) (0x400 * cr + 0x318)
+
+#define ACC_SRC_D0(cr) (0x400 * cr + 0x31C)
+#define ACC_SRC_D1(cr) (0x400 * cr + 0x320)
+#define IIR_SRC_B1(cr) (0x400 * cr + 0x324)
+#define IIR_SRC_B0(cr) (0x400 * cr + 0x328)
+#define MIX_DEST_A0(cr) (0x400 * cr + 0x32C)
+#define MIX_DEST_A1(cr) (0x400 * cr + 0x330)
+#define MIX_DEST_B0(cr) (0x400 * cr + 0x334)
+#define MIX_DEST_B1(cr) (0x400 * cr + 0x338)
+
+#define A_EEA(cr) (0x400 * cr + 0x33C) // effects work area end address
+
+#define P_ENDX(cr) (0x400 * cr + 0x340) // voice loop end status
+#define P_STAT(cr) (0x400 * cr + 0x344) // DMA status register
+#define P_ENDS(cr) (0x400 * cr + 0x346) // ?
+
+// CORE0 => +0x400, CORE1 => +0x428
+
+#define P_MVOLL(cr) (0x28 * cr + 0x760) // master volume (left)
+#define P_MVOLR(cr) (0x28 * cr + 0x762) // master volume (right)
+#define P_EVOLL(cr) (0x28 * cr + 0x764) // effect return volume (left)
+#define P_EVOLR(cr) (0x28 * cr + 0x766) // effect return volume (right)
+#define P_AVOLL(cr) (0x28 * cr + 0x768) // core external input volume (left)
+#define P_AVOLR(cr) (0x28 * cr + 0x76A) // core external input volume (right)
+#define P_BVOLL(cr) (0x28 * cr + 0x76C) // sound data input volume (left)
+#define P_BVOLR(cr) (0x28 * cr + 0x76E) // sound data input volume (right)
+#define P_MVOLXL(cr) (0x28 * cr + 0x770) // current master volume (left)
+#define P_MVOLXR(cr) (0x28 * cr + 0x772) // current master volume (right)
+
+#define IIR_ALPHA(cr) (0x28 * cr + 0x774)
+#define ACC_COEF_A(cr) (0x28 * cr + 0x776)
+#define ACC_COEF_B(cr) (0x28 * cr + 0x778)
+#define ACC_COEF_C(cr) (0x28 * cr + 0x77A)
+#define ACC_COEF_D(cr) (0x28 * cr + 0x77C)
+#define IIR_COEF(cr) (0x28 * cr + 0x77E)
+#define FB_ALPHA(cr) (0x28 * cr + 0x780)
+#define FB_X(cr) (0x28 * cr + 0x782)
+#define IN_COEF_L(cr) (0x28 * cr + 0x784)
+#define IN_COEF_R(cr) (0x28 * cr + 0x786)
+
+// CORE1 only => +0x400
+
+#define SPDIF_OUT 0x7C0 // SPDIF Out: OFF/'PCM'/Bitstream/Bypass
+#define SPDIF_MODE 0x7C6
+#define SPDIF_MEDIA 0x7C8 // SPDIF Media: 'CD'/DVD
+#define SPDIF_COPY 0x7CA // SPDIF Copy Protection
+
+// PS1 SPU CORE
+
+// individual voice settings
+
+#define SPU_VP_PITCH(vc) (0xC04 + (vc << 4)) // voice pitch
+#define SPU_VA_SSA(vc) (0xC06 + (vc << 4)) // voice waveform data start address
+#define SPU_VP_ADSR(vc) (0xC08 + (vc << 4)) // voice envelope
+#define SPU_VA_SSA(vc) (0xC0E + (vc << 4)) // voice waveform data loop address
+
+// common settings
+
+#define SPU_P_MVOLL 0xD80 // master volume (left)
+#define SPU_P_MVOLR 0xD82 // master volume (right)
+#define SPU_P_RVOLL 0xD84 // effect return volume (left)
+#define SPU_P_RVOLR 0xD86 // effect return volume (right)
+#define SPU_S_KON1 0xD88 // key on
+#define SPU_S_KON2 0xD8A //
+#define SPU_S_KOFF1 0xD8C // key off
+#define SPU_S_KOFF2 0xD8E //
+#define SPU_S_PMON1 0xD90 // pitch modulation on
+#define SPU_S_PMON2 0xD92 //
+#define SPU_S_NON1 0xD94 // noise generator on
+#define SPU_S_NON2 0xD96 //
+#define SPU_S_RVBON1 0xD98 // effects on
+#define SPU_S_RVBON2 0xD9A //
+#define SPU_S_MUTE1 0xD9C // voice mute
+#define SPU_S_MUTE2 0xD9E //
+
+#define SPU_A_ESA 0xDA2 // effects work area start
+#define SPU_A_IRQA 0xDA4 // IRQ address
+#define SPU_A_TSA 0xDA6 // DMA transfer start address
+#define SPU_P_DATA 0xDA8 // DMA data register
+#define SPU_P_CTRL 0xDAA // DMA control register
+#define SPU_P_STAT 0xDAE // DMA status register
+
+#define SPU_P_CDL 0xDB0 // sound data input volume (left)
+#define SPU_P_CDR 0xDB2 // sound data input volume (right)
+#define SPU_P_EXTL 0xDB4 // external input volume (left)
+#define SPU_P_EXTR 0xDB6 // external input volume (right)
+
+#define SPU_P_REVERB 0xDC0 // effects control
+
+
+// Individual voice parameter regs CORE 0
+// Only
+
+
+#define VP_VOLL(cr, vc) (0x400 * cr + 0x000 + (vc << 4)) // voice volume (left)
+#define VP_VOLR(cr, vc) (0x400 * cr + 0x002 + (vc << 4)) // voice volume (right)
+#define VP_PITCH(cr, vc) (0x400 * cr + 0x004 + (vc << 4)) // voice pitch
+#define VP_ADSR1(cr, vc) (0x400 * cr + 0x006 + (vc << 4)) // voice envelope (AR, DR, SL)
+#define VP_ADSR2(cr, vc) (0x400 * cr + 0x008 + (vc << 4)) // voice envelope (SR, RR)
+#define VP_ENVX(cr, vc) (0x400 * cr + 0x00A + (vc << 4)) // voice envelope (current value)
+#define VP_VOLXL(cr, vc) (0x400 * cr + 0x00C + (vc << 4)) // voice volume (current value left)
+#define VP_VOLXR(cr, vc) (0x400 * cr + 0x00E + (vc << 4)) // voice volume (current value right)
+
+#define VA_SSA(cr, vc) (0x400 * cr + 0x1C0 + (vc * 12)) // voice waveform data start address
+#define VA_LSAX(cr, vc) (0x400 * cr + 0x1C4 + (vc * 12)) // voice waveform data loop address
+#define VA_NAX(cr, vc) (0x400 * cr + 0x1C8 + (vc * 12)) // voice waveform data next address
+
+
+// CORE 0 Common Settings
+
+
+#define S_PMON(cr) (0x400 * cr + 0x180) // pitch modulation on
+#define S_NON(cr) (0x400 * cr + 0x184) // noise generator on
+#define S_VMIXL(cr) (0x400 * cr + 0x188) // voice output mixing (dry left)
+#define S_VMIXEL(cr) (0x400 * cr + 0x18C) // voice output mixing (wet left)
+#define S_VMIXR(cr) (0x400 * cr + 0x190) // voice output mixing (dry right)
+#define S_VMIXER(cr) (0x400 * cr + 0x194) // voice output mixing (wet right)
+#define P_MMIX(cr) (0x400 * cr + 0x198) // output type after voice mixing (See paragraph below)
+#define P_ATTR(cr) (0x400 * cr + 0x19A) // core attributes (See paragraph below)
+#define A_IRQA(cr) (0x400 * cr + 0x19C) // IRQ address
+#define S_KON(cr) (0x400 * cr + 0x1A0) // key on (start voice sound generation)
+#define S_KOFF(cr) (0x400 * cr + 0x1A4) // key off (end voice sound generation)
+#define A_TSA(cr) (0x400 * cr + 0x1A8) // DMA transfer start address
+#define P_DATA(cr) (0x400 * cr + 0x1AC) // DMA data register
+#define P_CTRL(cr) (0x400 * cr + 0x1AE) // DMA control register
+#define P_ADMAS(cr) (0x400 * cr + 0x1B0) // AutoDMA status
+
+#define A_ESA(cr) (0x400 * cr + 0x2E0) // effects work area start address
+
+
+// Core 0 Reverb Addresses
+
+
+#define FB_SRC_A(cr) (0x400 * cr + 0x2E4)
+#define FB_SRC_B(cr) (0x400 * cr + 0x2E8)
+#define IIR_DEST_A0(cr) (0x400 * cr + 0x2EC)
+#define IIR_DEST_A1(cr) (0x400 * cr + 0x2F0)
+#define ACC_SRC_A0(cr) (0x400 * cr + 0x2F4)
+#define ACC_SRC_A1(cr) (0x400 * cr + 0x2F8)
+#define ACC_SRC_B0(cr) (0x400 * cr + 0x2FC)
+
+#define ACC_SRC_B1(cr) (0x400 * cr + 0x300)
+#define IIR_SRC_A0(cr) (0x400 * cr + 0x304)
+#define IIR_SRC_A1(cr) (0x400 * cr + 0x308)
+#define IIR_DEST_B0(cr) (0x400 * cr + 0x30C)
+#define IIR_DEST_B1(cr) (0x400 * cr + 0x310)
+#define ACC_SRC_C0(cr) (0x400 * cr + 0x314)
+#define ACC_SRC_C1(cr) (0x400 * cr + 0x318)
+
+#define ACC_SRC_D0(cr) (0x400 * cr + 0x31C)
+#define ACC_SRC_D1(cr) (0x400 * cr + 0x320)
+#define IIR_SRC_B1(cr) (0x400 * cr + 0x324)
+#define IIR_SRC_B0(cr) (0x400 * cr + 0x328)
+#define MIX_DEST_A0(cr) (0x400 * cr + 0x32C)
+#define MIX_DEST_A1(cr) (0x400 * cr + 0x330)
+#define MIX_DEST_B0(cr) (0x400 * cr + 0x334)
+#define MIX_DEST_B1(cr) (0x400 * cr + 0x338)
+
+#define A_EEA(cr) (0x400 * cr + 0x33C) // effects work area end address
+
+#define P_ENDX(cr) (0x400 * cr + 0x340) // voice loop end status
+#define P_STAT(cr) (0x400 * cr + 0x344) // DMA status register
+#define P_ENDS(cr) (0x400 * cr + 0x346) // ?
+
+
+// CORE 0 Specific
+
+
+#define P_MVOLL(cr) (0x28 * cr + 0x760) // master volume (left)
+#define P_MVOLR(cr) (0x28 * cr + 0x762) // master volume (right)
+#define P_EVOLL(cr) (0x28 * cr + 0x764) // effect return volume (left)
+#define P_EVOLR(cr) (0x28 * cr + 0x766) // effect return volume (right)
+#define P_AVOLL(cr) (0x28 * cr + 0x768) // core external input volume (left)
+#define P_AVOLR(cr) (0x28 * cr + 0x76A) // core external input volume (right)
+#define P_BVOLL(cr) (0x28 * cr + 0x76C) // sound data input volume (left)
+#define P_BVOLR(cr) (0x28 * cr + 0x76E) // sound data input volume (right)
+#define P_MVOLXL(cr) (0x28 * cr + 0x770) // current master volume (left)
+#define P_MVOLXR(cr) (0x28 * cr + 0x772) // current master volume (right)
+
+
+// More CORE 0 Reverb
+
+
+#define IIR_ALPHA(cr) (0x28 * cr + 0x774)
+#define ACC_COEF_A(cr) (0x28 * cr + 0x776)
+#define ACC_COEF_B(cr) (0x28 * cr + 0x778)
+#define ACC_COEF_C(cr) (0x28 * cr + 0x77A)
+#define ACC_COEF_D(cr) (0x28 * cr + 0x77C)
+#define IIR_COEF(cr) (0x28 * cr + 0x77E)
+#define FB_ALPHA(cr) (0x28 * cr + 0x780)
+#define FB_X(cr) (0x28 * cr + 0x782)
+#define IN_COEF_L(cr) (0x28 * cr + 0x784)
+#define IN_COEF_R(cr) (0x28 * cr + 0x786)
+
+
+// CORE 1 only
+
+#define SPDIF_OUT 0x7C0 // SPDIF Out: OFF/'PCM'/Bitstream/Bypass
+#define SPDIF_MODE 0x7C6
+#define SPDIF_MEDIA 0x7C8 // SPDIF Media: 'CD'/DVD
+#define SPDIF_COPY 0x7CA // SPDIF Copy Protection
+*/
+
+/* PS1 SPU CORE
+
+*** The below really isn't needed, only if you ***
+*** want to add SPU support to the plugin ***
+*** which I see no need to add at this time. ***
+*** individual voice settings ***
+
+#define SPU_VP_PITCH(vc) (0xC04 + (vc << 4)) // voice pitch
+#define SPU_VA_SSA(vc) (0xC06 + (vc << 4)) // voice waveform data start address
+#define SPU_VP_ADSR(vc) (0xC08 + (vc << 4)) // voice envelope
+#define SPU_VA_SSA(vc) (0xC0E + (vc << 4)) // voice waveform data loop address
+
+// common settings
+
+#define SPU_P_MVOLL 0xD80 // master volume (left)
+#define SPU_P_MVOLR 0xD82 // master volume (right)
+#define SPU_P_RVOLL 0xD84 // effect return volume (left)
+#define SPU_P_RVOLR 0xD86 // effect return volume (right)
+#define SPU_S_KON1 0xD88 // key on
+#define SPU_S_KON2 0xD8A //
+#define SPU_S_KOFF1 0xD8C // key off
+#define SPU_S_KOFF2 0xD8E //
+#define SPU_S_PMON1 0xD90 // pitch modulation on
+#define SPU_S_PMON2 0xD92 //
+#define SPU_S_NON1 0xD94 // noise generator on
+#define SPU_S_NON2 0xD96 //
+#define SPU_S_RVBON1 0xD98 // effects on
+#define SPU_S_RVBON2 0xD9A //
+#define SPU_S_MUTE1 0xD9C // voice mute
+#define SPU_S_MUTE2 0xD9E //
+
+#define SPU_A_ESA 0xDA2 // effects work area start
+#define SPU_A_IRQA 0xDA4 // IRQ address
+#define SPU_A_TSA 0xDA6 // DMA transfer start address
+#define SPU_P_DATA 0xDA8 // DMA data register
+#define SPU_P_CTRL 0xDAA // DMA control register
+#define SPU_P_STAT 0xDAE // DMA status register
+
+#define SPU_P_CDL 0xDB0 // sound data input volume (left)
+#define SPU_P_CDR 0xDB2 // sound data input volume (right)
+#define SPU_P_EXTL 0xDB4 // external input volume (left)
+#define SPU_P_EXTR 0xDB6 // external input volume (right)
+
+#define SPU_P_REVERB 0xDC0 // effects control
+*/
+
+/*
+#define H_SPUReverbAddr 0x0da2
+#define H_SPUirqAddr 0x0da4
+#define H_SPUaddr 0x0da6
+#define H_SPUdata 0x0da8
+#define H_SPUctrl 0x0daa
+#define H_SPUstat 0x0dae
+#define H_SPUmvolL 0x0d80
+#define H_SPUmvolR 0x0d82
+#define H_SPUrvolL 0x0d84
+#define H_SPUrvolR 0x0d86
+#define H_SPUon1 0x0d88
+#define H_SPUon2 0x0d8a
+#define H_SPUoff1 0x0d8c
+#define H_SPUoff2 0x0d8e
+#define H_FMod1 0x0d90
+#define H_FMod2 0x0d92
+#define H_Noise1 0x0d94
+#define H_Noise2 0x0d96
+#define H_RVBon1 0x0d98
+#define H_RVBon2 0x0d9a
+#define H_SPUMute1 0x0d9c
+#define H_SPUMute2 0x0d9e
+#define H_CDLeft 0x0db0
+#define H_CDRight 0x0db2
+#define H_ExtLeft 0x0db4
+#define H_ExtRight 0x0db6
+#define H_Reverb 0x0dc0
+#define H_SPUPitch0 0x0c04
+#define H_SPUPitch1 0x0c14
+#define H_SPUPitch2 0x0c24
+#define H_SPUPitch3 0x0c34
+#define H_SPUPitch4 0x0c44
+#define H_SPUPitch5 0x0c54
+#define H_SPUPitch6 0x0c64
+#define H_SPUPitch7 0x0c74
+#define H_SPUPitch8 0x0c84
+#define H_SPUPitch9 0x0c94
+#define H_SPUPitch10 0x0ca4
+#define H_SPUPitch11 0x0cb4
+#define H_SPUPitch12 0x0cc4
+#define H_SPUPitch13 0x0cd4
+#define H_SPUPitch14 0x0ce4
+#define H_SPUPitch15 0x0cf4
+#define H_SPUPitch16 0x0d04
+#define H_SPUPitch17 0x0d14
+#define H_SPUPitch18 0x0d24
+#define H_SPUPitch19 0x0d34
+#define H_SPUPitch20 0x0d44
+#define H_SPUPitch21 0x0d54
+#define H_SPUPitch22 0x0d64
+#define H_SPUPitch23 0x0d74
+
+#define H_SPUStartAdr0 0x0c06
+#define H_SPUStartAdr1 0x0c16
+#define H_SPUStartAdr2 0x0c26
+#define H_SPUStartAdr3 0x0c36
+#define H_SPUStartAdr4 0x0c46
+#define H_SPUStartAdr5 0x0c56
+#define H_SPUStartAdr6 0x0c66
+#define H_SPUStartAdr7 0x0c76
+#define H_SPUStartAdr8 0x0c86
+#define H_SPUStartAdr9 0x0c96
+#define H_SPUStartAdr10 0x0ca6
+#define H_SPUStartAdr11 0x0cb6
+#define H_SPUStartAdr12 0x0cc6
+#define H_SPUStartAdr13 0x0cd6
+#define H_SPUStartAdr14 0x0ce6
+#define H_SPUStartAdr15 0x0cf6
+#define H_SPUStartAdr16 0x0d06
+#define H_SPUStartAdr17 0x0d16
+#define H_SPUStartAdr18 0x0d26
+#define H_SPUStartAdr19 0x0d36
+#define H_SPUStartAdr20 0x0d46
+#define H_SPUStartAdr21 0x0d56
+#define H_SPUStartAdr22 0x0d66
+#define H_SPUStartAdr23 0x0d76
+
+#define H_SPULoopAdr0 0x0c0e
+#define H_SPULoopAdr1 0x0c1e
+#define H_SPULoopAdr2 0x0c2e
+#define H_SPULoopAdr3 0x0c3e
+#define H_SPULoopAdr4 0x0c4e
+#define H_SPULoopAdr5 0x0c5e
+#define H_SPULoopAdr6 0x0c6e
+#define H_SPULoopAdr7 0x0c7e
+#define H_SPULoopAdr8 0x0c8e
+#define H_SPULoopAdr9 0x0c9e
+#define H_SPULoopAdr10 0x0cae
+#define H_SPULoopAdr11 0x0cbe
+#define H_SPULoopAdr12 0x0cce
+#define H_SPULoopAdr13 0x0cde
+#define H_SPULoopAdr14 0x0cee
+#define H_SPULoopAdr15 0x0cfe
+#define H_SPULoopAdr16 0x0d0e
+#define H_SPULoopAdr17 0x0d1e
+#define H_SPULoopAdr18 0x0d2e
+#define H_SPULoopAdr19 0x0d3e
+#define H_SPULoopAdr20 0x0d4e
+#define H_SPULoopAdr21 0x0d5e
+#define H_SPULoopAdr22 0x0d6e
+#define H_SPULoopAdr23 0x0d7e
+
+#define H_SPU_ADSRLevel0 0x0c08
+#define H_SPU_ADSRLevel1 0x0c18
+#define H_SPU_ADSRLevel2 0x0c28
+#define H_SPU_ADSRLevel3 0x0c38
+#define H_SPU_ADSRLevel4 0x0c48
+#define H_SPU_ADSRLevel5 0x0c58
+#define H_SPU_ADSRLevel6 0x0c68
+#define H_SPU_ADSRLevel7 0x0c78
+#define H_SPU_ADSRLevel8 0x0c88
+#define H_SPU_ADSRLevel9 0x0c98
+#define H_SPU_ADSRLevel10 0x0ca8
+#define H_SPU_ADSRLevel11 0x0cb8
+#define H_SPU_ADSRLevel12 0x0cc8
+#define H_SPU_ADSRLevel13 0x0cd8
+#define H_SPU_ADSRLevel14 0x0ce8
+#define H_SPU_ADSRLevel15 0x0cf8
+#define H_SPU_ADSRLevel16 0x0d08
+#define H_SPU_ADSRLevel17 0x0d18
+#define H_SPU_ADSRLevel18 0x0d28
+#define H_SPU_ADSRLevel19 0x0d38
+#define H_SPU_ADSRLevel20 0x0d48
+#define H_SPU_ADSRLevel21 0x0d58
+#define H_SPU_ADSRLevel22 0x0d68
+#define H_SPU_ADSRLevel23 0x0d78
+*/
diff --git a/plugins/ao/eng_psf/peops2/registers2.c b/plugins/ao/eng_psf/peops2/registers2.c new file mode 100644 index 00000000..42fa3238 --- /dev/null +++ b/plugins/ao/eng_psf/peops2/registers2.c @@ -0,0 +1,1342 @@ +/*************************************************************************** + registers.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2004/04/04 - Pete +// - changed plugin to emulate PS2 spu +// +// 2003/02/09 - kode54 +// - removed &0x3fff from reverb volume registers, fixes a few games, +// hopefully won't be breaking anything +// +// 2003/01/19 - Pete +// - added Neill's reverb +// +// 2003/01/06 - Pete +// - added Neill's ADSR timings +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#include "stdafx.h" + +#define _IN_REGISTERS + +#include "../peops2/externals.h" +#include "../peops2/registers.h" +#include "../peops2/regs.h" +#include "../peops2/reverb.h" +#include "../peops2/spu.h" +#include "../psx.h" + +/* +// adsr time values (in ms) by James Higgs ... see the end of +// the adsr.c source for details + +#define ATTACK_MS 514L +#define DECAYHALF_MS 292L +#define DECAY_MS 584L +#define SUSTAIN_MS 450L +#define RELEASE_MS 446L +*/ + +// we have a timebase of 1.020408f ms, not 1 ms... so adjust adsr defines +#define ATTACK_MS 494L +#define DECAYHALF_MS 286L +#define DECAY_MS 572L +#define SUSTAIN_MS 441L +#define RELEASE_MS 437L + +//////////////////////////////////////////////////////////////////////// +// WRITE REGISTERS: called by main emu +//////////////////////////////////////////////////////////////////////// + +EXPORT_GCC void CALLBACK SPU2write(mips_cpu_context *cpu, unsigned long reg, unsigned short val) +{ + spu2_state_t *spu = cpu->spu2; + long r=reg&0xffff; + + spu->regArea[r>>1] = val; + +// printf("SPU2: %04x to %08x\n", val, reg); + + if((r>=0x0000 && r<0x0180)||(r>=0x0400 && r<0x0580)) // some channel info? + { + int ch=(r>>4)&0x1f; + if(r>=0x400) ch+=24; + + switch(r&0x0f) + { + //------------------------------------------------// r volume + case 0: + SetVolumeL(spu, (unsigned char)ch,val); + break; + //------------------------------------------------// l volume + case 2: + SetVolumeR(spu, (unsigned char)ch,val); + break; + //------------------------------------------------// pitch + case 4: + SetPitch(spu, ch,val); + break; + //------------------------------------------------// level with pre-calcs + case 6: + { + const unsigned long lval=val;unsigned long lx; + //---------------------------------------------// + spu->s_chan[ch].ADSRX.AttackModeExp=(lval&0x8000)?1:0; + spu->s_chan[ch].ADSRX.AttackRate=(lval>>8) & 0x007f; + spu->s_chan[ch].ADSRX.DecayRate=(lval>>4) & 0x000f; + spu->s_chan[ch].ADSRX.SustainLevel=lval & 0x000f; + //---------------------------------------------// + if(!spu->iDebugMode) break; + //---------------------------------------------// stuff below is only for debug mode + + spu->s_chan[ch].ADSR.AttackModeExp=(lval&0x8000)?1:0; //0x007f + + lx=(((lval>>8) & 0x007f)>>2); // attack time to run from 0 to 100% volume + lx=min(31,lx); // no overflow on shift! + if(lx) + { + lx = (1<<lx); + if(lx<2147483) lx=(lx*ATTACK_MS)/10000L; // another overflow check + else lx=(lx/10000L)*ATTACK_MS; + if(!lx) lx=1; + } + spu->s_chan[ch].ADSR.AttackTime=lx; + + spu->s_chan[ch].ADSR.SustainLevel= // our adsr vol runs from 0 to 1024, so scale the sustain level + (1024*((lval) & 0x000f))/15; + + lx=(lval>>4) & 0x000f; // decay: + if(lx) // our const decay value is time it takes from 100% to 0% of volume + { + lx = ((1<<(lx))*DECAY_MS)/10000L; + if(!lx) lx=1; + } + spu->s_chan[ch].ADSR.DecayTime = // so calc how long does it take to run from 100% to the wanted sus level + (lx*(1024-spu->s_chan[ch].ADSR.SustainLevel))/1024; + } + break; + //------------------------------------------------// adsr times with pre-calcs + case 8: + { + const unsigned long lval=val;unsigned long lx; + + //----------------------------------------------// + spu->s_chan[ch].ADSRX.SustainModeExp = (lval&0x8000)?1:0; + spu->s_chan[ch].ADSRX.SustainIncrease= (lval&0x4000)?0:1; + spu->s_chan[ch].ADSRX.SustainRate = (lval>>6) & 0x007f; + spu->s_chan[ch].ADSRX.ReleaseModeExp = (lval&0x0020)?1:0; + spu->s_chan[ch].ADSRX.ReleaseRate = lval & 0x001f; + //----------------------------------------------// + if(!spu->iDebugMode) break; + //----------------------------------------------// stuff below is only for debug mode + + spu->s_chan[ch].ADSR.SustainModeExp = (lval&0x8000)?1:0; + spu->s_chan[ch].ADSR.ReleaseModeExp = (lval&0x0020)?1:0; + + lx=((((lval>>6) & 0x007f)>>2)); // sustain time... often very high + lx=min(31,lx); // values are used to hold the volume + if(lx) // until a sound stop occurs + { // the highest value we reach (due to + lx = (1<<lx); // overflow checking) is: + if(lx<2147483) lx=(lx*SUSTAIN_MS)/10000L; // 94704 seconds = 1578 minutes = 26 hours... + else lx=(lx/10000L)*SUSTAIN_MS; // should be enuff... if the stop doesn't + if(!lx) lx=1; // come in this time span, I don't care :) + } + spu->s_chan[ch].ADSR.SustainTime = lx; + + lx=(lval & 0x001f); + spu->s_chan[ch].ADSR.ReleaseVal =lx; + if(lx) // release time from 100% to 0% + { // note: the release time will be + lx = (1<<lx); // adjusted when a stop is coming, + if(lx<2147483) lx=(lx*RELEASE_MS)/10000L; // so at this time the adsr vol will + else lx=(lx/10000L)*RELEASE_MS; // run from (current volume) to 0% + if(!lx) lx=1; + } + spu->s_chan[ch].ADSR.ReleaseTime=lx; + + if(lval & 0x4000) // add/dec flag + spu->s_chan[ch].ADSR.SustainModeDec=-1; + else spu->s_chan[ch].ADSR.SustainModeDec=1; + } + break; + //------------------------------------------------// + } + + spu->iSpuAsyncWait=0; + + return; + } + + if((r>=0x01c0 && r<0x02E0)||(r>=0x05c0 && r<0x06E0)) // some channel info? + { + int ch=0; + if(r>=0x400) {ch=24;r-=0x400;} + + ch+=(r-0x1c0)/12; + r-=(ch%24)*12; + switch(r) + { + //------------------------------------------------// + case 0x1C0: + spu->s_chan[ch].iStartAdr=(((unsigned long)val&0xf)<<16)|(spu->s_chan[ch].iStartAdr&0xFFFF); + spu->s_chan[ch].pStart=spu->spuMemC+(spu->s_chan[ch].iStartAdr<<1); + break; + case 0x1C2: + spu->s_chan[ch].iStartAdr=(spu->s_chan[ch].iStartAdr & 0xF0000) | (val & 0xFFFF); + spu->s_chan[ch].pStart=spu->spuMemC+(spu->s_chan[ch].iStartAdr<<1); + break; + //------------------------------------------------// + case 0x1C4: + spu->s_chan[ch].iLoopAdr=(((unsigned long)val&0xf)<<16)|(spu->s_chan[ch].iLoopAdr&0xFFFF); + spu->s_chan[ch].pLoop=spu->spuMemC+(spu->s_chan[ch].iLoopAdr<<1); + spu->s_chan[ch].bIgnoreLoop=1; + break; + case 0x1C6: + spu->s_chan[ch].iLoopAdr=(spu->s_chan[ch].iLoopAdr & 0xF0000) | (val & 0xFFFF); + spu->s_chan[ch].pLoop=spu->spuMemC+(spu->s_chan[ch].iLoopAdr<<1); + spu->s_chan[ch].bIgnoreLoop=1; + break; + //------------------------------------------------// + case 0x1C8: + // unused... check if it gets written as well + spu->s_chan[ch].iNextAdr=(((unsigned long)val&0xf)<<16)|(spu->s_chan[ch].iNextAdr&0xFFFF); + break; + case 0x1CA: + // unused... check if it gets written as well + spu->s_chan[ch].iNextAdr=(spu->s_chan[ch].iNextAdr & 0xF0000) | (val & 0xFFFF); + break; + //------------------------------------------------// + } + + spu->iSpuAsyncWait=0; + + return; + } + + switch(r) + { + //-------------------------------------------------// + case PS2_C0_SPUaddr_Hi: + spu->spuAddr2[0] = (((unsigned long)val&0xf)<<16)|(spu->spuAddr2[0]&0xFFFF); + break; + //-------------------------------------------------// + case PS2_C0_SPUaddr_Lo: + spu->spuAddr2[0] = (spu->spuAddr2[0] & 0xF0000) | (val & 0xFFFF); + break; + //-------------------------------------------------// + case PS2_C1_SPUaddr_Hi: + spu->spuAddr2[1] = (((unsigned long)val&0xf)<<16)|(spu->spuAddr2[1]&0xFFFF); + break; + //-------------------------------------------------// + case PS2_C1_SPUaddr_Lo: + spu->spuAddr2[1] = (spu->spuAddr2[1] & 0xF0000) | (val & 0xFFFF); + break; + //-------------------------------------------------// + case PS2_C0_SPUdata: + spu->spuMem[spu->spuAddr2[0]] = val; + spu->spuAddr2[0]++; + if(spu->spuAddr2[0]>0xfffff) spu->spuAddr2[0]=0; + break; + //-------------------------------------------------// + case PS2_C1_SPUdata: + spu->spuMem[spu->spuAddr2[1]] = val; + spu->spuAddr2[1]++; + if(spu->spuAddr2[1]>0xfffff) spu->spuAddr2[1]=0; + break; + //-------------------------------------------------// + case PS2_C0_ATTR: + spu->spuCtrl2[0]=val; + break; + //-------------------------------------------------// + case PS2_C1_ATTR: + spu->spuCtrl2[1]=val; + break; + //-------------------------------------------------// + case PS2_C0_SPUstat: + spu->spuStat2[0]=val; + break; + //-------------------------------------------------// + case PS2_C1_SPUstat: + spu->spuStat2[1]=val; + break; + //-------------------------------------------------// + case PS2_C0_ReverbAddr_Hi: + spu->spuRvbAddr2[0] = (((unsigned long)val&0xf)<<16)|(spu->spuRvbAddr2[0]&0xFFFF); + SetReverbAddr(spu, 0); + break; + //-------------------------------------------------// + case PS2_C0_ReverbAddr_Lo: + spu->spuRvbAddr2[0] = (spu->spuRvbAddr2[0] & 0xF0000) | (val & 0xFFFF); + SetReverbAddr(spu, 0); + break; + //-------------------------------------------------// + case PS2_C0_ReverbAEnd_Hi: + spu->spuRvbAEnd2[0] = (((unsigned long)val&0xf)<<16)|(/*spu->spuRvbAEnd2[0]&*/0xFFFF); + spu->rvb[0].EndAddr=spu->spuRvbAEnd2[0]; + break; + //-------------------------------------------------// + case PS2_C1_ReverbAEnd_Hi: + spu->spuRvbAEnd2[1] = (((unsigned long)val&0xf)<<16)|(/*spu->spuRvbAEnd2[1]&*/0xFFFF); + spu->rvb[1].EndAddr=spu->spuRvbAEnd2[1]; + break; + //-------------------------------------------------// + case PS2_C1_ReverbAddr_Hi: + spu->spuRvbAddr2[1] = (((unsigned long)val&0xf)<<16)|(spu->spuRvbAddr2[1]&0xFFFF); + SetReverbAddr(spu, 1); + break; + //-------------------------------------------------// + case PS2_C1_ReverbAddr_Lo: + spu->spuRvbAddr2[1] = (spu->spuRvbAddr2[1] & 0xF0000) | (val & 0xFFFF); + SetReverbAddr(spu, 1); + break; + //-------------------------------------------------// + case PS2_C0_SPUirqAddr_Hi: + spu->spuIrq2[0] = (((unsigned long)val&0xf)<<16)|(spu->spuIrq2[0]&0xFFFF); + spu->pSpuIrq[0]=spu->spuMemC+(spu->spuIrq2[0]<<1); + break; + //-------------------------------------------------// + case PS2_C0_SPUirqAddr_Lo: + spu->spuIrq2[0] = (spu->spuIrq2[0] & 0xF0000) | (val & 0xFFFF); + spu->pSpuIrq[0]=spu->spuMemC+(spu->spuIrq2[0]<<1); + break; + //-------------------------------------------------// + case PS2_C1_SPUirqAddr_Hi: + spu->spuIrq2[1] = (((unsigned long)val&0xf)<<16)|(spu->spuIrq2[1]&0xFFFF); + spu->pSpuIrq[1]=spu->spuMemC+(spu->spuIrq2[1]<<1); + break; + //-------------------------------------------------// + case PS2_C1_SPUirqAddr_Lo: + spu->spuIrq2[1] = (spu->spuIrq2[1] & 0xF0000) | (val & 0xFFFF); + spu->pSpuIrq[1]=spu->spuMemC+(spu->spuIrq2[1]<<1); + break; + //-------------------------------------------------// + case PS2_C0_SPUrvolL: + spu->rvb[0].VolLeft=val; + break; + //-------------------------------------------------// + case PS2_C0_SPUrvolR: + spu->rvb[0].VolRight=val; + break; + //-------------------------------------------------// + case PS2_C1_SPUrvolL: + spu->rvb[1].VolLeft=val; + break; + //-------------------------------------------------// + case PS2_C1_SPUrvolR: + spu->rvb[1].VolRight=val; + break; + //-------------------------------------------------// + case PS2_C0_SPUon1: + SoundOn(spu, 0,16,val); + break; + //-------------------------------------------------// + case PS2_C0_SPUon2: + SoundOn(spu, 16,24,val); + break; + //-------------------------------------------------// + case PS2_C1_SPUon1: + SoundOn(spu, 24,40,val); + break; + //-------------------------------------------------// + case PS2_C1_SPUon2: + SoundOn(spu, 40,48,val); + break; + //-------------------------------------------------// + case PS2_C0_SPUoff1: + SoundOff(spu, 0,16,val); + break; + //-------------------------------------------------// + case PS2_C0_SPUoff2: + SoundOff(spu, 16,24,val); + break; + //-------------------------------------------------// + case PS2_C1_SPUoff1: + SoundOff(spu, 24,40,val); + break; + //-------------------------------------------------// + case PS2_C1_SPUoff2: + SoundOff(spu, 40,48,val); + break; + //-------------------------------------------------// + case PS2_C0_SPUend1: + case PS2_C0_SPUend2: + if(val) spu->dwEndChannel2[0]=0; + break; + //-------------------------------------------------// + case PS2_C1_SPUend1: + case PS2_C1_SPUend2: + if(val) spu->dwEndChannel2[1]=0; + break; + //-------------------------------------------------// + case PS2_C0_FMod1: + FModOn(spu, 0,16,val); + break; + //-------------------------------------------------// + case PS2_C0_FMod2: + FModOn(spu, 16,24,val); + break; + //-------------------------------------------------// + case PS2_C1_FMod1: + FModOn(spu, 24,40,val); + break; + //-------------------------------------------------// + case PS2_C1_FMod2: + FModOn(spu, 40,48,val); + break; + //-------------------------------------------------// + case PS2_C0_Noise1: + NoiseOn(spu, 0,16,val); + break; + //-------------------------------------------------// + case PS2_C0_Noise2: + NoiseOn(spu, 16,24,val); + break; + //-------------------------------------------------// + case PS2_C1_Noise1: + NoiseOn(spu, 24,40,val); + break; + //-------------------------------------------------// + case PS2_C1_Noise2: + NoiseOn(spu, 40,48,val); + break; + //-------------------------------------------------// + case PS2_C0_DryL1: + VolumeOn(spu, 0,16,val,0); + break; + //-------------------------------------------------// + case PS2_C0_DryL2: + VolumeOn(spu, 16,24,val,0); + break; + //-------------------------------------------------// + case PS2_C1_DryL1: + VolumeOn(spu, 24,40,val,0); + break; + //-------------------------------------------------// + case PS2_C1_DryL2: + VolumeOn(spu, 40,48,val,0); + break; + //-------------------------------------------------// + case PS2_C0_DryR1: + VolumeOn(spu, 0,16,val,1); + break; + //-------------------------------------------------// + case PS2_C0_DryR2: + VolumeOn(spu, 16,24,val,1); + break; + //-------------------------------------------------// + case PS2_C1_DryR1: + VolumeOn(spu, 24,40,val,1); + break; + //-------------------------------------------------// + case PS2_C1_DryR2: + VolumeOn(spu, 40,48,val,1); + break; + //-------------------------------------------------// + case PS2_C0_RVBon1_L: + ReverbOn(spu, 0,16,val,0); + break; + //-------------------------------------------------// + case PS2_C0_RVBon2_L: + ReverbOn(spu, 16,24,val,0); + break; + //-------------------------------------------------// + case PS2_C1_RVBon1_L: + ReverbOn(spu, 24,40,val,0); + break; + //-------------------------------------------------// + case PS2_C1_RVBon2_L: + ReverbOn(spu, 40,48,val,0); + break; + //-------------------------------------------------// + case PS2_C0_RVBon1_R: + ReverbOn(spu, 0,16,val,1); + break; + //-------------------------------------------------// + case PS2_C0_RVBon2_R: + ReverbOn(spu, 16,24,val,1); + break; + //-------------------------------------------------// + case PS2_C1_RVBon1_R: + ReverbOn(spu, 24,40,val,1); + break; + //-------------------------------------------------// + case PS2_C1_RVBon2_R: + ReverbOn(spu, 40,48,val,1); + break; + //-------------------------------------------------// + case PS2_C0_Reverb+0: + spu->rvb[0].FB_SRC_A=(((unsigned long)val&0xf)<<16)|(spu->rvb[0].FB_SRC_A&0xFFFF); + break; + case PS2_C0_Reverb+2: + spu->rvb[0].FB_SRC_A=(spu->rvb[0].FB_SRC_A & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+4: + spu->rvb[0].FB_SRC_B=(((unsigned long)val&0xf)<<16)|(spu->rvb[0].FB_SRC_B&0xFFFF); + break; + case PS2_C0_Reverb+6: + spu->rvb[0].FB_SRC_B=(spu->rvb[0].FB_SRC_B & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+8: + spu->rvb[0].IIR_DEST_A0=(((unsigned long)val&0xf)<<16)|(spu->rvb[0].IIR_DEST_A0&0xFFFF); + break; + case PS2_C0_Reverb+10: + spu->rvb[0].IIR_DEST_A0=(spu->rvb[0].IIR_DEST_A0 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+12: + spu->rvb[0].IIR_DEST_A1=(((unsigned long)val&0xf)<<16)|(spu->rvb[0].IIR_DEST_A1&0xFFFF); + break; + case PS2_C0_Reverb+14: + spu->rvb[0].IIR_DEST_A1=(spu->rvb[0].IIR_DEST_A1 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+16: + spu->rvb[0].ACC_SRC_A0=(((unsigned long)val&0xf)<<16)|(spu->rvb[0].ACC_SRC_A0&0xFFFF); + break; + case PS2_C0_Reverb+18: + spu->rvb[0].ACC_SRC_A0=(spu->rvb[0].ACC_SRC_A0 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+20: + spu->rvb[0].ACC_SRC_A1=(((unsigned long)val&0xf)<<16)|(spu->rvb[0].ACC_SRC_A1&0xFFFF); + break; + case PS2_C0_Reverb+22: + spu->rvb[0].ACC_SRC_A1=(spu->rvb[0].ACC_SRC_A1 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+24: + spu->rvb[0].ACC_SRC_B0=(((unsigned long)val&0xf)<<16)|(spu->rvb[0].ACC_SRC_B0&0xFFFF); + break; + case PS2_C0_Reverb+26: + spu->rvb[0].ACC_SRC_B0=(spu->rvb[0].ACC_SRC_B0 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+28: + spu->rvb[0].ACC_SRC_B1=(((unsigned long)val&0xf)<<16)|(spu->rvb[0].ACC_SRC_B1&0xFFFF); + break; + case PS2_C0_Reverb+30: + spu->rvb[0].ACC_SRC_B1=(spu->rvb[0].ACC_SRC_B1 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+32: + spu->rvb[0].IIR_SRC_A0=(((unsigned long)val&0xf)<<16)|(spu->rvb[0].IIR_SRC_A0&0xFFFF); + break; + case PS2_C0_Reverb+34: + spu->rvb[0].IIR_SRC_A0=(spu->rvb[0].IIR_SRC_A0 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+36: + spu->rvb[0].IIR_SRC_A1=(((unsigned long)val&0xf)<<16)|(spu->rvb[0].IIR_SRC_A1&0xFFFF); + break; + case PS2_C0_Reverb+38: + spu->rvb[0].IIR_SRC_A1=(spu->rvb[0].IIR_SRC_A1 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+40: + spu->rvb[0].IIR_DEST_B0=(((unsigned long)val&0xf)<<16)|(spu->rvb[0].IIR_DEST_B0&0xFFFF); + break; + case PS2_C0_Reverb+42: + spu->rvb[0].IIR_DEST_B0=(spu->rvb[0].IIR_DEST_B0 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+44: + spu->rvb[0].IIR_DEST_B1=(((unsigned long)val&0xf)<<16)|(spu->rvb[0].IIR_DEST_B1&0xFFFF); + break; + case PS2_C0_Reverb+46: + spu->rvb[0].IIR_DEST_B1=(spu->rvb[0].IIR_DEST_B1 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+48: + spu->rvb[0].ACC_SRC_C0=(((unsigned long)val&0xf)<<16)|(spu->rvb[0].ACC_SRC_C0&0xFFFF); + break; + case PS2_C0_Reverb+50: + spu->rvb[0].ACC_SRC_C0=(spu->rvb[0].ACC_SRC_C0 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+52: + spu->rvb[0].ACC_SRC_C1=(((unsigned long)val&0xf)<<16)|(spu->rvb[0].ACC_SRC_C1&0xFFFF); + break; + case PS2_C0_Reverb+54: + spu->rvb[0].ACC_SRC_C1=(spu->rvb[0].ACC_SRC_C1 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+56: + spu->rvb[0].ACC_SRC_D0=(((unsigned long)val&0xf)<<16)|(spu->rvb[0].ACC_SRC_D0&0xFFFF); + break; + case PS2_C0_Reverb+58: + spu->rvb[0].ACC_SRC_D0=(spu->rvb[0].ACC_SRC_D0 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+60: + spu->rvb[0].ACC_SRC_D1=(((unsigned long)val&0xf)<<16)|(spu->rvb[0].ACC_SRC_D1&0xFFFF); + break; + case PS2_C0_Reverb+62: + spu->rvb[0].ACC_SRC_D1=(spu->rvb[0].ACC_SRC_D1 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+64: + spu->rvb[0].IIR_SRC_B1=(((unsigned long)val&0xf)<<16)|(spu->rvb[0].IIR_SRC_B1&0xFFFF); + break; + case PS2_C0_Reverb+66: + spu->rvb[0].IIR_SRC_B1=(spu->rvb[0].IIR_SRC_B1 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+68: + spu->rvb[0].IIR_SRC_B0=(((unsigned long)val&0xf)<<16)|(spu->rvb[0].IIR_SRC_B0&0xFFFF); + break; + case PS2_C0_Reverb+70: + spu->rvb[0].IIR_SRC_B0=(spu->rvb[0].IIR_SRC_B0 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+72: + spu->rvb[0].MIX_DEST_A0=(((unsigned long)val&0xf)<<16)|(spu->rvb[0].MIX_DEST_A0&0xFFFF); + break; + case PS2_C0_Reverb+74: + spu->rvb[0].MIX_DEST_A0=(spu->rvb[0].MIX_DEST_A0 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+76: + spu->rvb[0].MIX_DEST_A1=(((unsigned long)val&0xf)<<16)|(spu->rvb[0].MIX_DEST_A1&0xFFFF); + break; + case PS2_C0_Reverb+78: + spu->rvb[0].MIX_DEST_A1=(spu->rvb[0].MIX_DEST_A1 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+80: + spu->rvb[0].MIX_DEST_B0=(((unsigned long)val&0xf)<<16)|(spu->rvb[0].MIX_DEST_B0&0xFFFF); + break; + case PS2_C0_Reverb+82: + spu->rvb[0].MIX_DEST_B0=(spu->rvb[0].MIX_DEST_B0 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+84: + spu->rvb[0].MIX_DEST_B1=(((unsigned long)val&0xf)<<16)|(spu->rvb[0].MIX_DEST_B1&0xFFFF); + break; + case PS2_C0_Reverb+86: + spu->rvb[0].MIX_DEST_B1=(spu->rvb[0].MIX_DEST_B1 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C0_ReverbX+0: spu->rvb[0].IIR_ALPHA=(short)val; break; + case PS2_C0_ReverbX+2: spu->rvb[0].ACC_COEF_A=(short)val; break; + case PS2_C0_ReverbX+4: spu->rvb[0].ACC_COEF_B=(short)val; break; + case PS2_C0_ReverbX+6: spu->rvb[0].ACC_COEF_C=(short)val; break; + case PS2_C0_ReverbX+8: spu->rvb[0].ACC_COEF_D=(short)val; break; + case PS2_C0_ReverbX+10: spu->rvb[0].IIR_COEF=(short)val; break; + case PS2_C0_ReverbX+12: spu->rvb[0].FB_ALPHA=(short)val; break; + case PS2_C0_ReverbX+14: spu->rvb[0].FB_X=(short)val; break; + case PS2_C0_ReverbX+16: spu->rvb[0].IN_COEF_L=(short)val; break; + case PS2_C0_ReverbX+18: spu->rvb[0].IN_COEF_R=(short)val; break; + //-------------------------------------------------// + case PS2_C1_Reverb+0: + spu->rvb[1].FB_SRC_A=(((unsigned long)val&0xf)<<16)|(spu->rvb[1].FB_SRC_A&0xFFFF); + break; + case PS2_C1_Reverb+2: + spu->rvb[1].FB_SRC_A=(spu->rvb[1].FB_SRC_A & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+4: + spu->rvb[1].FB_SRC_B=(((unsigned long)val&0xf)<<16)|(spu->rvb[1].FB_SRC_B&0xFFFF); + break; + case PS2_C1_Reverb+6: + spu->rvb[1].FB_SRC_B=(spu->rvb[1].FB_SRC_B & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+8: + spu->rvb[1].IIR_DEST_A0=(((unsigned long)val&0xf)<<16)|(spu->rvb[1].IIR_DEST_A0&0xFFFF); + break; + case PS2_C1_Reverb+10: + spu->rvb[1].IIR_DEST_A0=(spu->rvb[1].IIR_DEST_A0 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+12: + spu->rvb[1].IIR_DEST_A1=(((unsigned long)val&0xf)<<16)|(spu->rvb[1].IIR_DEST_A1&0xFFFF); + break; + case PS2_C1_Reverb+14: + spu->rvb[1].IIR_DEST_A1=(spu->rvb[1].IIR_DEST_A1 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+16: + spu->rvb[1].ACC_SRC_A0=(((unsigned long)val&0xf)<<16)|(spu->rvb[1].ACC_SRC_A0&0xFFFF); + break; + case PS2_C1_Reverb+18: + spu->rvb[1].ACC_SRC_A0=(spu->rvb[1].ACC_SRC_A0 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+20: + spu->rvb[1].ACC_SRC_A1=(((unsigned long)val&0xf)<<16)|(spu->rvb[1].ACC_SRC_A1&0xFFFF); + break; + case PS2_C1_Reverb+22: + spu->rvb[1].ACC_SRC_A1=(spu->rvb[1].ACC_SRC_A1 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+24: + spu->rvb[1].ACC_SRC_B0=(((unsigned long)val&0xf)<<16)|(spu->rvb[1].ACC_SRC_B0&0xFFFF); + break; + case PS2_C1_Reverb+26: + spu->rvb[1].ACC_SRC_B0=(spu->rvb[1].ACC_SRC_B0 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+28: + spu->rvb[1].ACC_SRC_B1=(((unsigned long)val&0xf)<<16)|(spu->rvb[1].ACC_SRC_B1&0xFFFF); + break; + case PS2_C1_Reverb+30: + spu->rvb[1].ACC_SRC_B1=(spu->rvb[1].ACC_SRC_B1 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+32: + spu->rvb[1].IIR_SRC_A0=(((unsigned long)val&0xf)<<16)|(spu->rvb[1].IIR_SRC_A0&0xFFFF); + break; + case PS2_C1_Reverb+34: + spu->rvb[1].IIR_SRC_A0=(spu->rvb[1].IIR_SRC_A0 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+36: + spu->rvb[1].IIR_SRC_A1=(((unsigned long)val&0xf)<<16)|(spu->rvb[1].IIR_SRC_A1&0xFFFF); + break; + case PS2_C1_Reverb+38: + spu->rvb[1].IIR_SRC_A1=(spu->rvb[1].IIR_SRC_A1 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+40: + spu->rvb[1].IIR_DEST_B0=(((unsigned long)val&0xf)<<16)|(spu->rvb[1].IIR_DEST_B0&0xFFFF); + break; + case PS2_C1_Reverb+42: + spu->rvb[1].IIR_DEST_B0=(spu->rvb[1].IIR_DEST_B0 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+44: + spu->rvb[1].IIR_DEST_B1=(((unsigned long)val&0xf)<<16)|(spu->rvb[1].IIR_DEST_B1&0xFFFF); + break; + case PS2_C1_Reverb+46: + spu->rvb[1].IIR_DEST_B1=(spu->rvb[1].IIR_DEST_B1 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+48: + spu->rvb[1].ACC_SRC_C0=(((unsigned long)val&0xf)<<16)|(spu->rvb[1].ACC_SRC_C0&0xFFFF); + break; + case PS2_C1_Reverb+50: + spu->rvb[1].ACC_SRC_C0=(spu->rvb[1].ACC_SRC_C0 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+52: + spu->rvb[1].ACC_SRC_C1=(((unsigned long)val&0xf)<<16)|(spu->rvb[1].ACC_SRC_C1&0xFFFF); + break; + case PS2_C1_Reverb+54: + spu->rvb[1].ACC_SRC_C1=(spu->rvb[1].ACC_SRC_C1 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+56: + spu->rvb[1].ACC_SRC_D0=(((unsigned long)val&0xf)<<16)|(spu->rvb[1].ACC_SRC_D0&0xFFFF); + break; + case PS2_C1_Reverb+58: + spu->rvb[1].ACC_SRC_D0=(spu->rvb[1].ACC_SRC_D0 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+60: + spu->rvb[1].ACC_SRC_D1=(((unsigned long)val&0xf)<<16)|(spu->rvb[1].ACC_SRC_D1&0xFFFF); + break; + case PS2_C1_Reverb+62: + spu->rvb[1].ACC_SRC_D1=(spu->rvb[1].ACC_SRC_D1 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+64: + spu->rvb[1].IIR_SRC_B1=(((unsigned long)val&0xf)<<16)|(spu->rvb[1].IIR_SRC_B1&0xFFFF); + break; + case PS2_C1_Reverb+66: + spu->rvb[1].IIR_SRC_B1=(spu->rvb[1].IIR_SRC_B1 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+68: + spu->rvb[1].IIR_SRC_B0=(((unsigned long)val&0xf)<<16)|(spu->rvb[1].IIR_SRC_B0&0xFFFF); + break; + case PS2_C1_Reverb+70: + spu->rvb[1].IIR_SRC_B0=(spu->rvb[1].IIR_SRC_B0 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+72: + spu->rvb[1].MIX_DEST_A0=(((unsigned long)val&0xf)<<16)|(spu->rvb[1].MIX_DEST_A0&0xFFFF); + break; + case PS2_C1_Reverb+74: + spu->rvb[1].MIX_DEST_A0=(spu->rvb[1].MIX_DEST_A0 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+76: + spu->rvb[1].MIX_DEST_A1=(((unsigned long)val&0xf)<<16)|(spu->rvb[1].MIX_DEST_A1&0xFFFF); + break; + case PS2_C1_Reverb+78: + spu->rvb[1].MIX_DEST_A1=(spu->rvb[1].MIX_DEST_A1 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+80: + spu->rvb[1].MIX_DEST_B0=(((unsigned long)val&0xf)<<16)|(spu->rvb[1].MIX_DEST_B0&0xFFFF); + break; + case PS2_C1_Reverb+82: + spu->rvb[1].MIX_DEST_B0=(spu->rvb[1].MIX_DEST_B0 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+84: + spu->rvb[1].MIX_DEST_B1=(((unsigned long)val&0xf)<<16)|(spu->rvb[1].MIX_DEST_B1&0xFFFF); + break; + case PS2_C1_Reverb+86: + spu->rvb[1].MIX_DEST_B1=(spu->rvb[1].MIX_DEST_B1 & 0xF0000) | ((val) & 0xFFFF); + break; + case PS2_C1_ReverbX+0: spu->rvb[1].IIR_ALPHA=(short)val; break; + case PS2_C1_ReverbX+2: spu->rvb[1].ACC_COEF_A=(short)val; break; + case PS2_C1_ReverbX+4: spu->rvb[1].ACC_COEF_B=(short)val; break; + case PS2_C1_ReverbX+6: spu->rvb[1].ACC_COEF_C=(short)val; break; + case PS2_C1_ReverbX+8: spu->rvb[1].ACC_COEF_D=(short)val; break; + case PS2_C1_ReverbX+10: spu->rvb[1].IIR_COEF=(short)val; break; + case PS2_C1_ReverbX+12: spu->rvb[1].FB_ALPHA=(short)val; break; + case PS2_C1_ReverbX+14: spu->rvb[1].FB_X=(short)val; break; + case PS2_C1_ReverbX+16: spu->rvb[1].IN_COEF_L=(short)val; break; + case PS2_C1_ReverbX+18: spu->rvb[1].IN_COEF_R=(short)val; break; + } + + spu->iSpuAsyncWait=0; + +} + +//////////////////////////////////////////////////////////////////////// +// READ REGISTER: called by main emu +//////////////////////////////////////////////////////////////////////// + +EXPORT_GCC unsigned short CALLBACK SPU2read(mips_cpu_context *cpu, unsigned long reg) +{ + spu2_state_t *spu = cpu->spu2; + long r=reg&0xffff; + +#ifdef _WINDOWS +// if(iDebugMode==1) logprintf("R_REG %X\r\n",reg&0xFFFF); +#endif + + spu->iSpuAsyncWait=0; + + if((r>=0x0000 && r<0x0180)||(r>=0x0400 && r<0x0580)) // some channel info? + { + switch(r&0x0f) + { + //------------------------------------------------// env value + case 10: + { + int ch=(r>>4)&0x1f; + if(r>=0x400) ch+=24; + if(spu->s_chan[ch].bNew) return 1; // we are started, but not processed? return 1 + if(spu->s_chan[ch].ADSRX.lVolume && // same here... we haven't decoded one sample yet, so no envelope yet. return 1 as well + !spu->s_chan[ch].ADSRX.EnvelopeVol) + return 1; + return (unsigned short)(spu->s_chan[ch].ADSRX.EnvelopeVol>>16); + }break; + } + } + + if((r>=0x01c0 && r<0x02E0)||(r>=0x05c0 && r<0x06E0)) // some channel info? + { + int ch=0;unsigned long rx=r; + if(rx>=0x400) {ch=24;rx-=0x400;} + + ch+=(rx-0x1c0)/12; + rx-=(ch%24)*12; + + switch(rx) + { + //------------------------------------------------// + case 0x1C4: + return (((spu->s_chan[ch].pLoop-spu->spuMemC)>>17)&0xF); + break; + case 0x1C6: + return (((spu->s_chan[ch].pLoop-spu->spuMemC)>>1)&0xFFFF); + break; + //------------------------------------------------// + case 0x1C8: + return (((spu->s_chan[ch].pCurr-spu->spuMemC)>>17)&0xF); + break; + case 0x1CA: + return (((spu->s_chan[ch].pCurr-spu->spuMemC)>>1)&0xFFFF); + break; + //------------------------------------------------// + } + } + + switch(r) + { + //--------------------------------------------------// + case PS2_C0_SPUend1: + return (unsigned short)((spu->dwEndChannel2[0]&0xFFFF)); + case PS2_C0_SPUend2: + return (unsigned short)((spu->dwEndChannel2[0]>>16)); + //--------------------------------------------------// + case PS2_C1_SPUend1: + return (unsigned short)((spu->dwEndChannel2[1]&0xFFFF)); + case PS2_C1_SPUend2: + return (unsigned short)((spu->dwEndChannel2[1]>>16)); + //--------------------------------------------------// + case PS2_C0_ATTR: + return spu->spuCtrl2[0]; + break; + //--------------------------------------------------// + case PS2_C1_ATTR: + return spu->spuCtrl2[1]; + break; + //--------------------------------------------------// + case PS2_C0_SPUstat: + return spu->spuStat2[0]; + break; + //--------------------------------------------------// + case PS2_C1_SPUstat: + return spu->spuStat2[1]; + break; + //--------------------------------------------------// + case PS2_C0_SPUdata: + { + unsigned short s=spu->spuMem[spu->spuAddr2[0]]; + spu->spuAddr2[0]++; + if(spu->spuAddr2[0]>0xfffff) spu->spuAddr2[0]=0; + return s; + } + //--------------------------------------------------// + case PS2_C1_SPUdata: + { + unsigned short s=spu->spuMem[spu->spuAddr2[1]]; + spu->spuAddr2[1]++; + if(spu->spuAddr2[1]>0xfffff) spu->spuAddr2[1]=0; + return s; + } + //--------------------------------------------------// + case PS2_C0_SPUaddr_Hi: + return (unsigned short)((spu->spuAddr2[0]>>16)&0xF); + break; + case PS2_C0_SPUaddr_Lo: + return (unsigned short)((spu->spuAddr2[0]&0xFFFF)); + break; + //--------------------------------------------------// + case PS2_C1_SPUaddr_Hi: + return (unsigned short)((spu->spuAddr2[1]>>16)&0xF); + break; + case PS2_C1_SPUaddr_Lo: + return (unsigned short)((spu->spuAddr2[1]&0xFFFF)); + break; + //--------------------------------------------------// + } + + return spu->regArea[r>>1]; +} + +EXPORT_GCC void CALLBACK SPU2writePS1Port(mips_cpu_context *cpu, unsigned long reg, unsigned short val) +{ + spu2_state_t *spu = cpu->spu2; + const u32 r=reg&0xfff; + + if(r>=0xc00 && r<0xd80) // channel info + { + SPU2write(cpu, r-0xc00, val); + return; + } + + switch(r) + { + //-------------------------------------------------// + case H_SPUaddr: + spu->spuAddr2[0] = (u32) val<<2; + break; + //-------------------------------------------------// + case H_SPUdata: + spu->spuMem[spu->spuAddr2[0]] = BFLIP16(val); + spu->spuAddr2[0]++; + if(spu->spuAddr2[0]>0xfffff) spu->spuAddr2[0]=0; + break; + //-------------------------------------------------// + case H_SPUctrl: +// spuCtrl=val; + break; + //-------------------------------------------------// + case H_SPUstat: + spu->spuStat2[0]=val & 0xf800; + break; + //-------------------------------------------------// + case H_SPUReverbAddr: + spu->spuRvbAddr2[0] = val; + SetReverbAddr(spu, 0); + break; + //-------------------------------------------------// + case H_SPUirqAddr: + spu->spuIrq2[0] = val<<2; + spu->pSpuIrq[0]=spu->spuMemC+((u32) val<<1); + break; + //-------------------------------------------------// + /* Volume settings appear to be at least 15-bit unsigned in this case. + Definitely NOT 15-bit signed. Probably 16-bit signed, so s16 type cast. + Check out "Chrono Cross: Shadow's End Forest" + */ + case H_SPUrvolL: + spu->rvb[0].VolLeft=(s16)val; + //printf("%d\n",val); + break; + //-------------------------------------------------// + case H_SPUrvolR: + spu->rvb[0].VolRight=(s16)val; + //printf("%d\n",val); + break; + //-------------------------------------------------// + +/* + case H_ExtLeft: + //auxprintf("EL %d\n",val); + break; + //-------------------------------------------------// + case H_ExtRight: + //auxprintf("ER %d\n",val); + break; + //-------------------------------------------------// + case H_SPUmvolL: + //auxprintf("ML %d\n",val); + break; + //-------------------------------------------------// + case H_SPUmvolR: + //auxprintf("MR %d\n",val); + break; + //-------------------------------------------------// + case H_SPUMute1: + //printf("M0 %04x\n",val); + break; + //-------------------------------------------------// + case H_SPUMute2: + // printf("M1 %04x\n",val); + break; +*/ + //-------------------------------------------------// + case H_SPUon1: + SoundOn(spu, 0,16,val); + break; + //-------------------------------------------------// + case H_SPUon2: + //printf("Boop: %08x: %04x\n",reg,val); + SoundOn(spu, 16,24,val); + break; + //-------------------------------------------------// + case H_SPUoff1: + SoundOff(spu, 0,16,val); + break; + //-------------------------------------------------// + case H_SPUoff2: + SoundOff(spu, 16,24,val); + // printf("Boop: %08x: %04x\n",reg,val); + break; + //-------------------------------------------------// + case H_FMod1: + FModOn(spu, 0,16,val); + break; + //-------------------------------------------------// + case H_FMod2: + FModOn(spu, 16,24,val); + break; + //-------------------------------------------------// + case H_Noise1: + NoiseOn(spu, 0,16,val); + break; + //-------------------------------------------------// + case H_Noise2: + NoiseOn(spu, 16,24,val); + break; + //-------------------------------------------------// + case H_RVBon1: + ReverbOn(spu, 0,16,val,0); + break; + + //-------------------------------------------------// + case H_RVBon2: + ReverbOn(spu, 16,24,val,0); + break; + + //-------------------------------------------------// + case H_Reverb+0: + spu->rvb[0].FB_SRC_A=val; + break; + + case H_Reverb+2 : spu->rvb[0].FB_SRC_B=(s16)val; break; + case H_Reverb+4 : spu->rvb[0].IIR_ALPHA=(s16)val; break; + case H_Reverb+6 : spu->rvb[0].ACC_COEF_A=(s16)val; break; + case H_Reverb+8 : spu->rvb[0].ACC_COEF_B=(s16)val; break; + case H_Reverb+10 : spu->rvb[0].ACC_COEF_C=(s16)val; break; + case H_Reverb+12 : spu->rvb[0].ACC_COEF_D=(s16)val; break; + case H_Reverb+14 : spu->rvb[0].IIR_COEF=(s16)val; break; + case H_Reverb+16 : spu->rvb[0].FB_ALPHA=(s16)val; break; + case H_Reverb+18 : spu->rvb[0].FB_X=(s16)val; break; + case H_Reverb+20 : spu->rvb[0].IIR_DEST_A0=(s16)val; break; + case H_Reverb+22 : spu->rvb[0].IIR_DEST_A1=(s16)val; break; + case H_Reverb+24 : spu->rvb[0].ACC_SRC_A0=(s16)val; break; + case H_Reverb+26 : spu->rvb[0].ACC_SRC_A1=(s16)val; break; + case H_Reverb+28 : spu->rvb[0].ACC_SRC_B0=(s16)val; break; + case H_Reverb+30 : spu->rvb[0].ACC_SRC_B1=(s16)val; break; + case H_Reverb+32 : spu->rvb[0].IIR_SRC_A0=(s16)val; break; + case H_Reverb+34 : spu->rvb[0].IIR_SRC_A1=(s16)val; break; + case H_Reverb+36 : spu->rvb[0].IIR_DEST_B0=(s16)val; break; + case H_Reverb+38 : spu->rvb[0].IIR_DEST_B1=(s16)val; break; + case H_Reverb+40 : spu->rvb[0].ACC_SRC_C0=(s16)val; break; + case H_Reverb+42 : spu->rvb[0].ACC_SRC_C1=(s16)val; break; + case H_Reverb+44 : spu->rvb[0].ACC_SRC_D0=(s16)val; break; + case H_Reverb+46 : spu->rvb[0].ACC_SRC_D1=(s16)val; break; + case H_Reverb+48 : spu->rvb[0].IIR_SRC_B1=(s16)val; break; + case H_Reverb+50 : spu->rvb[0].IIR_SRC_B0=(s16)val; break; + case H_Reverb+52 : spu->rvb[0].MIX_DEST_A0=(s16)val; break; + case H_Reverb+54 : spu->rvb[0].MIX_DEST_A1=(s16)val; break; + case H_Reverb+56 : spu->rvb[0].MIX_DEST_B0=(s16)val; break; + case H_Reverb+58 : spu->rvb[0].MIX_DEST_B1=(s16)val; break; + case H_Reverb+60 : spu->rvb[0].IN_COEF_L=(s16)val; break; + case H_Reverb+62 : spu->rvb[0].IN_COEF_R=(s16)val; break; + } +} + +EXPORT_GCC unsigned short CALLBACK SPU2readPS1Port(mips_cpu_context *cpu, unsigned long reg) +{ + spu2_state_t *spu = cpu->spu2; + const u32 r=reg&0xfff; + + if(r>=0x0c00 && r<0x0d80) + { + return SPU2read(cpu, r-0xc00); + } + + switch(r) + { +// case H_SPUctrl: +// return spuCtrl; + break; + + case H_SPUstat: + return spu->spuStat2[0]; + break; + + case H_SPUaddr: + return (u16)(spu->spuAddr2[0]>>2); + break; + + case H_SPUdata: + { + u16 s=BFLIP16(spu->spuMem[spu->spuAddr2[0]]); + spu->spuAddr2[0]++; + if(spu->spuAddr2[0]>0xfffff) spu->spuAddr2[0]=0; + return s; + } + break; + + case H_SPUirqAddr: + return spu->spuIrq2[0]>>2; + break; + } + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// SOUND ON register write +//////////////////////////////////////////////////////////////////////// + +void SoundOn(spu2_state_t *spu, int start,int end,unsigned short val) // SOUND ON PSX COMAND +{ + int ch; + + for(ch=start;ch<end;ch++,val>>=1) // loop channels + { + if((val&1) && spu->s_chan[ch].pStart) // mmm... start has to be set before key on !?! + { + spu->s_chan[ch].bIgnoreLoop=0; + spu->s_chan[ch].bNew=1; + spu->dwNewChannel2[ch/24]|=(1<<(ch%24)); // bitfield for faster testing + } + } +} + +//////////////////////////////////////////////////////////////////////// +// SOUND OFF register write +//////////////////////////////////////////////////////////////////////// + +void SoundOff(spu2_state_t *spu, int start,int end,unsigned short val) // SOUND OFF PSX COMMAND +{ + int ch; + for(ch=start;ch<end;ch++,val>>=1) // loop channels + { + if(val&1) // && spu->s_chan[i].bOn) mmm... + { + spu->s_chan[ch].bStop=1; + } + } +} + +//////////////////////////////////////////////////////////////////////// +// FMOD register write +//////////////////////////////////////////////////////////////////////// + +void FModOn(spu2_state_t *spu, int start,int end,unsigned short val) // FMOD ON PSX COMMAND +{ + int ch; + + for(ch=start;ch<end;ch++,val>>=1) // loop channels + { + if(val&1) // -> fmod on/off + { + if(ch>0) + { + spu->s_chan[ch].bFMod=1; // --> sound channel + spu->s_chan[ch-1].bFMod=2; // --> freq channel + } + } + else + { + spu->s_chan[ch].bFMod=0; // --> turn off fmod + } + } +} + +//////////////////////////////////////////////////////////////////////// +// NOISE register write +//////////////////////////////////////////////////////////////////////// + +void NoiseOn(spu2_state_t *spu, int start,int end,unsigned short val) // NOISE ON PSX COMMAND +{ + int ch; + + for(ch=start;ch<end;ch++,val>>=1) // loop channels + { + if(val&1) // -> noise on/off + { + spu->s_chan[ch].bNoise=1; + } + else + { + spu->s_chan[ch].bNoise=0; + } + } +} + +//////////////////////////////////////////////////////////////////////// +// LEFT VOLUME register write +//////////////////////////////////////////////////////////////////////// + +// please note: sweep and phase invert are wrong... but I've never seen +// them used + +void SetVolumeL(spu2_state_t *spu, unsigned char ch,short vol) // LEFT VOLUME +{ + spu->s_chan[ch].iLeftVolRaw=vol; + + if(vol&0x8000) // sweep? + { + short sInc=1; // -> sweep up? + if(vol&0x2000) sInc=-1; // -> or down? + if(vol&0x1000) vol^=0xffff; // -> mmm... phase inverted? have to investigate this + vol=((vol&0x7f)+1)/2; // -> sweep: 0..127 -> 0..64 + vol+=vol/(2*sInc); // -> HACK: we don't sweep right now, so we just raise/lower the volume by the half! + vol*=128; + } + else // no sweep: + { + if(vol&0x4000) // -> mmm... phase inverted? have to investigate this + //vol^=0xffff; + vol=0x3fff-(vol&0x3fff); + } + + vol&=0x3fff; + spu->s_chan[ch].iLeftVolume=vol; // store volume +} + +//////////////////////////////////////////////////////////////////////// +// RIGHT VOLUME register write +//////////////////////////////////////////////////////////////////////// + +void SetVolumeR(spu2_state_t *spu, unsigned char ch,short vol) // RIGHT VOLUME +{ + spu->s_chan[ch].iRightVolRaw=vol; + + if(vol&0x8000) // comments... see above :) + { + short sInc=1; + if(vol&0x2000) sInc=-1; + if(vol&0x1000) vol^=0xffff; + vol=((vol&0x7f)+1)/2; + vol+=vol/(2*sInc); + vol*=128; + } + else + { + if(vol&0x4000) //vol=vol^=0xffff; + vol=0x3fff-(vol&0x3fff); + } + + vol&=0x3fff; + spu->s_chan[ch].iRightVolume=vol; +} + +//////////////////////////////////////////////////////////////////////// +// PITCH register write +//////////////////////////////////////////////////////////////////////// + +void SetPitch(spu2_state_t *spu, int ch,unsigned short val) // SET PITCH +{ + int NP; + double intr; + + if(val>0x3fff) NP=0x3fff; // get pitch val + else NP=val; + + intr = (double)48000.0f / (double)44100.0f * (double)NP; + NP = (UINT32)intr; + + spu->s_chan[ch].iRawPitch=NP; + + NP=(44100L*NP)/4096L; // calc frequency + + if(NP<1) NP=1; // some security + spu->s_chan[ch].iActFreq=NP; // store frequency +} + +//////////////////////////////////////////////////////////////////////// +// REVERB register write +//////////////////////////////////////////////////////////////////////// + +void ReverbOn(spu2_state_t *spu, int start,int end,unsigned short val,int iRight) // REVERB ON PSX COMMAND +{ + int ch; + + for(ch=start;ch<end;ch++,val>>=1) // loop channels + { + if(val&1) // -> reverb on/off + { + if(iRight) spu->s_chan[ch].bReverbR=1; + else spu->s_chan[ch].bReverbL=1; + } + else + { + if(iRight) spu->s_chan[ch].bReverbR=0; + else spu->s_chan[ch].bReverbL=0; + } + } +} + +//////////////////////////////////////////////////////////////////////// +// REVERB START register write +//////////////////////////////////////////////////////////////////////// + +void SetReverbAddr(spu2_state_t *spu, int core) +{ + long val=spu->spuRvbAddr2[core]; + + if(spu->rvb[core].StartAddr!=val) + { + if(val<=0x27ff) + { + spu->rvb[core].StartAddr=spu->rvb[core].CurrAddr=0; + } + else + { + spu->rvb[core].StartAddr=val; + spu->rvb[core].CurrAddr=spu->rvb[core].StartAddr; + } + } +} + +//////////////////////////////////////////////////////////////////////// +// DRY LEFT/RIGHT per voice switches +//////////////////////////////////////////////////////////////////////// + +void VolumeOn(spu2_state_t *spu, int start,int end,unsigned short val,int iRight) // VOLUME ON PSX COMMAND +{ + int ch; + + for(ch=start;ch<end;ch++,val>>=1) // loop channels + { + if(val&1) // -> reverb on/off + { + if(iRight) spu->s_chan[ch].bVolumeR=1; + else spu->s_chan[ch].bVolumeL=1; + } + else + { + if(iRight) spu->s_chan[ch].bVolumeR=0; + else spu->s_chan[ch].bVolumeL=0; + } + } +} + + diff --git a/plugins/ao/eng_psf/peops2/regs.h b/plugins/ao/eng_psf/peops2/regs.h new file mode 100644 index 00000000..0e795ed7 --- /dev/null +++ b/plugins/ao/eng_psf/peops2/regs.h @@ -0,0 +1,44 @@ +/***************************************************************************
+ regs.h - description
+ -------------------
+ begin : Wed May 15 2002
+ copyright : (C) 2002 by Pete Bernert
+ email : BlackDove@addcom.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+//*************************************************************************//
+// History of changes:
+//
+// 2004/04/04 - Pete
+// - changed plugin to emulate PS2 spu
+//
+// 2002/05/15 - Pete
+// - generic cleanup for the Peops release
+//
+//*************************************************************************//
+
+struct spu2_state_s;
+
+void SoundOn(struct spu2_state_s *spu, int start,int end,unsigned short val);
+void SoundOff(struct spu2_state_s *spu, int start,int end,unsigned short val);
+void VolumeOn(struct spu2_state_s *spu, int start,int end,unsigned short val,int iRight);
+void FModOn(struct spu2_state_s *spu, int start,int end,unsigned short val);
+void NoiseOn(struct spu2_state_s *spu, int start,int end,unsigned short val);
+void SetVolumeL(struct spu2_state_s *spu, unsigned char ch,short vol);
+void SetVolumeR(struct spu2_state_s *spu, unsigned char ch,short vol);
+void SetPitch(struct spu2_state_s *spu, int ch,unsigned short val);
+void ReverbOn(struct spu2_state_s *spu, int start,int end,unsigned short val,int iRight);
+void SetReverbAddr(struct spu2_state_s *spu, int core);
+
+//EXPORT_GCC void CALLBACK SPU2write(unsigned long reg, unsigned short val);
+
diff --git a/plugins/ao/eng_psf/peops2/reverb.h b/plugins/ao/eng_psf/peops2/reverb.h new file mode 100755 index 00000000..5305030c --- /dev/null +++ b/plugins/ao/eng_psf/peops2/reverb.h @@ -0,0 +1,33 @@ +/***************************************************************************
+ reverb.h - description
+ -------------------
+ begin : Wed May 15 2002
+ copyright : (C) 2002 by Pete Bernert
+ email : BlackDove@addcom.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+//*************************************************************************//
+// History of changes:
+//
+// 2004/04/04 - Pete
+// - changed plugin to emulate PS2 spu
+//
+// 2002/05/15 - Pete
+// - generic cleanup for the Peops release
+//
+//*************************************************************************//
+
+
+INLINE void StartREVERB(int ch);
+INLINE void StoreREVERB(int ch,int ns);
+
diff --git a/plugins/ao/eng_psf/peops2/reverb2.c b/plugins/ao/eng_psf/peops2/reverb2.c new file mode 100644 index 00000000..ceab8c54 --- /dev/null +++ b/plugins/ao/eng_psf/peops2/reverb2.c @@ -0,0 +1,414 @@ +/***************************************************************************
+ reverb.c - description
+ -------------------
+ begin : Wed May 15 2002
+ copyright : (C) 2002 by Pete Bernert
+ email : BlackDove@addcom.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+//*************************************************************************//
+// History of changes:
+//
+// 2004/04/04 - Pete
+// - changed to SPU2 functionality
+//
+// 2003/01/19 - Pete
+// - added Neill's reverb (see at the end of file)
+//
+// 2002/12/26 - Pete
+// - adjusted reverb handling
+//
+// 2002/08/14 - Pete
+// - added extra reverb
+//
+// 2002/05/15 - Pete
+// - generic cleanup for the Peops release
+//
+//*************************************************************************//
+
+#include "stdafx.h"
+
+#define _IN_REVERB
+
+// will be included from spu.c
+#ifdef _IN_SPU
+
+////////////////////////////////////////////////////////////////////////
+// globals
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+// START REVERB
+////////////////////////////////////////////////////////////////////////
+
+INLINE void StartREVERB(spu2_state_t *spu, int ch)
+{
+ int core=ch/24;
+
+ if((spu->s_chan[ch].bReverbL || spu->s_chan[ch].bReverbR) && (spu->spuCtrl2[core]&0x80)) // reverb possible?
+ {
+ if(spu->iUseReverb==1) spu->s_chan[ch].bRVBActive=1;
+ }
+ else spu->s_chan[ch].bRVBActive=0; // else -> no reverb
+}
+
+////////////////////////////////////////////////////////////////////////
+// HELPER FOR NEILL'S REVERB: re-inits our reverb mixing buf
+////////////////////////////////////////////////////////////////////////
+
+INLINE void InitREVERB(spu2_state_t *spu)
+{
+ if(spu->iUseReverb==1)
+ {
+ memset(spu->sRVBStart[0],0,NSSIZE*2*4);
+ memset(spu->sRVBStart[1],0,NSSIZE*2*4);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+// STORE REVERB
+////////////////////////////////////////////////////////////////////////
+
+INLINE void StoreREVERB(spu2_state_t *spu, int ch,int ns)
+{
+ int core=ch/24;
+
+ if(spu->iUseReverb==0) return;
+ else
+ if(spu->iUseReverb==1) // -------------------------------- // Neil's reverb
+ {
+ const int iRxl=(spu->s_chan[ch].sval*spu->s_chan[ch].iLeftVolume*spu->s_chan[ch].bReverbL)/0x4000;
+ const int iRxr=(spu->s_chan[ch].sval*spu->s_chan[ch].iRightVolume*spu->s_chan[ch].bReverbR)/0x4000;
+
+ ns<<=1;
+
+ *(spu->sRVBStart[core]+ns) +=iRxl; // -> we mix all active reverb channels into an extra buffer
+ *(spu->sRVBStart[core]+ns+1)+=iRxr;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+
+INLINE int g_buffer(spu2_state_t *spu, int iOff,int core) // get_buffer content helper: takes care about wraps
+{
+ short * p=(short *)spu->spuMem;
+ iOff=(iOff)+spu->rvb[core].CurrAddr;
+ while(iOff>spu->rvb[core].EndAddr) iOff=spu->rvb[core].StartAddr+(iOff-(spu->rvb[core].EndAddr+1));
+ while(iOff<spu->rvb[core].StartAddr) iOff=spu->rvb[core].EndAddr-(spu->rvb[core].StartAddr-iOff);
+ return (int)*(p+iOff);
+}
+
+////////////////////////////////////////////////////////////////////////
+
+INLINE void s_buffer(spu2_state_t *spu, int iOff,int iVal,int core) // set_buffer content helper: takes care about wraps and clipping
+{
+ short * p=(short *)spu->spuMem;
+ iOff=(iOff)+spu->rvb[core].CurrAddr;
+ while(iOff>spu->rvb[core].EndAddr) iOff=spu->rvb[core].StartAddr+(iOff-(spu->rvb[core].EndAddr+1));
+ while(iOff<spu->rvb[core].StartAddr) iOff=spu->rvb[core].EndAddr-(spu->rvb[core].StartAddr-iOff);
+ if(iVal<-32768L) iVal=-32768L;if(iVal>32767L) iVal=32767L;
+ *(p+iOff)=(short)iVal;
+}
+
+////////////////////////////////////////////////////////////////////////
+
+INLINE void s_buffer1(spu2_state_t *spu, int iOff,int iVal,int core) // set_buffer (+1 sample) content helper: takes care about wraps and clipping
+{
+ short * p=(short *)spu->spuMem;
+ iOff=(iOff)+spu->rvb[core].CurrAddr+1;
+ while(iOff>spu->rvb[core].EndAddr) iOff=spu->rvb[core].StartAddr+(iOff-(spu->rvb[core].EndAddr+1));
+ while(iOff<spu->rvb[core].StartAddr) iOff=spu->rvb[core].EndAddr-(spu->rvb[core].StartAddr-iOff);
+ if(iVal<-32768L) iVal=-32768L;if(iVal>32767L) iVal=32767L;
+ *(p+iOff)=(short)iVal;
+}
+
+////////////////////////////////////////////////////////////////////////
+
+INLINE int MixREVERBLeft(spu2_state_t *spu, int ns,int core)
+{
+ if(spu->iUseReverb==1)
+ {
+ if(!spu->rvb[core].StartAddr || !spu->rvb[core].EndAddr ||
+ spu->rvb[core].StartAddr>=spu->rvb[core].EndAddr) // reverb is off
+ {
+ spu->rvb[core].iLastRVBLeft=spu->rvb[core].iLastRVBRight=spu->rvb[core].iRVBLeft=spu->rvb[core].iRVBRight=0;
+ return 0;
+ }
+
+ spu->rvb[core].iCnt++;
+
+ if(spu->rvb[core].iCnt&1) // we work on every second left value: downsample to 22 khz
+ {
+ if((spu->spuCtrl2[core]&0x80)) // -> reverb on? oki
+ {
+ int ACC0,ACC1,FB_A0,FB_A1,FB_B0,FB_B1;
+
+ const int INPUT_SAMPLE_L=*(spu->sRVBStart[core]+(ns<<1));
+ const int INPUT_SAMPLE_R=*(spu->sRVBStart[core]+(ns<<1)+1);
+
+ const int IIR_INPUT_A0 = (g_buffer(spu, spu->rvb[core].IIR_SRC_A0,core) * spu->rvb[core].IIR_COEF)/32768L + (INPUT_SAMPLE_L * spu->rvb[core].IN_COEF_L)/32768L;
+ const int IIR_INPUT_A1 = (g_buffer(spu, spu->rvb[core].IIR_SRC_A1,core) * spu->rvb[core].IIR_COEF)/32768L + (INPUT_SAMPLE_R * spu->rvb[core].IN_COEF_R)/32768L;
+ const int IIR_INPUT_B0 = (g_buffer(spu, spu->rvb[core].IIR_SRC_B0,core) * spu->rvb[core].IIR_COEF)/32768L + (INPUT_SAMPLE_L * spu->rvb[core].IN_COEF_L)/32768L;
+ const int IIR_INPUT_B1 = (g_buffer(spu, spu->rvb[core].IIR_SRC_B1,core) * spu->rvb[core].IIR_COEF)/32768L + (INPUT_SAMPLE_R * spu->rvb[core].IN_COEF_R)/32768L;
+
+ const int IIR_A0 = (IIR_INPUT_A0 * spu->rvb[core].IIR_ALPHA)/32768L + (g_buffer(spu, spu->rvb[core].IIR_DEST_A0,core) * (32768L - spu->rvb[core].IIR_ALPHA))/32768L;
+ const int IIR_A1 = (IIR_INPUT_A1 * spu->rvb[core].IIR_ALPHA)/32768L + (g_buffer(spu, spu->rvb[core].IIR_DEST_A1,core) * (32768L - spu->rvb[core].IIR_ALPHA))/32768L;
+ const int IIR_B0 = (IIR_INPUT_B0 * spu->rvb[core].IIR_ALPHA)/32768L + (g_buffer(spu, spu->rvb[core].IIR_DEST_B0,core) * (32768L - spu->rvb[core].IIR_ALPHA))/32768L;
+ const int IIR_B1 = (IIR_INPUT_B1 * spu->rvb[core].IIR_ALPHA)/32768L + (g_buffer(spu, spu->rvb[core].IIR_DEST_B1,core) * (32768L - spu->rvb[core].IIR_ALPHA))/32768L;
+
+ s_buffer1(spu, spu->rvb[core].IIR_DEST_A0, IIR_A0,core);
+ s_buffer1(spu, spu->rvb[core].IIR_DEST_A1, IIR_A1,core);
+ s_buffer1(spu, spu->rvb[core].IIR_DEST_B0, IIR_B0,core);
+ s_buffer1(spu, spu->rvb[core].IIR_DEST_B1, IIR_B1,core);
+
+ ACC0 = (g_buffer(spu, spu->rvb[core].ACC_SRC_A0,core) * spu->rvb[core].ACC_COEF_A)/32768L +
+ (g_buffer(spu, spu->rvb[core].ACC_SRC_B0,core) * spu->rvb[core].ACC_COEF_B)/32768L +
+ (g_buffer(spu, spu->rvb[core].ACC_SRC_C0,core) * spu->rvb[core].ACC_COEF_C)/32768L +
+ (g_buffer(spu, spu->rvb[core].ACC_SRC_D0,core) * spu->rvb[core].ACC_COEF_D)/32768L;
+ ACC1 = (g_buffer(spu, spu->rvb[core].ACC_SRC_A1,core) * spu->rvb[core].ACC_COEF_A)/32768L +
+ (g_buffer(spu, spu->rvb[core].ACC_SRC_B1,core) * spu->rvb[core].ACC_COEF_B)/32768L +
+ (g_buffer(spu, spu->rvb[core].ACC_SRC_C1,core) * spu->rvb[core].ACC_COEF_C)/32768L +
+ (g_buffer(spu, spu->rvb[core].ACC_SRC_D1,core) * spu->rvb[core].ACC_COEF_D)/32768L;
+
+ FB_A0 = g_buffer(spu, spu->rvb[core].MIX_DEST_A0 - spu->rvb[core].FB_SRC_A,core);
+ FB_A1 = g_buffer(spu, spu->rvb[core].MIX_DEST_A1 - spu->rvb[core].FB_SRC_A,core);
+ FB_B0 = g_buffer(spu, spu->rvb[core].MIX_DEST_B0 - spu->rvb[core].FB_SRC_B,core);
+ FB_B1 = g_buffer(spu, spu->rvb[core].MIX_DEST_B1 - spu->rvb[core].FB_SRC_B,core);
+
+ s_buffer(spu, spu->rvb[core].MIX_DEST_A0, ACC0 - (FB_A0 * spu->rvb[core].FB_ALPHA)/32768L,core);
+ s_buffer(spu, spu->rvb[core].MIX_DEST_A1, ACC1 - (FB_A1 * spu->rvb[core].FB_ALPHA)/32768L,core);
+
+ s_buffer(spu, spu->rvb[core].MIX_DEST_B0, (spu->rvb[core].FB_ALPHA * ACC0)/32768L - (FB_A0 * (int)(spu->rvb[core].FB_ALPHA^0xFFFF8000))/32768L - (FB_B0 * spu->rvb[core].FB_X)/32768L,core);
+ s_buffer(spu, spu->rvb[core].MIX_DEST_B1, (spu->rvb[core].FB_ALPHA * ACC1)/32768L - (FB_A1 * (int)(spu->rvb[core].FB_ALPHA^0xFFFF8000))/32768L - (FB_B1 * spu->rvb[core].FB_X)/32768L,core);
+
+ spu->rvb[core].iLastRVBLeft = spu->rvb[core].iRVBLeft;
+ spu->rvb[core].iLastRVBRight = spu->rvb[core].iRVBRight;
+
+ spu->rvb[core].iRVBLeft = (g_buffer(spu, spu->rvb[core].MIX_DEST_A0,core)+g_buffer(spu, spu->rvb[core].MIX_DEST_B0,core))/3;
+ spu->rvb[core].iRVBRight = (g_buffer(spu, spu->rvb[core].MIX_DEST_A1,core)+g_buffer(spu, spu->rvb[core].MIX_DEST_B1,core))/3;
+
+ spu->rvb[core].iRVBLeft = (spu->rvb[core].iRVBLeft * spu->rvb[core].VolLeft) / 0x4000;
+ spu->rvb[core].iRVBRight = (spu->rvb[core].iRVBRight * spu->rvb[core].VolRight) / 0x4000;
+
+ spu->rvb[core].CurrAddr++;
+ if(spu->rvb[core].CurrAddr>spu->rvb[core].EndAddr) spu->rvb[core].CurrAddr=spu->rvb[core].StartAddr;
+
+ return spu->rvb[core].iLastRVBLeft+(spu->rvb[core].iRVBLeft-spu->rvb[core].iLastRVBLeft)/2;
+ }
+ else // -> reverb off
+ {
+ spu->rvb[core].iLastRVBLeft=spu->rvb[core].iLastRVBRight=spu->rvb[core].iRVBLeft=spu->rvb[core].iRVBRight=0;
+ }
+
+ spu->rvb[core].CurrAddr++;
+ if(spu->rvb[core].CurrAddr>spu->rvb[core].EndAddr) spu->rvb[core].CurrAddr=spu->rvb[core].StartAddr;
+ }
+
+ return spu->rvb[core].iLastRVBLeft;
+ }
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+
+INLINE int MixREVERBRight(spu2_state_t *spu, int core)
+{
+ if(spu->iUseReverb==1) // Neill's reverb:
+ {
+ int i=spu->rvb[core].iLastRVBRight+(spu->rvb[core].iRVBRight-spu->rvb[core].iLastRVBRight)/2;
+ spu->rvb[core].iLastRVBRight=spu->rvb[core].iRVBRight;
+ return i; // -> just return the last right reverb val (little bit scaled by the previous right val)
+ }
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+
+#endif
+
+/*
+-----------------------------------------------------------------------------
+PSX reverb hardware notes
+by Neill Corlett
+-----------------------------------------------------------------------------
+
+Yadda yadda disclaimer yadda probably not perfect yadda well it's okay anyway
+yadda yadda.
+
+-----------------------------------------------------------------------------
+
+Basics
+------
+
+- The reverb buffer is 22khz 16-bit mono PCM.
+- It starts at the reverb address given by 1DA2, extends to
+ the end of sound RAM, and wraps back to the 1DA2 address.
+
+Setting the address at 1DA2 resets the current reverb work address.
+
+This work address ALWAYS increments every 1/22050 sec., regardless of
+whether reverb is enabled (bit 7 of 1DAA set).
+
+And the contents of the reverb buffer ALWAYS play, scaled by the
+"reverberation depth left/right" volumes (1D84/1D86).
+(which, by the way, appear to be scaled so 3FFF=approx. 1.0, 4000=-1.0)
+
+-----------------------------------------------------------------------------
+
+Register names
+--------------
+
+These are probably not their real names.
+These are probably not even correct names.
+We will use them anyway, because we can.
+
+1DC0: FB_SRC_A (offset)
+1DC2: FB_SRC_B (offset)
+1DC4: IIR_ALPHA (coef.)
+1DC6: ACC_COEF_A (coef.)
+1DC8: ACC_COEF_B (coef.)
+1DCA: ACC_COEF_C (coef.)
+1DCC: ACC_COEF_D (coef.)
+1DCE: IIR_COEF (coef.)
+1DD0: FB_ALPHA (coef.)
+1DD2: FB_X (coef.)
+1DD4: IIR_DEST_A0 (offset)
+1DD6: IIR_DEST_A1 (offset)
+1DD8: ACC_SRC_A0 (offset)
+1DDA: ACC_SRC_A1 (offset)
+1DDC: ACC_SRC_B0 (offset)
+1DDE: ACC_SRC_B1 (offset)
+1DE0: IIR_SRC_A0 (offset)
+1DE2: IIR_SRC_A1 (offset)
+1DE4: IIR_DEST_B0 (offset)
+1DE6: IIR_DEST_B1 (offset)
+1DE8: ACC_SRC_C0 (offset)
+1DEA: ACC_SRC_C1 (offset)
+1DEC: ACC_SRC_D0 (offset)
+1DEE: ACC_SRC_D1 (offset)
+1DF0: IIR_SRC_B1 (offset)
+1DF2: IIR_SRC_B0 (offset)
+1DF4: MIX_DEST_A0 (offset)
+1DF6: MIX_DEST_A1 (offset)
+1DF8: MIX_DEST_B0 (offset)
+1DFA: MIX_DEST_B1 (offset)
+1DFC: IN_COEF_L (coef.)
+1DFE: IN_COEF_R (coef.)
+
+The coefficients are signed fractional values.
+-32768 would be -1.0
+ 32768 would be 1.0 (if it were possible... the highest is of course 32767)
+
+The offsets are (byte/8) offsets into the reverb buffer.
+i.e. you multiply them by 8, you get byte offsets.
+You can also think of them as (samples/4) offsets.
+They appear to be signed. They can be negative.
+None of the documented presets make them negative, though.
+
+Yes, 1DF0 and 1DF2 appear to be backwards. Not a typo.
+
+-----------------------------------------------------------------------------
+
+What it does
+------------
+
+We take all reverb sources:
+- regular channels that have the reverb bit on
+- cd and external sources, if their reverb bits are on
+and mix them into one stereo 44100hz signal.
+
+Lowpass/downsample that to 22050hz. The PSX uses a proper bandlimiting
+algorithm here, but I haven't figured out the hysterically exact specifics.
+I use an 8-tap filter with these coefficients, which are nice but probably
+not the real ones:
+
+0.037828187894
+0.157538631280
+0.321159685278
+0.449322115345
+0.449322115345
+0.321159685278
+0.157538631280
+0.037828187894
+
+So we have two input samples (INPUT_SAMPLE_L, INPUT_SAMPLE_R) every 22050hz.
+
+* IN MY EMULATION, I divide these by 2 to make it clip less.
+ (and of course the L/R output coefficients are adjusted to compensate)
+ The real thing appears to not do this.
+
+At every 22050hz tick:
+- If the reverb bit is enabled (bit 7 of 1DAA), execute the reverb
+ steady-state algorithm described below
+- AFTERWARDS, retrieve the "wet out" L and R samples from the reverb buffer
+ (This part may not be exactly right and I guessed at the coefs. TODO: check later.)
+ L is: 0.333 * (buffer[MIX_DEST_A0] + buffer[MIX_DEST_B0])
+ R is: 0.333 * (buffer[MIX_DEST_A1] + buffer[MIX_DEST_B1])
+- Advance the current buffer position by 1 sample
+
+The wet out L and R are then upsampled to 44100hz and played at the
+"reverberation depth left/right" (1D84/1D86) volume, independent of the main
+volume.
+
+-----------------------------------------------------------------------------
+
+Reverb steady-state
+-------------------
+
+The reverb steady-state algorithm is fairly clever, and of course by
+"clever" I mean "batshit insane".
+
+buffer[x] is relative to the current buffer position, not the beginning of
+the buffer. Note that all buffer offsets must wrap around so they're
+contained within the reverb work area.
+
+Clipping is performed at the end... maybe also sooner, but definitely at
+the end.
+
+IIR_INPUT_A0 = buffer[IIR_SRC_A0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L;
+IIR_INPUT_A1 = buffer[IIR_SRC_A1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R;
+IIR_INPUT_B0 = buffer[IIR_SRC_B0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L;
+IIR_INPUT_B1 = buffer[IIR_SRC_B1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R;
+
+IIR_A0 = IIR_INPUT_A0 * IIR_ALPHA + buffer[IIR_DEST_A0] * (1.0 - IIR_ALPHA);
+IIR_A1 = IIR_INPUT_A1 * IIR_ALPHA + buffer[IIR_DEST_A1] * (1.0 - IIR_ALPHA);
+IIR_B0 = IIR_INPUT_B0 * IIR_ALPHA + buffer[IIR_DEST_B0] * (1.0 - IIR_ALPHA);
+IIR_B1 = IIR_INPUT_B1 * IIR_ALPHA + buffer[IIR_DEST_B1] * (1.0 - IIR_ALPHA);
+
+buffer[IIR_DEST_A0 + 1sample] = IIR_A0;
+buffer[IIR_DEST_A1 + 1sample] = IIR_A1;
+buffer[IIR_DEST_B0 + 1sample] = IIR_B0;
+buffer[IIR_DEST_B1 + 1sample] = IIR_B1;
+
+ACC0 = buffer[ACC_SRC_A0] * ACC_COEF_A +
+ buffer[ACC_SRC_B0] * ACC_COEF_B +
+ buffer[ACC_SRC_C0] * ACC_COEF_C +
+ buffer[ACC_SRC_D0] * ACC_COEF_D;
+ACC1 = buffer[ACC_SRC_A1] * ACC_COEF_A +
+ buffer[ACC_SRC_B1] * ACC_COEF_B +
+ buffer[ACC_SRC_C1] * ACC_COEF_C +
+ buffer[ACC_SRC_D1] * ACC_COEF_D;
+
+FB_A0 = buffer[MIX_DEST_A0 - FB_SRC_A];
+FB_A1 = buffer[MIX_DEST_A1 - FB_SRC_A];
+FB_B0 = buffer[MIX_DEST_B0 - FB_SRC_B];
+FB_B1 = buffer[MIX_DEST_B1 - FB_SRC_B];
+
+buffer[MIX_DEST_A0] = ACC0 - FB_A0 * FB_ALPHA;
+buffer[MIX_DEST_A1] = ACC1 - FB_A1 * FB_ALPHA;
+buffer[MIX_DEST_B0] = (FB_ALPHA * ACC0) - FB_A0 * (FB_ALPHA^0x8000) - FB_B0 * FB_X;
+buffer[MIX_DEST_B1] = (FB_ALPHA * ACC1) - FB_A1 * (FB_ALPHA^0x8000) - FB_B1 * FB_X;
+
+-----------------------------------------------------------------------------
+*/
+
diff --git a/plugins/ao/eng_psf/peops2/spu.h b/plugins/ao/eng_psf/peops2/spu.h new file mode 100644 index 00000000..0400e306 --- /dev/null +++ b/plugins/ao/eng_psf/peops2/spu.h @@ -0,0 +1,109 @@ +/*************************************************************************** + spu.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2004/04/04 - Pete +// - changed plugin to emulate PS2 spu +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#include "../psx.h" + +typedef struct spu2_state_s { + // psx buffer / addresses + + unsigned short regArea[32*1024]; + unsigned short spuMem[1*1024*1024]; + unsigned char * spuMemC; + unsigned char * pSpuIrq[2]; + unsigned char * pSpuBuffer; + + // user settings + + int iUseXA;//=0; + int iVolume;//=3; + int iXAPitch;//=1; + int iUseTimer;//=2; + int iSPUIRQWait;//=1; + int iDebugMode;//=0; + int iRecordMode;//=0; + int iUseReverb;//=1; + int iUseInterpolation;//=2; + + // MAIN infos struct for each channel + + SPUCHAN s_chan[MAXCHAN+1]; // channel + 1 infos (1 is security for fmod handling) + REVERBInfo rvb[2]; + + unsigned long dwNoiseVal;//=1; // global noise generator + + unsigned short spuCtrl2[2]; // some vars to store psx reg infos + unsigned short spuStat2[2]; + unsigned long spuIrq2[2]; + unsigned long spuAddr2[2]; // address into spu mem + unsigned long spuRvbAddr2[2]; + unsigned long spuRvbAEnd2[2]; + int bEndThread; // thread handlers + int bThreadEnded; + int bSpuInit; + int bSPUIsOpen; + + unsigned long dwNewChannel2[2]; // flags for faster testing, if new channel starts + unsigned long dwEndChannel2[2]; + + // UNUSED IN PS2 YET + void (CALLBACK *irqCallback)(void); // func of main emu, called on spu irq + void (CALLBACK *cddavCallback)(unsigned short,unsigned short); + + int SSumR[NSSIZE]; + int SSumL[NSSIZE]; + int iCycle; + short * pS; + + int lastch;//=-1; // last channel processed on spu irq in timer mode + int lastns; // last ns pos + int iSecureStart; // secure start counter + + u32 sampcount; + u32 decaybegin; + u32 decayend; + + // REVERB info and timing vars... + int * sRVBPlay[2]; + int * sRVBEnd[2]; + int * sRVBStart[2]; + + int iSpuAsyncWait; +} spu2_state_t; + + +//void SetupTimer(mips_cpu_context *cpu); +//void RemoveTimer(mips_cpu_context *cpu); +//EXPORT_GCC void CALLBACK SPU2playADPCMchannel(mips_cpu_context *cpu, xa_decode_t *xap); + +EXPORT_GCC long CALLBACK SPU2init(mips_cpu_context *cpu, void (*callback)(unsigned char *, long, void *), void *data); +EXPORT_GCC long CALLBACK SPU2open(mips_cpu_context *cpu, void *pDsp); +EXPORT_GCC void CALLBACK SPU2async(mips_cpu_context *cpu, unsigned long cycle); +EXPORT_GCC void CALLBACK SPU2close(mips_cpu_context *cpu); +void setlength2(spu2_state_t *spu, s32 stop, s32 fade); + diff --git a/plugins/ao/eng_psf/peops2/spu2.c b/plugins/ao/eng_psf/peops2/spu2.c new file mode 100644 index 00000000..5b7ae050 --- /dev/null +++ b/plugins/ao/eng_psf/peops2/spu2.c @@ -0,0 +1,981 @@ +/*************************************************************************** + spu.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2005/08/29 - Pete +// - changed to 48Khz output +// +// 2004/12/25 - Pete +// - inc'd version for pcsx2-0.7 +// +// 2004/04/18 - Pete +// - changed all kind of things in the plugin +// +// 2004/04/04 - Pete +// - changed plugin to emulate PS2 spu +// +// 2003/04/07 - Eric +// - adjusted cubic interpolation algorithm +// +// 2003/03/16 - Eric +// - added cubic interpolation +// +// 2003/03/01 - linuzappz +// - libraryName changes using ALSA +// +// 2003/02/28 - Pete +// - added option for type of interpolation +// - adjusted spu irqs again (Thousant Arms, Valkyrie Profile) +// - added MONO support for MSWindows DirectSound +// +// 2003/02/20 - kode54 +// - amended interpolation code, goto GOON could skip initialization of gpos and cause segfault +// +// 2003/02/19 - kode54 +// - moved SPU IRQ handler and changed sample flag processing +// +// 2003/02/18 - kode54 +// - moved ADSR calculation outside of the sample decode loop, somehow I doubt that +// ADSR timing is relative to the frequency at which a sample is played... I guess +// this remains to be seen, and I don't know whether ADSR is applied to noise channels... +// +// 2003/02/09 - kode54 +// - one-shot samples now process the end block before stopping +// - in light of removing fmod hack, now processing ADSR on frequency channel as well +// +// 2003/02/08 - kode54 +// - replaced easy interpolation with gaussian +// - removed fmod averaging hack +// - changed .sinc to be updated from .iRawPitch, no idea why it wasn't done this way already (<- Pete: because I sometimes fail to see the obvious, haharhar :) +// +// 2003/02/08 - linuzappz +// - small bugfix for one usleep that was 1 instead of 1000 +// - added iDisStereo for no stereo (Linux) +// +// 2003/01/22 - Pete +// - added easy interpolation & small noise adjustments +// +// 2003/01/19 - Pete +// - added Neill's reverb +// +// 2003/01/12 - Pete +// - added recording window handlers +// +// 2003/01/06 - Pete +// - added Neill's ADSR timings +// +// 2002/12/28 - Pete +// - adjusted spu irq handling, fmod handling and loop handling +// +// 2002/08/14 - Pete +// - added extra reverb +// +// 2002/06/08 - linuzappz +// - SPUupdate changed for SPUasync +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#include "stdafx.h" + +#define _IN_SPU + +#include "../psx.h" +#include "../peops2/externals.h" +#include "../peops2/regs.h" +#include "../peops2/dma.h" +#include "../peops2/spu.h" + +//////////////////////////////////////////////////////////////////////// +// globals +//////////////////////////////////////////////////////////////////////// + + +// certain globals (were local before, but with the new timeproc I need em global) + +const int f[5][2] = { { 0, 0 }, + { 60, 0 }, + { 115, -52 }, + { 98, -55 }, + { 122, -60 } }; + +//////////////////////////////////////////////////////////////////////// +// CODE AREA +//////////////////////////////////////////////////////////////////////// + +// dirty inline func includes + +#include "reverb2.c" +#include "adsr2.c" + +//////////////////////////////////////////////////////////////////////// +// helpers for simple interpolation + +// +// easy interpolation on upsampling, no special filter, just "Pete's common sense" tm +// +// instead of having n equal sample values in a row like: +// ____ +// |____ +// +// we compare the current delta change with the next delta change. +// +// if curr_delta is positive, +// +// - and next delta is smaller (or changing direction): +// \. +// -__ +// +// - and next delta significant (at least twice) bigger: +// --_ +// \. +// +// - and next delta is nearly same: +// \. +// \. +// +// +// if curr_delta is negative, +// +// - and next delta is smaller (or changing direction): +// _-- +// / +// +// - and next delta significant (at least twice) bigger: +// / +// __- +// +// - and next delta is nearly same: +// / +// / +// + + +INLINE void InterpolateUp(spu2_state_t *spu, int ch) +{ + if(spu->s_chan[ch].SB[32]==1) // flag == 1? calc step and set flag... and don't change the value in this pass + { + const int id1=spu->s_chan[ch].SB[30]-spu->s_chan[ch].SB[29]; // curr delta to next val + const int id2=spu->s_chan[ch].SB[31]-spu->s_chan[ch].SB[30]; // and next delta to next-next val :) + + spu->s_chan[ch].SB[32]=0; + + if(id1>0) // curr delta positive + { + if(id2<id1) + {spu->s_chan[ch].SB[28]=id1;spu->s_chan[ch].SB[32]=2;} + else + if(id2<(id1<<1)) + spu->s_chan[ch].SB[28]=(id1*spu->s_chan[ch].sinc)/0x10000L; + else + spu->s_chan[ch].SB[28]=(id1*spu->s_chan[ch].sinc)/0x20000L; + } + else // curr delta negative + { + if(id2>id1) + {spu->s_chan[ch].SB[28]=id1;spu->s_chan[ch].SB[32]=2;} + else + if(id2>(id1<<1)) + spu->s_chan[ch].SB[28]=(id1*spu->s_chan[ch].sinc)/0x10000L; + else + spu->s_chan[ch].SB[28]=(id1*spu->s_chan[ch].sinc)/0x20000L; + } + } + else + if(spu->s_chan[ch].SB[32]==2) // flag 1: calc step and set flag... and don't change the value in this pass + { + spu->s_chan[ch].SB[32]=0; + + spu->s_chan[ch].SB[28]=(spu->s_chan[ch].SB[28]*spu->s_chan[ch].sinc)/0x20000L; + if(spu->s_chan[ch].sinc<=0x8000) + spu->s_chan[ch].SB[29]=spu->s_chan[ch].SB[30]-(spu->s_chan[ch].SB[28]*((0x10000/spu->s_chan[ch].sinc)-1)); + else spu->s_chan[ch].SB[29]+=spu->s_chan[ch].SB[28]; + } + else // no flags? add bigger val (if possible), calc smaller step, set flag1 + spu->s_chan[ch].SB[29]+=spu->s_chan[ch].SB[28]; +} + +// +// even easier interpolation on downsampling, also no special filter, again just "Pete's common sense" tm +// + +INLINE void InterpolateDown(spu2_state_t *spu, int ch) +{ + if(spu->s_chan[ch].sinc>=0x20000L) // we would skip at least one val? + { + spu->s_chan[ch].SB[29]+=(spu->s_chan[ch].SB[30]-spu->s_chan[ch].SB[29])/2; // add easy weight + if(spu->s_chan[ch].sinc>=0x30000L) // we would skip even more vals? + spu->s_chan[ch].SB[29]+=(spu->s_chan[ch].SB[31]-spu->s_chan[ch].SB[30])/2;// add additional next weight + } +} + +//////////////////////////////////////////////////////////////////////// +// helpers for gauss interpolation + +#define gval0 (((short*)(&spu->s_chan[ch].SB[29]))[gpos]) +#define gval(x) (((short*)(&spu->s_chan[ch].SB[29]))[(gpos+x)&3]) + +#include "gauss_i.h" + +//////////////////////////////////////////////////////////////////////// + +//#include "xa.c" + +//////////////////////////////////////////////////////////////////////// +// START SOUND... called by main thread to setup a new sound on a channel +//////////////////////////////////////////////////////////////////////// + +INLINE void StartSound(spu2_state_t *spu, int ch) +{ + spu->dwNewChannel2[ch/24]&=~(1<<(ch%24)); // clear new channel bit + spu->dwEndChannel2[ch/24]&=~(1<<(ch%24)); // clear end channel bit + + StartADSR(spu, ch); + StartREVERB(spu, ch); + + spu->s_chan[ch].pCurr=spu->s_chan[ch].pStart; // set sample start + + spu->s_chan[ch].s_1=0; // init mixing vars + spu->s_chan[ch].s_2=0; + spu->s_chan[ch].iSBPos=28; + + spu->s_chan[ch].bNew=0; // init channel flags + spu->s_chan[ch].bStop=0; + spu->s_chan[ch].bOn=1; + + spu->s_chan[ch].SB[29]=0; // init our interpolation helpers + spu->s_chan[ch].SB[30]=0; + + if(spu->iUseInterpolation>=2) // gauss interpolation? + {spu->s_chan[ch].spos=0x30000L;spu->s_chan[ch].SB[28]=0;} // -> start with more decoding + else {spu->s_chan[ch].spos=0x10000L;spu->s_chan[ch].SB[31]=0;} // -> no/simple interpolation starts with one 44100 decoding +} + +//////////////////////////////////////////////////////////////////////// +// MAIN SPU FUNCTION +// here is the main job handler... thread, timer or direct func call +// basically the whole sound processing is done in this fat func! +//////////////////////////////////////////////////////////////////////// + +// Counting to 65536 results in full volume offage. +void setlength2(spu2_state_t *spu, s32 stop, s32 fade) +{ + if(stop==~0) + { + spu->decaybegin=~0; + } + else + { + stop=(stop*441)/10; + fade=(fade*441)/10; + + spu->decaybegin=stop; + spu->decayend=stop+fade; + } +} +// 5 ms waiting phase, if buffer is full and no new sound has to get started +// .. can be made smaller (smallest val: 1 ms), but bigger waits give +// better performance + +#define PAUSE_W 5 +#define PAUSE_L 5000 + +//////////////////////////////////////////////////////////////////////// + +static void *MAINThread(mips_cpu_context *cpu, int samp2run) +{ + spu2_state_t *spu = cpu->spu2; + int s_1,s_2,fa,voldiv=spu->iVolume; + unsigned char * start;unsigned int nSample; + int ch,predict_nr,shift_factor,flags,d,d2,s; + int gpos,bIRQReturn=0; + +// while(!bEndThread) // until we are shutting down + { + //--------------------------------------------------// + // ok, at the beginning we are looking if there is + // enuff free place in the dsound/oss buffer to + // fill in new data, or if there is a new channel to start. + // if not, we wait (thread) or return (timer/spuasync) + // until enuff free place is available/a new channel gets + // started + + if(spu->dwNewChannel2[0] || spu->dwNewChannel2[1]) // new channel should start immedately? + { // (at least one bit 0 ... MAXCHANNEL is set?) + spu->iSecureStart++; // -> set iSecure + if(spu->iSecureStart>5) spu->iSecureStart=0; // (if it is set 5 times - that means on 5 tries a new samples has been started - in a row, we will reset it, to give the sound update a chance) + } + else spu->iSecureStart=0; // 0: no new channel should start + +/* if (!iSecureStart) + { + iSecureStart=0; // reset secure + return; + }*/ + +#if 0 + while(!iSecureStart && !bEndThread) // && // no new start? no thread end? +// (SoundGetBytesBuffered()>TESTSIZE)) // and still enuff data in sound buffer? + { + iSecureStart=0; // reset secure + + if(iUseTimer) return 0; // linux no-thread mode? bye + + if(dwNewChannel2[0] || dwNewChannel2[1]) + iSecureStart=1; // if a new channel kicks in (or, of course, sound buffer runs low), we will leave the loop + } +#endif + + //--------------------------------------------------// continue from irq handling in timer mode? + + if(spu->lastch>=0) // will be -1 if no continue is pending + { + ch=spu->lastch; spu->lastch=-1; // -> setup all kind of vars to continue + goto GOON; // -> directly jump to the continue point + } + + //--------------------------------------------------// + //- main channel loop -// + //--------------------------------------------------// + { + for(ch=0;ch<MAXCHAN;ch++) // loop em all... we will collect 1 ms of sound of each playing channel + { + if(spu->s_chan[ch].bNew) StartSound(spu, ch); // start new sound + if(!spu->s_chan[ch].bOn) continue; // channel not playing? next + + if(spu->s_chan[ch].iActFreq!=spu->s_chan[ch].iUsedFreq) // new psx frequency? + { + spu->s_chan[ch].iUsedFreq=spu->s_chan[ch].iActFreq; // -> take it and calc steps + spu->s_chan[ch].sinc=spu->s_chan[ch].iRawPitch<<4; + if(!spu->s_chan[ch].sinc) spu->s_chan[ch].sinc=1; + if(spu->iUseInterpolation==1) spu->s_chan[ch].SB[32]=1; // -> freq change in simle imterpolation mode: set flag + } +// ns=0; +// while(ns<NSSIZE) // loop until 1 ms of data is reached + { + while(spu->s_chan[ch].spos>=0x10000L) + { + if(spu->s_chan[ch].iSBPos==28) // 28 reached? + { + start=spu->s_chan[ch].pCurr; // set up the current pos + + if (start == (unsigned char*)-1) // special "stop" sign + { + spu->s_chan[ch].bOn=0; // -> turn everything off + spu->s_chan[ch].ADSRX.lVolume=0; + spu->s_chan[ch].ADSRX.EnvelopeVol=0; + goto ENDX; // -> and done for this channel + } + + spu->s_chan[ch].iSBPos=0; + + //////////////////////////////////////////// spu irq handler here? mmm... do it later + + s_1=spu->s_chan[ch].s_1; + s_2=spu->s_chan[ch].s_2; + + predict_nr=(int)*start;start++; + shift_factor=predict_nr&0xf; + predict_nr >>= 4; + flags=(int)*start;start++; + + // -------------------------------------- // + + for (nSample=0;nSample<28;start++) + { + d=(int)*start; + s=((d&0xf)<<12); + if(s&0x8000) s|=0xffff0000; + + fa=(s >> shift_factor); + fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6); + s_2=s_1;s_1=fa; + s=((d & 0xf0) << 8); + + spu->s_chan[ch].SB[nSample++]=fa; + + if(s&0x8000) s|=0xffff0000; + fa=(s>>shift_factor); + fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6); + s_2=s_1;s_1=fa; + + spu->s_chan[ch].SB[nSample++]=fa; + } + + //////////////////////////////////////////// irq check + + if(spu->spuCtrl2[ch/24]&0x40) // some irq active? + { + if((spu->pSpuIrq[ch/24] > start-16 && // irq address reached? + spu->pSpuIrq[ch/24] <= start) || + ((flags&1) && // special: irq on looping addr, when stop/loop flag is set + (spu->pSpuIrq[ch/24] > spu->s_chan[ch].pLoop-16 && + spu->pSpuIrq[ch/24] <= spu->s_chan[ch].pLoop))) + { + spu->s_chan[ch].iIrqDone=1; // -> debug flag + + if(spu->irqCallback) spu->irqCallback(); // -> call main emu (not supported in SPU2 right now) + else + { + if(ch<24) InterruptDMA4(cpu); // -> let's see what is happening if we call our irqs instead ;) + else InterruptDMA7(cpu); + } + + if(spu->iSPUIRQWait) // -> option: wait after irq for main emu + { + spu->iSpuAsyncWait=1; + bIRQReturn=1; + } + } + } + + //////////////////////////////////////////// flag handler + + if((flags&4) && (!spu->s_chan[ch].bIgnoreLoop)) + spu->s_chan[ch].pLoop=start-16; // loop adress + + if(flags&1) // 1: stop/loop + { + spu->dwEndChannel2[ch/24]|=(1<<(ch%24)); + + // We play this block out first... + //if(!(flags&2)|| spu->s_chan[ch].pLoop==NULL) + // 1+2: do loop... otherwise: stop + if(flags!=3 || spu->s_chan[ch].pLoop==NULL) // PETE: if we don't check exactly for 3, loop hang ups will happen (DQ4, for example) + { // and checking if pLoop is set avoids crashes, yeah + start = (unsigned char*)-1; + } + else + { + start = spu->s_chan[ch].pLoop; + } + } + + spu->s_chan[ch].pCurr=start; // store values for next cycle + spu->s_chan[ch].s_1=s_1; + spu->s_chan[ch].s_2=s_2; + + //////////////////////////////////////////// + + if(bIRQReturn) // special return for "spu irq - wait for cpu action" + { + bIRQReturn=0; + { + spu->lastch=ch; +// lastns=ns; // changemeback + + return 0; + } + } + + //////////////////////////////////////////// + +GOON: ; + + } + + fa=spu->s_chan[ch].SB[spu->s_chan[ch].iSBPos++]; // get sample data + +// if((spu->spuCtrl2[ch/24]&0x4000)==0) fa=0; // muted? +// else // else adjust + { + if(fa>32767L) fa=32767L; + if(fa<-32767L) fa=-32767L; + } + + if(spu->iUseInterpolation>=2) // gauss/cubic interpolation + { + gpos = spu->s_chan[ch].SB[28]; + gval0 = fa; + gpos = (gpos+1) & 3; + spu->s_chan[ch].SB[28] = gpos; + } + else + if(spu->iUseInterpolation==1) // simple interpolation + { + spu->s_chan[ch].SB[28] = 0; + spu->s_chan[ch].SB[29] = spu->s_chan[ch].SB[30]; // -> helpers for simple linear interpolation: delay real val for two slots, and calc the two deltas, for a 'look at the future behaviour' + spu->s_chan[ch].SB[30] = spu->s_chan[ch].SB[31]; + spu->s_chan[ch].SB[31] = fa; + spu->s_chan[ch].SB[32] = 1; // -> flag: calc new interolation + } + else spu->s_chan[ch].SB[29]=fa; // no interpolation + + spu->s_chan[ch].spos -= 0x10000L; + } + + //////////////////////////////////////////////// + // noise handler... just produces some noise data + // surely wrong... and no noise frequency (spuCtrl&0x3f00) will be used... + // and sometimes the noise will be used as fmod modulation... pfff + + if(spu->s_chan[ch].bNoise) + { + if((spu->dwNoiseVal<<=1)&0x80000000L) + { + spu->dwNoiseVal^=0x0040001L; + fa=((spu->dwNoiseVal>>2)&0x7fff); + fa=-fa; + } + else fa=(spu->dwNoiseVal>>2)&0x7fff; + + // mmm... depending on the noise freq we allow bigger/smaller changes to the previous val + fa=spu->s_chan[ch].iOldNoise+((fa-spu->s_chan[ch].iOldNoise)/((0x001f-((spu->spuCtrl2[ch/24]&0x3f00)>>9))+1)); + if(fa>32767L) fa=32767L; + if(fa<-32767L) fa=-32767L; + spu->s_chan[ch].iOldNoise=fa; + + if(spu->iUseInterpolation<2) // no gauss/cubic interpolation? + spu->s_chan[ch].SB[29] = fa; // -> store noise val in "current sample" slot + } //---------------------------------------- + else // NO NOISE (NORMAL SAMPLE DATA) HERE + {//------------------------------------------// + if(spu->iUseInterpolation==3) // cubic interpolation + { + long xd; + xd = ((spu->s_chan[ch].spos) >> 1)+1; + gpos = spu->s_chan[ch].SB[28]; + + fa = gval(3) - 3*gval(2) + 3*gval(1) - gval0; + fa *= (xd - (2<<15)) / 6; + fa >>= 15; + fa += gval(2) - gval(1) - gval(1) + gval0; + fa *= (xd - (1<<15)) >> 1; + fa >>= 15; + fa += gval(1) - gval0; + fa *= xd; + fa >>= 15; + fa = fa + gval0; + } + //------------------------------------------// + else + if(spu->iUseInterpolation==2) // gauss interpolation + { + int vl, vr; + vl = (spu->s_chan[ch].spos >> 6) & ~3; + gpos = spu->s_chan[ch].SB[28]; + vr=(gauss[vl]*gval0)&~2047; + vr+=(gauss[vl+1]*gval(1))&~2047; + vr+=(gauss[vl+2]*gval(2))&~2047; + vr+=(gauss[vl+3]*gval(3))&~2047; + fa = vr>>11; +/* + vr=(gauss[vl]*gval0)>>9; + vr+=(gauss[vl+1]*gval(1))>>9; + vr+=(gauss[vl+2]*gval(2))>>9; + vr+=(gauss[vl+3]*gval(3))>>9; + fa = vr>>2; +*/ + } + //------------------------------------------// + else + if(spu->iUseInterpolation==1) // simple interpolation + { + if(spu->s_chan[ch].sinc<0x10000L) // -> upsampling? + InterpolateUp(spu, ch); // --> interpolate up + else InterpolateDown(spu, ch); // --> else down + fa=spu->s_chan[ch].SB[29]; + } + //------------------------------------------// + else fa=spu->s_chan[ch].SB[29]; // no interpolation + } + + spu->s_chan[ch].sval = (MixADSR(spu, ch) * fa) / 1023; // add adsr + + if(spu->s_chan[ch].bFMod==2) // fmod freq channel + { + int NP=spu->s_chan[ch+1].iRawPitch; + double intr; + + NP=((32768L+spu->s_chan[ch].sval)*NP)/32768L; // mmm... I still need to adjust that to 1/48 khz... we will wait for the first game/demo using it to decide how to do it :) + + if(NP>0x3fff) NP=0x3fff; + if(NP<0x1) NP=0x1; + + intr = (double)48000.0f / (double)44100.0f * (double)NP; + NP = (UINT32)intr; + + NP=(44100L*NP)/(4096L); // calc frequency + + spu->s_chan[ch+1].iActFreq=NP; + spu->s_chan[ch+1].iUsedFreq=NP; + spu->s_chan[ch+1].sinc=(((NP/10)<<16)/4410); + if(!spu->s_chan[ch+1].sinc) spu->s_chan[ch+1].sinc=1; + if(spu->iUseInterpolation==1) // freq change in sipmle interpolation mode + spu->s_chan[ch+1].SB[32]=1; + +// mmmm... set up freq decoding positions? +// spu->s_chan[ch+1].iSBPos=28; +// spu->s_chan[ch+1].spos=0x10000L; + } + else + { + ////////////////////////////////////////////// + // ok, left/right sound volume (psx volume goes from 0 ... 0x3fff) + + if(spu->s_chan[ch].iMute) + spu->s_chan[ch].sval=0; // debug mute + else + { + if(spu->s_chan[ch].bVolumeL) + spu->SSumL[0]+=(spu->s_chan[ch].sval*spu->s_chan[ch].iLeftVolume)/0x4000L; + if(spu->s_chan[ch].bVolumeR) + spu->SSumR[0]+=(spu->s_chan[ch].sval*spu->s_chan[ch].iRightVolume)/0x4000L; + } + + ////////////////////////////////////////////// + // now let us store sound data for reverb + + if(spu->s_chan[ch].bRVBActive) StoreREVERB(spu, ch,0); + } + + //////////////////////////////////////////////// + // ok, go on until 1 ms data of this channel is collected + + spu->s_chan[ch].spos += spu->s_chan[ch].sinc; + + } +ENDX: ; + } + } + + //---------------------------------------------------// + //- here we have another 1 ms of sound data + //---------------------------------------------------// + + /////////////////////////////////////////////////////// + // mix all channels (including reverb) into one buffer + + spu->SSumL[0]+=MixREVERBLeft(spu, 0,0); + spu->SSumL[0]+=MixREVERBLeft(spu, 0,1); + spu->SSumR[0]+=MixREVERBRight(spu, 0); + spu->SSumR[0]+=MixREVERBRight(spu, 1); + + d=spu->SSumL[0]/voldiv;spu->SSumL[0]=0; + d2=spu->SSumR[0]/voldiv;spu->SSumR[0]=0; + + if(d<-32767) d=-32767;if(d>32767) d=32767; + if(d2<-32767) d2=-32767;if(d2>32767) d2=32767; + + if(spu->sampcount>=spu->decaybegin) + { + s32 dmul; + if(spu->decaybegin!=~0) // Is anyone REALLY going to be playing a song + // for 13 hours? + { + if(spu->sampcount>=spu->decayend) + { +// ao_song_done = 1; + return(0); + } + + dmul=256-(256*(spu->sampcount-spu->decaybegin)/(spu->decayend-spu->decaybegin)); + d=(d*dmul)>>8; + d2=(d2*dmul)>>8; + } + } + spu->sampcount++; + + *spu->pS++=d; + *spu->pS++=d2; + + InitREVERB(spu); + + ////////////////////////////////////////////////////// + // feed the sound + // wanna have around 1/60 sec (16.666 ms) updates + if ((((unsigned char *)spu->pS)-((unsigned char *)spu->pSpuBuffer)) == (735*4)) + { + cpu->spu_callback((u8*)spu->pSpuBuffer,(u8*)spu->pS-(u8*)spu->pSpuBuffer, cpu->spu_callback_data); + spu->pS=(short *)spu->pSpuBuffer; + } + } + + // end of big main loop... + + spu->bThreadEnded=1; + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// SPU ASYNC... even newer epsxe func +// 1 time every 'cycle' cycles... harhar +//////////////////////////////////////////////////////////////////////// + +EXPORT_GCC void CALLBACK SPU2async(mips_cpu_context *cpu, unsigned long cycle) +{ + spu2_state_t *spu = cpu->spu2; + if(spu->iSpuAsyncWait) + { + spu->iSpuAsyncWait++; + if(spu->iSpuAsyncWait<=64) return; + spu->iSpuAsyncWait=0; + } + + MAINThread(cpu, 0); // -> linux high-compat mode +} + +//////////////////////////////////////////////////////////////////////// +// INIT/EXIT STUFF +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// SPUINIT: this func will be called first by the main emu +//////////////////////////////////////////////////////////////////////// + + +EXPORT_GCC long CALLBACK SPU2init(mips_cpu_context *cpu, void (*callback)(unsigned char *, long, void *), void *data) +{ + cpu->spu2 = malloc (sizeof (spu2_state_t)); + memset (cpu->spu2, 0, sizeof (spu2_state_t)); + cpu->spu2->iUseXA=0; + cpu->spu2->iVolume=3; + cpu->spu2->iXAPitch=1; + cpu->spu2->iUseTimer=2; + cpu->spu2->iSPUIRQWait=1; + cpu->spu2->iDebugMode=0; + cpu->spu2->iRecordMode=0; + cpu->spu2->iUseReverb=1; + cpu->spu2->iUseInterpolation=2; + cpu->spu2->dwNoiseVal=1; // global noise generator + cpu->spu2->lastch=-1; + + cpu->spu_callback = callback; + cpu->spu_callback_data = data; + cpu->spu2->spuMemC=(unsigned char *)cpu->spu2->spuMem; // just small setup + memset((void *)cpu->spu2->s_chan,0,MAXCHAN*sizeof(SPUCHAN)); + memset(cpu->spu2->rvb,0,2*sizeof(REVERBInfo)); + + cpu->spu2->sampcount = 0; + + InitADSR(); + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// SETUPTIMER: init of certain buffers and threads/timers +//////////////////////////////////////////////////////////////////////// + +static void SetupTimer(mips_cpu_context *cpu) +{ + spu2_state_t *spu = cpu->spu2; + memset(spu->SSumR,0,NSSIZE*sizeof(int)); // init some mixing buffers + memset(spu->SSumL,0,NSSIZE*sizeof(int)); + spu->pS=(short *)spu->pSpuBuffer; // setup soundbuffer pointer + + spu->bEndThread=0; // init thread vars + spu->bThreadEnded=0; + spu->bSpuInit=1; // flag: we are inited +} + +//////////////////////////////////////////////////////////////////////// +// REMOVETIMER: kill threads/timers +//////////////////////////////////////////////////////////////////////// + +static void RemoveTimer(mips_cpu_context *cpu) +{ + spu2_state_t *spu = cpu->spu2; + spu->bEndThread=1; // raise flag to end thread + spu->bThreadEnded=0; // no more spu is running + spu->bSpuInit=0; +} + +//////////////////////////////////////////////////////////////////////// +// SETUPSTREAMS: init most of the spu buffers +//////////////////////////////////////////////////////////////////////// + +static void SetupStreams(mips_cpu_context *cpu) +{ + spu2_state_t *spu = cpu->spu2; + int i; + + spu->pSpuBuffer=(unsigned char *)malloc(32768); // alloc mixing buffer + + i=NSSIZE*2; + + spu->sRVBStart[0] = (int *)malloc(i*4); // alloc reverb buffer + memset(spu->sRVBStart[0],0,i*4); + spu->sRVBEnd[0] = spu->sRVBStart[0] + i; + spu->sRVBPlay[0] = spu->sRVBStart[0]; + spu->sRVBStart[1] = (int *)malloc(i*4); // alloc reverb buffer + memset(spu->sRVBStart[1],0,i*4); + spu->sRVBEnd[1] = spu->sRVBStart[1] + i; + spu->sRVBPlay[1] = spu->sRVBStart[1]; + + for(i=0;i<MAXCHAN;i++) // loop sound channels + { +// we don't use mutex sync... not needed, would only +// slow us down: +// spu->s_chan[i].hMutex=CreateMutex(NULL,FALSE,NULL); + spu->s_chan[i].ADSRX.SustainLevel = 1024; // -> init sustain + spu->s_chan[i].iMute=0; + spu->s_chan[i].iIrqDone=0; + spu->s_chan[i].pLoop=spu->spuMemC; + spu->s_chan[i].pStart=spu->spuMemC; + spu->s_chan[i].pCurr=spu->spuMemC; + } +} + +//////////////////////////////////////////////////////////////////////// +// REMOVESTREAMS: free most buffer +//////////////////////////////////////////////////////////////////////// + +static void RemoveStreams(mips_cpu_context *cpu) +{ + spu2_state_t *spu = cpu->spu2; + free(spu->pSpuBuffer); // free mixing buffer + spu->pSpuBuffer=NULL; + free(spu->sRVBStart[0]); // free reverb buffer + spu->sRVBStart[0]=0; + free(spu->sRVBStart[1]); // free reverb buffer + spu->sRVBStart[1]=0; + +/* + int i; + for(i=0;i<MAXCHAN;i++) + { + WaitForSingleObject(spu->s_chan[i].hMutex,2000); + ReleaseMutex(spu->s_chan[i].hMutex); + if(spu->s_chan[i].hMutex) + {CloseHandle(spu->s_chan[i].hMutex);spu->s_chan[i].hMutex=0;} + } +*/ +} + + +//////////////////////////////////////////////////////////////////////// +// SPUOPEN: called by main emu after init +//////////////////////////////////////////////////////////////////////// + +EXPORT_GCC long CALLBACK SPU2open(mips_cpu_context *cpu, void *pDsp) +{ + spu2_state_t *spu = cpu->spu2; + if(spu->bSPUIsOpen) return 0; // security for some stupid main emus + + spu->iUseXA=0; // just small setup + spu->iVolume=3; + spu->bEndThread=0; + spu->bThreadEnded=0; + spu->spuMemC=(unsigned char *)spu->spuMem; + memset((void *)spu->s_chan,0,(MAXCHAN+1)*sizeof(SPUCHAN)); + spu->pSpuIrq[0]=0; + spu->pSpuIrq[1]=0; + spu->iSPUIRQWait=1; + spu->dwNewChannel2[0]=0; + spu->dwNewChannel2[1]=0; + spu->dwEndChannel2[0]=0; + spu->dwEndChannel2[1]=0; + spu->spuCtrl2[0]=0; + spu->spuCtrl2[1]=0; + spu->spuStat2[0]=0; + spu->spuStat2[1]=0; + spu->spuIrq2[0]=0; + spu->spuIrq2[1]=0; + spu->spuAddr2[0]=0xffffffff; + spu->spuAddr2[1]=0xffffffff; + spu->spuRvbAddr2[0]=0; + spu->spuRvbAddr2[1]=0; + spu->spuRvbAEnd2[0]=0; + spu->spuRvbAEnd2[1]=0; + +// ReadConfig(); // read user stuff + +// SetupSound(); // setup midas (before init!) + + SetupStreams(cpu); // prepare streaming + + SetupTimer(cpu); // timer for feeding data + + spu->bSPUIsOpen=1; + + return 0; +} + +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// SPUCLOSE: called before shutdown +//////////////////////////////////////////////////////////////////////// + +EXPORT_GCC void CALLBACK SPU2close(mips_cpu_context *cpu) +{ + spu2_state_t *spu = cpu->spu2; + if(!spu->bSPUIsOpen) return; // some security + + spu->bSPUIsOpen=0; // no more open + + RemoveTimer(cpu); // no more feeding + +// RemoveSound(cpu); // no more sound handling + + RemoveStreams(cpu); // no more streaming +} + +//////////////////////////////////////////////////////////////////////// +// SPUSHUTDOWN: called by main emu on final exit +//////////////////////////////////////////////////////////////////////// + +EXPORT_GCC void CALLBACK SPU2shutdown(void) +{ + return; +} + +//////////////////////////////////////////////////////////////////////// +// SPUTEST: we don't test, we are always fine ;) +//////////////////////////////////////////////////////////////////////// + +EXPORT_GCC long CALLBACK SPU2test(void) +{ + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// SETUP CALLBACKS +// this functions will be called once, +// passes a callback that should be called on SPU-IRQ/cdda volume change +//////////////////////////////////////////////////////////////////////// + +#if 0 +// not used yet +EXPORT_GCC void CALLBACK SPU2irqCallback(void (CALLBACK *callback)(void)) +{ + irqCallback = callback; +} + +// not used yet +EXPORT_GCC void CALLBACK SPU2registerCallback(void (CALLBACK *callback)(void)) +{ + irqCallback = callback; +} + +// not used yet +EXPORT_GCC void CALLBACK SPU2registerCDDAVolume(void (CALLBACK *CDDAVcallback)(unsigned short,unsigned short)) +{ + cddavCallback = CDDAVcallback; +} +#endif diff --git a/plugins/ao/eng_psf/peops2/stdafx.h b/plugins/ao/eng_psf/peops2/stdafx.h new file mode 100644 index 00000000..943f38d3 --- /dev/null +++ b/plugins/ao/eng_psf/peops2/stdafx.h @@ -0,0 +1,41 @@ +/*************************************************************************** + StdAfx.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#define EXPORT_GCC + +#include <stdlib.h> +#define RRand(range) (random()%range) +#include <string.h> +#include <math.h> + +#undef CALLBACK +#define CALLBACK +#define DWORD unsigned long +#define LOWORD(l) ((unsigned short)(l)) +#define HIWORD(l) ((unsigned short)(((unsigned long)(l) >> 16) & 0xFFFF)) + +#include "psemuxa.h" + diff --git a/plugins/ao/eng_psf/peops2/xa.c b/plugins/ao/eng_psf/peops2/xa.c new file mode 100755 index 00000000..fb63ad40 --- /dev/null +++ b/plugins/ao/eng_psf/peops2/xa.c @@ -0,0 +1,363 @@ +/***************************************************************************
+ xa.c - description
+ -------------------
+ begin : Wed May 15 2002
+ copyright : (C) 2002 by Pete Bernert
+ email : BlackDove@addcom.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+//*************************************************************************//
+// History of changes:
+//
+// 2003/02/18 - kode54
+// - added gaussian interpolation
+//
+// 2002/05/15 - Pete
+// - generic cleanup for the Peops release
+//
+//*************************************************************************//
+
+#include "stdafx.h"
+
+#define _IN_XA
+
+// will be included from spu.c
+#ifdef _IN_SPU
+
+////////////////////////////////////////////////////////////////////////
+// XA GLOBALS
+////////////////////////////////////////////////////////////////////////
+
+xa_decode_t * xapGlobal=0;
+
+unsigned long * XAFeed = NULL;
+unsigned long * XAPlay = NULL;
+unsigned long * XAStart = NULL;
+unsigned long * XAEnd = NULL;
+
+unsigned long XARepeat = 0;
+unsigned long XALastVal = 0;
+
+int iLeftXAVol = 32767;
+int iRightXAVol = 32767;
+
+static int gauss_ptr = 0;
+static int gauss_window[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+
+#define gvall0 gauss_window[gauss_ptr]
+#define gvall(x) gauss_window[(gauss_ptr+x)&3]
+#define gvalr0 gauss_window[4+gauss_ptr]
+#define gvalr(x) gauss_window[4+((gauss_ptr+x)&3)]
+
+////////////////////////////////////////////////////////////////////////
+// MIX XA
+////////////////////////////////////////////////////////////////////////
+
+INLINE void MixXA(void)
+{
+ int ns;
+
+ for(ns=0;ns<NSSIZE && XAPlay!=XAFeed;ns++)
+ {
+ XALastVal=*XAPlay++;
+ if(XAPlay==XAEnd) XAPlay=XAStart;
+ SSumL[ns]+=(((short)(XALastVal&0xffff)) * iLeftXAVol)/32767;
+ SSumR[ns]+=(((short)((XALastVal>>16)&0xffff)) * iRightXAVol)/32767;
+ }
+
+ if(XAPlay==XAFeed && XARepeat)
+ {
+ XARepeat--;
+ for(;ns<NSSIZE;ns++)
+ {
+ SSumL[ns]+=(((short)(XALastVal&0xffff)) * iLeftXAVol)/32767;
+ SSumR[ns]+=(((short)((XALastVal>>16)&0xffff)) * iRightXAVol)/32767;
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+// FEED XA
+////////////////////////////////////////////////////////////////////////
+
+INLINE void FeedXA(xa_decode_t *xap)
+{
+ int sinc,spos,i,iSize,iPlace,vl,vr;
+
+ if(!bSPUIsOpen) return;
+
+ xapGlobal = xap; // store info for save states
+ XARepeat = 100; // set up repeat
+
+ iSize=((44100*xap->nsamples)/xap->freq); // get size
+ if(!iSize) return; // none? bye
+
+ if(XAFeed<XAPlay) iPlace=XAPlay-XAFeed; // how much space in my buf?
+ else iPlace=(XAEnd-XAFeed) + (XAPlay-XAStart);
+
+ if(iPlace==0) return; // no place at all
+
+ //----------------------------------------------------//
+ if(iXAPitch) // pitch change option?
+ {
+ static DWORD dwLT=0;
+ static DWORD dwFPS=0;
+ static int iFPSCnt=0;
+ static int iLastSize=0;
+ static DWORD dwL1=0;
+ DWORD dw=timeGetTime(),dw1,dw2;
+
+ iPlace=iSize;
+
+ dwFPS+=dw-dwLT;iFPSCnt++;
+
+ dwLT=dw;
+
+ if(iFPSCnt>=10)
+ {
+ if(!dwFPS) dwFPS=1;
+ dw1=1000000/dwFPS;
+ if(dw1>=(dwL1-100) && dw1<=(dwL1+100)) dw1=dwL1;
+ else dwL1=dw1;
+ dw2=(xap->freq*100/xap->nsamples);
+ if((!dw1)||((dw2+100)>=dw1)) iLastSize=0;
+ else
+ {
+ iLastSize=iSize*dw2/dw1;
+ if(iLastSize>iPlace) iLastSize=iPlace;
+ iSize=iLastSize;
+ }
+ iFPSCnt=0;dwFPS=0;
+ }
+ else
+ {
+ if(iLastSize) iSize=iLastSize;
+ }
+ }
+ //----------------------------------------------------//
+
+ spos=0x10000L;
+ sinc = (xap->nsamples << 16) / iSize; // calc freq by num / size
+
+ if(xap->stereo)
+ {
+ unsigned long * pS=(unsigned long *)xap->pcm;
+ unsigned long l=0;
+
+ if(iXAPitch)
+ {
+ long l1,l2;short s;
+ for(i=0;i<iSize;i++)
+ {
+ if(iUseInterpolation==2)
+ {
+ while(spos>=0x10000L)
+ {
+ l = *pS++;
+ gauss_window[gauss_ptr] = (short)LOWORD(l);
+ gauss_window[4+gauss_ptr] = (short)HIWORD(l);
+ gauss_ptr = (gauss_ptr+1) & 3;
+ spos -= 0x10000L;
+ }
+ vl = (spos >> 6) & ~3;
+ vr=(gauss[vl]*gvall0)&~2047;
+ vr+=(gauss[vl+1]*gvall(1))&~2047;
+ vr+=(gauss[vl+2]*gvall(2))&~2047;
+ vr+=(gauss[vl+3]*gvall(3))&~2047;
+ l= (vr >> 11) & 0xffff;
+ vr=(gauss[vl]*gvalr0)&~2047;
+ vr+=(gauss[vl+1]*gvalr(1))&~2047;
+ vr+=(gauss[vl+2]*gvalr(2))&~2047;
+ vr+=(gauss[vl+3]*gvalr(3))&~2047;
+ l |= vr << 5;
+ }
+ else
+ {
+ while(spos>=0x10000L)
+ {
+ l = *pS++;
+ spos -= 0x10000L;
+ }
+ }
+
+ s=(short)LOWORD(l);
+ l1=s;
+ l1=(l1*iPlace)/iSize;
+ if(l1<-32767) l1=-32767;
+ if(l1> 32767) l1=32767;
+ s=(short)HIWORD(l);
+ l2=s;
+ l2=(l2*iPlace)/iSize;
+ if(l2<-32767) l2=-32767;
+ if(l2> 32767) l2=32767;
+ l=(l1&0xffff)|(l2<<16);
+
+ *XAFeed++=l;
+
+ if(XAFeed==XAEnd) XAFeed=XAStart;
+ if(XAFeed==XAPlay)
+ {
+ if(XAPlay!=XAStart) XAFeed=XAPlay-1;
+ break;
+ }
+
+ spos += sinc;
+ }
+ }
+ else
+ {
+ for(i=0;i<iSize;i++)
+ {
+ if(iUseInterpolation==2)
+ {
+ while(spos>=0x10000L)
+ {
+ l = *pS++;
+ gauss_window[gauss_ptr] = (short)LOWORD(l);
+ gauss_window[4+gauss_ptr] = (short)HIWORD(l);
+ gauss_ptr = (gauss_ptr+1) & 3;
+ spos -= 0x10000L;
+ }
+ vl = (spos >> 6) & ~3;
+ vr=(gauss[vl]*gvall0)&~2047;
+ vr+=(gauss[vl+1]*gvall(1))&~2047;
+ vr+=(gauss[vl+2]*gvall(2))&~2047;
+ vr+=(gauss[vl+3]*gvall(3))&~2047;
+ l= (vr >> 11) & 0xffff;
+ vr=(gauss[vl]*gvalr0)&~2047;
+ vr+=(gauss[vl+1]*gvalr(1))&~2047;
+ vr+=(gauss[vl+2]*gvalr(2))&~2047;
+ vr+=(gauss[vl+3]*gvalr(3))&~2047;
+ l |= vr << 5;
+ }
+ else
+ {
+ while(spos>=0x10000L)
+ {
+ l = *pS++;
+ spos -= 0x10000L;
+ }
+ }
+
+ *XAFeed++=l;
+
+ if(XAFeed==XAEnd) XAFeed=XAStart;
+ if(XAFeed==XAPlay)
+ {
+ if(XAPlay!=XAStart) XAFeed=XAPlay-1;
+ break;
+ }
+
+ spos += sinc;
+ }
+ }
+ }
+ else
+ {
+ unsigned short * pS=(unsigned short *)xap->pcm;
+ unsigned long l;short s=0;
+
+ if(iXAPitch)
+ {
+ long l1;
+ for(i=0;i<iSize;i++)
+ {
+ if(iUseInterpolation==2)
+ {
+ while(spos>=0x10000L)
+ {
+ gauss_window[gauss_ptr] = (short)*pS++;
+ gauss_ptr = (gauss_ptr+1) & 3;
+ spos -= 0x10000L;
+ }
+ vl = (spos >> 6) & ~3;
+ vr=(gauss[vl]*gvall0)&~2047;
+ vr+=(gauss[vl+1]*gvall(1))&~2047;
+ vr+=(gauss[vl+2]*gvall(2))&~2047;
+ vr+=(gauss[vl+3]*gvall(3))&~2047;
+ l1=s= vr >> 11;
+ l1 &= 0xffff;
+ }
+ else
+ {
+ while(spos>=0x10000L)
+ {
+ s = *pS++;
+ spos -= 0x10000L;
+ }
+ l1=s;
+ }
+
+ l1=(l1*iPlace)/iSize;
+ if(l1<-32767) l1=-32767;
+ if(l1> 32767) l1=32767;
+ l=(l1&0xffff)|(l1<<16);
+ *XAFeed++=l;
+
+ if(XAFeed==XAEnd) XAFeed=XAStart;
+ if(XAFeed==XAPlay)
+ {
+ if(XAPlay!=XAStart) XAFeed=XAPlay-1;
+ break;
+ }
+
+ spos += sinc;
+ }
+ }
+ else
+ {
+ for(i=0;i<iSize;i++)
+ {
+ if(iUseInterpolation==2)
+ {
+ while(spos>=0x10000L)
+ {
+ gauss_window[gauss_ptr] = (short)*pS++;
+ gauss_ptr = (gauss_ptr+1) & 3;
+ spos -= 0x10000L;
+ }
+ vl = (spos >> 6) & ~3;
+ vr=(gauss[vl]*gvall0)&~2047;
+ vr+=(gauss[vl+1]*gvall(1))&~2047;
+ vr+=(gauss[vl+2]*gvall(2))&~2047;
+ vr+=(gauss[vl+3]*gvall(3))&~2047;
+ l=s= vr >> 11;
+ l &= 0xffff;
+ }
+ else
+ {
+ while(spos>=0x10000L)
+ {
+ s = *pS++;
+ spos -= 0x10000L;
+ }
+ l=s;
+ }
+
+ *XAFeed++=(l|(l<<16));
+
+ if(XAFeed==XAEnd) XAFeed=XAStart;
+ if(XAFeed==XAPlay)
+ {
+ if(XAPlay!=XAStart) XAFeed=XAPlay-1;
+ break;
+ }
+
+ spos += sinc;
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/plugins/ao/eng_psf/psx.c b/plugins/ao/eng_psf/psx.c new file mode 100644 index 00000000..8f646d05 --- /dev/null +++ b/plugins/ao/eng_psf/psx.c @@ -0,0 +1,3140 @@ +/* + * Sony CXD8530AQ/CXD8530BQ/CXD8530CQ/CXD8661R + * + * PSX CPU emulator for the MAME project written by smf + * Thanks to Farfetch'd for information on the delay slot bug + * + * The PSX CPU is a custom r3000a with a built in + * geometry transform engine, no mmu & no data cache. + * + * There is a stall circuit for load delays, but + * it doesn't work if the load occurs in a branch + * delay slot. + * + */ + +#include <stdio.h> +#include "ao.h" +#include "cpuintrf.h" +#include "psx.h" + +#define EXC_INT ( 0 ) +#define EXC_ADEL ( 4 ) +#define EXC_ADES ( 5 ) +#define EXC_SYS ( 8 ) +#define EXC_BP ( 9 ) +#define EXC_RI ( 10 ) +#define EXC_CPU ( 11 ) +#define EXC_OVF ( 12 ) + +#define CP0_RANDOM ( 1 ) +#define CP0_BADVADDR ( 8 ) +#define CP0_SR ( 12 ) +#define CP0_CAUSE ( 13 ) +#define CP0_EPC ( 14 ) +#define CP0_PRID ( 15 ) + +#define SR_IEC ( 1L << 0 ) +#define SR_KUC ( 1L << 1 ) +#define SR_ISC ( 1L << 16 ) +#define SR_SWC ( 1L << 17 ) +#define SR_TS ( 1L << 21 ) +#define SR_BEV ( 1L << 22 ) +#define SR_RE ( 1L << 25 ) +#define SR_CU0 ( 1L << 28 ) +#define SR_CU1 ( 1L << 29 ) +#define SR_CU2 ( 1L << 30 ) +#define SR_CU3 ( 1L << 31 ) + +#define CAUSE_EXC ( 31L << 2 ) +#define CAUSE_IP ( 255L << 8 ) +#define CAUSE_IP2 ( 1L << 10 ) +#define CAUSE_IP3 ( 1L << 11 ) +#define CAUSE_IP4 ( 1L << 12 ) +#define CAUSE_IP5 ( 1L << 13 ) +#define CAUSE_IP6 ( 1L << 14 ) +#define CAUSE_IP7 ( 1L << 15 ) +#define CAUSE_CE ( 3L << 28 ) +#define CAUSE_CE0 ( 0L << 28 ) +#define CAUSE_CE1 ( 1L << 28 ) +#define CAUSE_CE2 ( 2L << 28 ) +#define CAUSE_BD ( 1L << 31 ) + +static UINT8 mips_reg_layout[] = +{ + MIPS_PC, -1, + MIPS_DELAYV, MIPS_DELAYR, -1, + MIPS_HI, MIPS_LO, -1, + -1, + MIPS_R0, MIPS_R1, -1, + MIPS_R2, MIPS_R3, -1, + MIPS_R4, MIPS_R5, -1, + MIPS_R6, MIPS_R7, -1, + MIPS_R8, MIPS_R9, -1, + MIPS_R10, MIPS_R11, -1, + MIPS_R12, MIPS_R13, -1, + MIPS_R14, MIPS_R15, -1, + MIPS_R16, MIPS_R17, -1, + MIPS_R18, MIPS_R19, -1, + MIPS_R20, MIPS_R21, -1, + MIPS_R22, MIPS_R23, -1, + MIPS_R24, MIPS_R25, -1, + MIPS_R26, MIPS_R27, -1, + MIPS_R28, MIPS_R29, -1, + MIPS_R30, MIPS_R31, -1, + -1, + MIPS_CP0R0, MIPS_CP0R1, -1, + MIPS_CP0R2, MIPS_CP0R3, -1, + MIPS_CP0R4, MIPS_CP0R5, -1, + MIPS_CP0R6, MIPS_CP0R7, -1, + MIPS_CP0R8, MIPS_CP0R9, -1, + MIPS_CP0R10, MIPS_CP0R11, -1, + MIPS_CP0R12, MIPS_CP0R13, -1, + MIPS_CP0R14, MIPS_CP0R15, -1, + MIPS_CP0R16, MIPS_CP0R17, -1, + MIPS_CP0R18, MIPS_CP0R19, -1, + MIPS_CP0R20, MIPS_CP0R21, -1, + MIPS_CP0R22, MIPS_CP0R23, -1, + MIPS_CP0R24, MIPS_CP0R25, -1, + MIPS_CP0R26, MIPS_CP0R27, -1, + MIPS_CP0R28, MIPS_CP0R29, -1, + MIPS_CP0R30, MIPS_CP0R31, -1, + -1, + MIPS_CP2DR0, MIPS_CP2DR1, -1, + MIPS_CP2DR2, MIPS_CP2DR3, -1, + MIPS_CP2DR4, MIPS_CP2DR5, -1, + MIPS_CP2DR6, MIPS_CP2DR7, -1, + MIPS_CP2DR8, MIPS_CP2DR9, -1, + MIPS_CP2DR10, MIPS_CP2DR11, -1, + MIPS_CP2DR12, MIPS_CP2DR13, -1, + MIPS_CP2DR14, MIPS_CP2DR15, -1, + MIPS_CP2DR16, MIPS_CP2DR17, -1, + MIPS_CP2DR18, MIPS_CP2DR19, -1, + MIPS_CP2DR20, MIPS_CP2DR21, -1, + MIPS_CP2DR22, MIPS_CP2DR23, -1, + MIPS_CP2DR24, MIPS_CP2DR25, -1, + MIPS_CP2DR26, MIPS_CP2DR27, -1, + MIPS_CP2DR28, MIPS_CP2DR29, -1, + MIPS_CP2DR30, MIPS_CP2DR31, -1, + -1, + MIPS_CP2CR0, MIPS_CP2CR1, -1, + MIPS_CP2CR2, MIPS_CP2CR3, -1, + MIPS_CP2CR4, MIPS_CP2CR5, -1, + MIPS_CP2CR6, MIPS_CP2CR7, -1, + MIPS_CP2CR8, MIPS_CP2CR9, -1, + MIPS_CP2CR10, MIPS_CP2CR11, -1, + MIPS_CP2CR12, MIPS_CP2CR13, -1, + MIPS_CP2CR14, MIPS_CP2CR15, -1, + MIPS_CP2CR16, MIPS_CP2CR17, -1, + MIPS_CP2CR18, MIPS_CP2CR19, -1, + MIPS_CP2CR20, MIPS_CP2CR21, -1, + MIPS_CP2CR22, MIPS_CP2CR23, -1, + MIPS_CP2CR24, MIPS_CP2CR25, -1, + MIPS_CP2CR26, MIPS_CP2CR27, -1, + MIPS_CP2CR28, MIPS_CP2CR29, -1, + MIPS_CP2CR30, MIPS_CP2CR31, + 0 +}; + +static UINT8 mips_win_layout[] = { + 45, 0,35,13, /* register window (top right) */ + 0, 0,44,13, /* disassembler window (left, upper) */ + 0,14,44, 8, /* memory #1 window (left, middle) */ + 45,14,35, 8, /* memory #2 window (lower) */ + 0,23,80, 1 /* command line window (bottom rows) */ +}; + +static const char *delayn[] = +{ + "pc", "at", "v0", "v1", "a0", "a1", "a2", "a3", + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", + "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", + "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra", + "pc" +}; + +#define REGPC ( 32 ) + +//static mips_cpu_context mipscpu; + +static UINT32 mips_mtc0_writemask[]= +{ + 0xffffffff, /* INDEX */ + 0x00000000, /* RANDOM */ + 0xffffff00, /* ENTRYLO */ + 0x00000000, + 0xffe00000, /* CONTEXT */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, /* BADVADDR */ + 0x00000000, + 0xffffffc0, /* ENTRYHI */ + 0x00000000, + 0xf27fff3f, /* SR */ + 0x00000300, /* CAUSE */ + 0x00000000, /* EPC */ + 0x00000000, /* PRID */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000 +}; + +#if 0 +void GTELOG(const char *a,...) +{ + va_list va; + char s_text[ 1024 ]; + va_start( va, a ); + vsprintf( s_text, a, va ); + va_end( va ); + logerror( "%08x: GTE: %08x %s\n", cpu->pc, INS_COFUN( cpu->op ), s_text ); +} +#else +INLINE void GTELOG(const char *a, ...) {} +#endif + +static UINT32 getcp2dr( mips_cpu_context *cpu, int n_reg ); +static void setcp2dr( mips_cpu_context *cpu, int n_reg, UINT32 n_value ); +static UINT32 getcp2cr( mips_cpu_context *cpu, int n_reg ); +static void setcp2cr( mips_cpu_context *cpu, int n_reg, UINT32 n_value ); +static void docop2( mips_cpu_context *cpu, int gteop ); +static void mips_exception(mips_cpu_context *cpu, int exception ); + +void mips_stop( void ) +{ +#ifdef MAME_DEBUG + extern int debug_key_pressed; + debug_key_pressed = 1; + CALL_MAME_DEBUG; +#endif +} + +INLINE void mips_set_cp0r(mips_cpu_context *cpu, int reg, UINT32 value ) +{ + cpu->cp0r[ reg ] = value; + if( reg == CP0_SR || reg == CP0_CAUSE ) + { + if( ( cpu->cp0r[ CP0_SR ] & SR_IEC ) != 0 && ( cpu->cp0r[ CP0_SR ] & cpu->cp0r[ CP0_CAUSE ] & CAUSE_IP ) != 0 ) + { + mips_exception(cpu, EXC_INT ); + } + else if( cpu->delayr != REGPC && ( cpu->pc & ( ( ( cpu->cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 3 ) ) != 0 ) + { + mips_exception( cpu, EXC_ADEL ); + mips_set_cp0r( cpu, CP0_BADVADDR, cpu->pc ); + } + } +} + +INLINE void mips_commit_delayed_load(mips_cpu_context *cpu) +{ + if( cpu->delayr != 0 ) + { + cpu->r[ cpu->delayr ] = cpu->delayv; + cpu->delayr = 0; + cpu->delayv = 0; + } +} + +INLINE void mips_delayed_branch(mips_cpu_context *cpu, UINT32 n_adr ) +{ + if( ( n_adr & ( ( ( cpu->cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 3 ) ) != 0 ) + { + mips_exception( cpu, EXC_ADEL ); + mips_set_cp0r( cpu, CP0_BADVADDR, n_adr ); + } + else + { + mips_commit_delayed_load(cpu); + cpu->delayr = REGPC; + cpu->delayv = n_adr; + cpu->pc += 4; + } +} + +INLINE void mips_set_pc(mips_cpu_context *cpu, unsigned val ) +{ + cpu->pc = val; + change_pc( val ); + cpu->delayr = 0; + cpu->delayv = 0; +} + +INLINE void mips_advance_pc(mips_cpu_context *cpu) +{ + if( cpu->delayr == REGPC ) + { + mips_set_pc( cpu, cpu->delayv ); + } + else + { + mips_commit_delayed_load(cpu); + cpu->pc += 4; + } +} + +INLINE void mips_load(mips_cpu_context *cpu, UINT32 n_r, UINT32 n_v ) +{ + mips_advance_pc(cpu); + if( n_r != 0 ) + { + cpu->r[ n_r ] = n_v; + } +} + +INLINE void mips_delayed_load( mips_cpu_context *cpu, UINT32 n_r, UINT32 n_v ) +{ + if( cpu->delayr == REGPC ) + { + mips_set_pc( cpu, cpu->delayv ); + cpu->delayr = n_r; + cpu->delayv = n_v; + } + else + { + mips_commit_delayed_load(cpu); + cpu->pc += 4; + if( n_r != 0 ) + { + cpu->r[ n_r ] = n_v; + } + } +} + +static void mips_exception( mips_cpu_context *cpu, int exception ) +{ + mips_set_cp0r( cpu, CP0_SR, ( cpu->cp0r[ CP0_SR ] & ~0x3f ) | ( ( cpu->cp0r[ CP0_SR ] << 2 ) & 0x3f ) ); + if( cpu->delayr == REGPC ) + { + mips_set_cp0r( cpu, CP0_EPC, cpu->pc - 4 ); + mips_set_cp0r( cpu, CP0_CAUSE, ( cpu->cp0r[ CP0_CAUSE ] & ~CAUSE_EXC ) | CAUSE_BD | ( exception << 2 ) ); + } + else + { + mips_commit_delayed_load(cpu); + mips_set_cp0r( cpu, CP0_EPC, cpu->pc ); + mips_set_cp0r( cpu, CP0_CAUSE, ( cpu->cp0r[ CP0_CAUSE ] & ~( CAUSE_EXC | CAUSE_BD ) ) | ( exception << 2 ) ); + } + if( cpu->cp0r[ CP0_SR ] & SR_BEV ) + { + mips_set_pc (cpu, 0xbfc00180 ); + } + else + { + mips_set_pc (cpu, 0x80000080 ); + } +} + +mips_cpu_context *mips_alloc( void ) { + mips_cpu_context *ctx = malloc (sizeof (mips_cpu_context)); + memset (ctx, 0, sizeof (mips_cpu_context)); + return ctx; +} + +void mips_init(mips_cpu_context *cpu) +{ +#if 0 + int cpu = cpu_getactivecpu(); + + state_save_register_UINT32( "psxcpu", cpu, "op", &cpu->op, 1 ); + state_save_register_UINT32( "psxcpu", cpu, "pc", &cpu->pc, 1 ); + state_save_register_UINT32( "psxcpu", cpu, "delayv", &cpu->delayv, 1 ); + state_save_register_UINT32( "psxcpu", cpu, "delayr", &cpu->delayr, 1 ); + state_save_register_UINT32( "psxcpu", cpu, "hi", &cpu->hi, 1 ); + state_save_register_UINT32( "psxcpu", cpu, "lo", &cpu->lo, 1 ); + state_save_register_UINT32( "psxcpu", cpu, "r", &cpu->r[ 0 ], 32 ); + state_save_register_UINT32( "psxcpu", cpu, "cp0r", &cpu->cp0r[ 0 ], 32 ); + state_save_register_UINT32( "psxcpu", cpu, "cp2cr", &cpu->cp2cr[ 0 ].d, 32 ); + state_save_register_UINT32( "psxcpu", cpu, "cp2dr", &cpu->cp2dr[ 0 ].d, 32 ); +#endif +} + +void mips_reset( mips_cpu_context *cpu, void *param ) +{ + mips_set_cp0r( cpu, CP0_SR, ( cpu->cp0r[ CP0_SR ] & ~( SR_TS | SR_SWC | SR_KUC | SR_IEC ) ) | SR_BEV ); + mips_set_cp0r( cpu, CP0_RANDOM, 63 ); /* todo: */ + mips_set_cp0r( cpu, CP0_PRID, 0x00000200 ); /* todo: */ + mips_set_pc (cpu, 0xbfc00000 ); + cpu->prevpc = 0xffffffff; +} + +void mips_exit(mips_cpu_context *cpu) { + free (cpu); +} + +void mips_shorten_frame(mips_cpu_context *cpu) +{ + cpu->mips_ICount = 0; +} + +void psx_hw_runcounters(mips_cpu_context *cpu); + +int psxcpu_verbose = 0; + +int mips_execute( mips_cpu_context *cpu, int cycles ) +{ + UINT32 n_res; + + cpu->mips_ICount = cycles; + do + { +// CALL_MAME_DEBUG; + +// psx_hw_runcounters(); + + cpu->op = cpu_readop32( cpu->pc ); + +#if 0 + while (cpu->prevpc == cpu->pc) + { + psx_hw_runcounters(); + cpu->mips_ICount--; + + if (cpu->mips_ICount == 0) return cycles; + } + + // if we're not in a delay slot, update + // if we're in a delay slot and the delay instruction is not NOP, update + if (( cpu->delayr == 0 ) || ((cpu->delayr != 0) && (cpu->op != 0))) + { + cpu->prevpc = cpu->pc; + } +#endif +#if 0 + if (1) //psxcpu_verbose) + { + printf("[%08x: %08x] [SP %08x RA %08x V0 %08x V1 %08x A0 %08x S0 %08x S1 %08x]\n", cpu->pc, cpu->op, cpu->r[29], cpu->r[31], cpu->r[2], cpu->r[3], cpu->r[4], cpu->r[ 16 ], cpu->r[ 17 ]); +// psxcpu_verbose--; + } +#endif + switch( INS_OP( cpu->op ) ) + { + case OP_SPECIAL: + switch( INS_FUNCT( cpu->op ) ) + { + case FUNCT_HLECALL: +// printf("HLECALL, PC = %08x\n", cpu->pc); + psx_bios_hle(cpu, cpu->pc); + break; + case FUNCT_SLL: + mips_load(cpu, INS_RD( cpu->op ), cpu->r[ INS_RT( cpu->op ) ] << INS_SHAMT( cpu->op ) ); + break; + case FUNCT_SRL: + mips_load(cpu, INS_RD( cpu->op ), cpu->r[ INS_RT( cpu->op ) ] >> INS_SHAMT( cpu->op ) ); + break; + case FUNCT_SRA: + mips_load(cpu, INS_RD( cpu->op ), (INT32)cpu->r[ INS_RT( cpu->op ) ] >> INS_SHAMT( cpu->op ) ); + break; + case FUNCT_SLLV: + mips_load(cpu, INS_RD( cpu->op ), cpu->r[ INS_RT( cpu->op ) ] << ( cpu->r[ INS_RS( cpu->op ) ] & 31 ) ); + break; + case FUNCT_SRLV: + mips_load(cpu, INS_RD( cpu->op ), cpu->r[ INS_RT( cpu->op ) ] >> ( cpu->r[ INS_RS( cpu->op ) ] & 31 ) ); + break; + case FUNCT_SRAV: + mips_load(cpu, INS_RD( cpu->op ), (INT32)cpu->r[ INS_RT( cpu->op ) ] >> ( cpu->r[ INS_RS( cpu->op ) ] & 31 ) ); + break; + case FUNCT_JR: + if( INS_RD( cpu->op ) != 0 ) + { + mips_exception( cpu, EXC_RI ); + } + else + { + mips_delayed_branch( cpu, cpu->r[ INS_RS( cpu->op ) ] ); + } + break; + case FUNCT_JALR: + n_res = cpu->pc + 8; + mips_delayed_branch( cpu, cpu->r[ INS_RS( cpu->op ) ] ); + if( INS_RD( cpu->op ) != 0 ) + { + cpu->r[ INS_RD( cpu->op ) ] = n_res; + } + break; + case FUNCT_SYSCALL: + mips_exception( cpu, EXC_SYS ); + break; + case FUNCT_BREAK: + printf("BREAK!\n"); + exit(-1); +// mips_exception( cpu, EXC_BP ); + mips_advance_pc(cpu); + break; + case FUNCT_MFHI: + mips_load(cpu, INS_RD( cpu->op ), cpu->hi ); + break; + case FUNCT_MTHI: + if( INS_RD( cpu->op ) != 0 ) + { + mips_exception(cpu, EXC_RI ); + } + else + { + mips_advance_pc(cpu); + cpu->hi = cpu->r[ INS_RS( cpu->op ) ]; + } + break; + case FUNCT_MFLO: + mips_load(cpu, INS_RD( cpu->op ), cpu->lo ); + break; + case FUNCT_MTLO: + if( INS_RD( cpu->op ) != 0 ) + { + mips_exception(cpu, EXC_RI ); + } + else + { + mips_advance_pc(cpu); + cpu->lo = cpu->r[ INS_RS( cpu->op ) ]; + } + break; + case FUNCT_MULT: + if( INS_RD( cpu->op ) != 0 ) + { + mips_exception(cpu, EXC_RI ); + } + else + { + INT64 n_res64; + n_res64 = MUL_64_32_32( (INT32)cpu->r[ INS_RS( cpu->op ) ], (INT32)cpu->r[ INS_RT( cpu->op ) ] ); + mips_advance_pc(cpu); + cpu->lo = LO32_32_64( n_res64 ); + cpu->hi = HI32_32_64( n_res64 ); + } + break; + case FUNCT_MULTU: + if( INS_RD( cpu->op ) != 0 ) + { + mips_exception(cpu, EXC_RI ); + } + else + { + UINT64 n_res64; + n_res64 = MUL_U64_U32_U32( cpu->r[ INS_RS( cpu->op ) ], cpu->r[ INS_RT( cpu->op ) ] ); + mips_advance_pc(cpu); + cpu->lo = LO32_U32_U64( n_res64 ); + cpu->hi = HI32_U32_U64( n_res64 ); + } + break; + case FUNCT_DIV: + if( INS_RD( cpu->op ) != 0 ) + { + mips_exception(cpu, EXC_RI ); + } + else + { + UINT32 n_div; + UINT32 n_mod; + if( cpu->r[ INS_RT( cpu->op ) ] != 0 ) + { + n_div = (INT32)cpu->r[ INS_RS( cpu->op ) ] / (INT32)cpu->r[ INS_RT( cpu->op ) ]; + n_mod = (INT32)cpu->r[ INS_RS( cpu->op ) ] % (INT32)cpu->r[ INS_RT( cpu->op ) ]; + mips_advance_pc(cpu); + cpu->lo = n_div; + cpu->hi = n_mod; + } + else + { + mips_advance_pc(cpu); + } + } + break; + case FUNCT_DIVU: + if( INS_RD( cpu->op ) != 0 ) + { + mips_exception(cpu, EXC_RI ); + } + else + { + UINT32 n_div; + UINT32 n_mod; + if( cpu->r[ INS_RT( cpu->op ) ] != 0 ) + { + n_div = cpu->r[ INS_RS( cpu->op ) ] / cpu->r[ INS_RT( cpu->op ) ]; + n_mod = cpu->r[ INS_RS( cpu->op ) ] % cpu->r[ INS_RT( cpu->op ) ]; + mips_advance_pc(cpu); + cpu->lo = n_div; + cpu->hi = n_mod; + } + else + { + mips_advance_pc(cpu); + } + } + break; + case FUNCT_ADD: + { + n_res = cpu->r[ INS_RS( cpu->op ) ] + cpu->r[ INS_RT( cpu->op ) ]; + if( (INT32)( ~( cpu->r[ INS_RS( cpu->op ) ] ^ cpu->r[ INS_RT( cpu->op ) ] ) & ( cpu->r[ INS_RS( cpu->op ) ] ^ n_res ) ) < 0 ) + { + mips_exception(cpu, EXC_OVF ); + } + else + { + mips_load(cpu, INS_RD( cpu->op ), n_res ); + } + } + break; + case FUNCT_ADDU: + mips_load(cpu, INS_RD( cpu->op ), cpu->r[ INS_RS( cpu->op ) ] + cpu->r[ INS_RT( cpu->op ) ] ); + break; + case FUNCT_SUB: + n_res = cpu->r[ INS_RS( cpu->op ) ] - cpu->r[ INS_RT( cpu->op ) ]; + if( (INT32)( ( cpu->r[ INS_RS( cpu->op ) ] ^ cpu->r[ INS_RT( cpu->op ) ] ) & ( cpu->r[ INS_RS( cpu->op ) ] ^ n_res ) ) < 0 ) + { + mips_exception(cpu, EXC_OVF ); + } + else + { + mips_load(cpu, INS_RD( cpu->op ), n_res ); + } + break; + case FUNCT_SUBU: + mips_load(cpu, INS_RD( cpu->op ), cpu->r[ INS_RS( cpu->op ) ] - cpu->r[ INS_RT( cpu->op ) ] ); + break; + case FUNCT_AND: + mips_load(cpu, INS_RD( cpu->op ), cpu->r[ INS_RS( cpu->op ) ] & cpu->r[ INS_RT( cpu->op ) ] ); + break; + case FUNCT_OR: + mips_load(cpu, INS_RD( cpu->op ), cpu->r[ INS_RS( cpu->op ) ] | cpu->r[ INS_RT( cpu->op ) ] ); + break; + case FUNCT_XOR: + mips_load(cpu, INS_RD( cpu->op ), cpu->r[ INS_RS( cpu->op ) ] ^ cpu->r[ INS_RT( cpu->op ) ] ); + break; + case FUNCT_NOR: + mips_load(cpu, INS_RD( cpu->op ), ~( cpu->r[ INS_RS( cpu->op ) ] | cpu->r[ INS_RT( cpu->op ) ] ) ); + break; + case FUNCT_SLT: + mips_load(cpu, INS_RD( cpu->op ), (INT32)cpu->r[ INS_RS( cpu->op ) ] < (INT32)cpu->r[ INS_RT( cpu->op ) ] ); + break; + case FUNCT_SLTU: + mips_load(cpu, INS_RD( cpu->op ), cpu->r[ INS_RS( cpu->op ) ] < cpu->r[ INS_RT( cpu->op ) ] ); + break; + default: + mips_exception(cpu, EXC_RI ); + break; + } + break; + case OP_REGIMM: + switch( INS_RT( cpu->op ) ) + { + case RT_BLTZ: + if( (INT32)cpu->r[ INS_RS( cpu->op ) ] < 0 ) + { + mips_delayed_branch( cpu, cpu->pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ) << 2 ) ); + } + else + { + mips_advance_pc(cpu); + } + break; + case RT_BGEZ: + if( (INT32)cpu->r[ INS_RS( cpu->op ) ] >= 0 ) + { + mips_delayed_branch( cpu, cpu->pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ) << 2 ) ); + } + else + { + mips_advance_pc(cpu); + } + break; + case RT_BLTZAL: + n_res = cpu->pc + 8; + if( (INT32)cpu->r[ INS_RS( cpu->op ) ] < 0 ) + { + mips_delayed_branch( cpu, cpu->pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ) << 2 ) ); + } + else + { + mips_advance_pc(cpu); + } + cpu->r[ 31 ] = n_res; + break; + case RT_BGEZAL: + n_res = cpu->pc + 8; + if( (INT32)cpu->r[ INS_RS( cpu->op ) ] >= 0 ) + { + mips_delayed_branch( cpu, cpu->pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ) << 2 ) ); + } + else + { + mips_advance_pc(cpu); + } + cpu->r[ 31 ] = n_res; + break; + } + break; + case OP_J: + mips_delayed_branch( cpu, ( ( cpu->pc + 4 ) & 0xf0000000 ) + ( INS_TARGET( cpu->op ) << 2 ) ); + break; + case OP_JAL: + n_res = cpu->pc + 8; + mips_delayed_branch( cpu, ( ( cpu->pc + 4 ) & 0xf0000000 ) + ( INS_TARGET( cpu->op ) << 2 ) ); + cpu->r[ 31 ] = n_res; + break; + case OP_BEQ: + if( cpu->r[ INS_RS( cpu->op ) ] == cpu->r[ INS_RT( cpu->op ) ] ) + { + mips_delayed_branch( cpu, cpu->pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ) << 2 ) ); + } + else + { + mips_advance_pc(cpu); + } + break; + case OP_BNE: + if( cpu->r[ INS_RS( cpu->op ) ] != cpu->r[ INS_RT( cpu->op ) ] ) + { + mips_delayed_branch( cpu, cpu->pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ) << 2 ) ); + } + else + { + mips_advance_pc(cpu); + } + break; + case OP_BLEZ: + if( INS_RT( cpu->op ) != 0 ) + { + mips_exception(cpu, EXC_RI ); + } + else if( (INT32)cpu->r[ INS_RS( cpu->op ) ] <= 0 ) + { + mips_delayed_branch( cpu, cpu->pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ) << 2 ) ); + } + else + { + mips_advance_pc(cpu); + } + break; + case OP_BGTZ: + if( INS_RT( cpu->op ) != 0 ) + { + mips_exception(cpu, EXC_RI ); + } + else if( (INT32)cpu->r[ INS_RS( cpu->op ) ] > 0 ) + { + mips_delayed_branch( cpu, cpu->pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ) << 2 ) ); + } + else + { + mips_advance_pc(cpu); + } + break; + case OP_ADDI: + { + UINT32 n_imm; + n_imm = MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ); + n_res = cpu->r[ INS_RS( cpu->op ) ] + n_imm; + if( (INT32)( ~( cpu->r[ INS_RS( cpu->op ) ] ^ n_imm ) & ( cpu->r[ INS_RS( cpu->op ) ] ^ n_res ) ) < 0 ) + { + mips_exception(cpu, EXC_OVF ); + } + else + { + mips_load(cpu, INS_RT( cpu->op ), n_res ); + } + } + break; + case OP_ADDIU: + if (INS_RT( cpu->op ) == 0) + { + psx_iop_call(cpu, cpu->pc, INS_IMMEDIATE(cpu->op)); + mips_advance_pc(cpu); + } + else + { + mips_load(cpu, INS_RT( cpu->op ), cpu->r[ INS_RS( cpu->op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ) ); + } + break; + case OP_SLTI: + mips_load(cpu, INS_RT( cpu->op ), (INT32)cpu->r[ INS_RS( cpu->op ) ] < MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ) ); + break; + case OP_SLTIU: + mips_load(cpu, INS_RT( cpu->op ), cpu->r[ INS_RS( cpu->op ) ] < (UINT32)MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ) ); + break; + case OP_ANDI: + mips_load(cpu, INS_RT( cpu->op ), cpu->r[ INS_RS( cpu->op ) ] & INS_IMMEDIATE( cpu->op ) ); + break; + case OP_ORI: + mips_load(cpu, INS_RT( cpu->op ), cpu->r[ INS_RS( cpu->op ) ] | INS_IMMEDIATE( cpu->op ) ); + break; + case OP_XORI: + mips_load(cpu, INS_RT( cpu->op ), cpu->r[ INS_RS( cpu->op ) ] ^ INS_IMMEDIATE( cpu->op ) ); + break; + case OP_LUI: + mips_load(cpu, INS_RT( cpu->op ), INS_IMMEDIATE( cpu->op ) << 16 ); + break; + case OP_COP0: + if( ( cpu->cp0r[ CP0_SR ] & SR_KUC ) != 0 && ( cpu->cp0r[ CP0_SR ] & SR_CU0 ) == 0 ) + { + mips_exception(cpu, EXC_CPU ); + mips_set_cp0r( cpu, CP0_CAUSE, ( cpu->cp0r[ CP0_CAUSE ] & ~CAUSE_CE ) | CAUSE_CE0 ); + } + else + { + switch( INS_RS( cpu->op ) ) + { + case RS_MFC: + mips_delayed_load( cpu, INS_RT( cpu->op ), cpu->cp0r[ INS_RD( cpu->op ) ] ); + break; + case RS_CFC: + /* todo: */ + logerror( "%08x: COP0 CFC not supported\n", cpu->pc ); + mips_stop(); + mips_advance_pc(cpu); + break; + case RS_MTC: + n_res = ( cpu->cp0r[ INS_RD( cpu->op ) ] & ~mips_mtc0_writemask[ INS_RD( cpu->op ) ] ) | + ( cpu->r[ INS_RT( cpu->op ) ] & mips_mtc0_writemask[ INS_RD( cpu->op ) ] ); + mips_advance_pc(cpu); + mips_set_cp0r(cpu, INS_RD( cpu->op ), n_res ); + break; + case RS_CTC: + /* todo: */ + logerror( "%08x: COP0 CTC not supported\n", cpu->pc ); + mips_stop(); + mips_advance_pc(cpu); + break; + case RS_BC: + switch( INS_RT( cpu->op ) ) + { + case RT_BCF: + /* todo: */ + logerror( "%08x: COP0 BCF not supported\n", cpu->pc ); + mips_stop(); + mips_advance_pc(cpu); + break; + case RT_BCT: + /* todo: */ + logerror( "%08x: COP0 BCT not supported\n", cpu->pc ); + mips_stop(); + mips_advance_pc(cpu); + break; + default: + /* todo: */ + logerror( "%08x: COP0 unknown command %08x\n", cpu->pc, cpu->op ); + mips_stop(); + mips_advance_pc(cpu); + break; + } + break; + default: + switch( INS_CO( cpu->op ) ) + { + case 1: + switch( INS_CF( cpu->op ) ) + { + case CF_RFE: + mips_advance_pc(cpu); + mips_set_cp0r(cpu, CP0_SR, ( cpu->cp0r[ CP0_SR ] & ~0xf ) | ( ( cpu->cp0r[ CP0_SR ] >> 2 ) & 0xf ) ); + break; + default: + /* todo: */ + logerror( "%08x: COP0 unknown command %08x\n", cpu->pc, cpu->op ); + mips_stop(); + mips_advance_pc(cpu); + break; + } + break; + default: + /* todo: */ + logerror( "%08x: COP0 unknown command %08x\n", cpu->pc, cpu->op ); + mips_stop(); + mips_advance_pc(cpu); + break; + } + break; + } + } + break; + case OP_COP1: + if( ( cpu->cp0r[ CP0_SR ] & SR_CU1 ) == 0 ) + { + mips_exception(cpu, EXC_CPU ); + mips_set_cp0r(cpu, CP0_CAUSE, ( cpu->cp0r[ CP0_CAUSE ] & ~CAUSE_CE ) | CAUSE_CE1 ); + } + else + { + switch( INS_RS( cpu->op ) ) + { + case RS_MFC: + /* todo: */ + logerror( "%08x: COP1 BCT not supported\n", cpu->pc ); + mips_stop(); + mips_advance_pc(cpu); + break; + case RS_CFC: + /* todo: */ + logerror( "%08x: COP1 CFC not supported\n", cpu->pc ); + mips_stop(); + mips_advance_pc(cpu); + break; + case RS_MTC: + /* todo: */ + logerror( "%08x: COP1 MTC not supported\n", cpu->pc ); + mips_stop(); + mips_advance_pc(cpu); + break; + case RS_CTC: + /* todo: */ + logerror( "%08x: COP1 CTC not supported\n", cpu->pc ); + mips_stop(); + mips_advance_pc(cpu); + break; + case RS_BC: + switch( INS_RT( cpu->op ) ) + { + case RT_BCF: + /* todo: */ + logerror( "%08x: COP1 BCF not supported\n", cpu->pc ); + mips_stop(); + mips_advance_pc(cpu); + break; + case RT_BCT: + /* todo: */ + logerror( "%08x: COP1 BCT not supported\n", cpu->pc ); + mips_stop(); + mips_advance_pc(cpu); + break; + default: + /* todo: */ + logerror( "%08x: COP1 unknown command %08x\n", cpu->pc, cpu->op ); + mips_stop(); + mips_advance_pc(cpu); + break; + } + break; + default: + switch( INS_CO( cpu->op ) ) + { + case 1: + /* todo: */ + logerror( "%08x: COP1 unknown command %08x\n", cpu->pc, cpu->op ); + mips_stop(); + mips_advance_pc(cpu); + break; + default: + /* todo: */ + logerror( "%08x: COP1 unknown command %08x\n", cpu->pc, cpu->op ); + mips_stop(); + mips_advance_pc(cpu); + break; + } + break; + } + } + break; + case OP_COP2: + if( ( cpu->cp0r[ CP0_SR ] & SR_CU2 ) == 0 ) + { + mips_exception(cpu, EXC_CPU ); + mips_set_cp0r(cpu, CP0_CAUSE, ( cpu->cp0r[ CP0_CAUSE ] & ~CAUSE_CE ) | CAUSE_CE2 ); + } + else + { + switch( INS_RS( cpu->op ) ) + { + case RS_MFC: + mips_delayed_load(cpu, INS_RT( cpu->op ), getcp2dr(cpu, INS_RD( cpu->op ) ) ); + break; + case RS_CFC: + mips_delayed_load(cpu, INS_RT( cpu->op ), getcp2cr(cpu, INS_RD( cpu->op ) ) ); + break; + case RS_MTC: + setcp2dr(cpu, INS_RD( cpu->op ), cpu->r[ INS_RT( cpu->op ) ] ); + mips_advance_pc(cpu); + break; + case RS_CTC: + setcp2cr(cpu, INS_RD( cpu->op ), cpu->r[ INS_RT( cpu->op ) ] ); + mips_advance_pc(cpu); + break; + case RS_BC: + switch( INS_RT( cpu->op ) ) + { + case RT_BCF: + /* todo: */ + logerror( "%08x: COP2 BCF not supported\n", cpu->pc ); + mips_stop(); + mips_advance_pc(cpu); + break; + case RT_BCT: + /* todo: */ + logerror( "%08x: COP2 BCT not supported\n", cpu->pc ); + mips_stop(); + mips_advance_pc(cpu); + break; + default: + /* todo: */ + logerror( "%08x: COP2 unknown command %08x\n", cpu->pc, cpu->op ); + mips_stop(); + mips_advance_pc(cpu); + break; + } + break; + default: + switch( INS_CO( cpu->op ) ) + { + case 1: + docop2(cpu, INS_COFUN( cpu->op ) ); + mips_advance_pc(cpu); + break; + default: + /* todo: */ + logerror( "%08x: COP2 unknown command %08x\n", cpu->pc, cpu->op ); + mips_stop(); + mips_advance_pc(cpu); + break; + } + break; + } + } + break; + case OP_LB: + if( ( cpu->cp0r[ CP0_SR ] & SR_ISC ) != 0 ) + { + /* todo: */ + logerror( "%08x: LB SR_ISC not supported\n", cpu->pc ); + mips_stop(); + mips_advance_pc(cpu); + } + else if( ( cpu->cp0r[ CP0_SR ] & ( SR_RE | SR_KUC ) ) == ( SR_RE | SR_KUC ) ) + { + UINT32 n_adr; + n_adr = cpu->r[ INS_RS( cpu->op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ); + if( ( n_adr & ( ( cpu->cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 ) + { + mips_exception(cpu, EXC_ADEL ); + mips_set_cp0r(cpu, CP0_BADVADDR, n_adr ); + } + else + { + mips_delayed_load(cpu, INS_RT( cpu->op ), MIPS_BYTE_EXTEND( program_read_byte_32le( cpu, n_adr ^ 3 ) ) ); + } + } + else + { + UINT32 n_adr; + n_adr = cpu->r[ INS_RS( cpu->op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ); + if( ( n_adr & ( ( cpu->cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 ) + { + mips_exception(cpu, EXC_ADEL ); + mips_set_cp0r(cpu, CP0_BADVADDR, n_adr ); + } + else + { + mips_delayed_load(cpu, INS_RT( cpu->op ), MIPS_BYTE_EXTEND( program_read_byte_32le( cpu, n_adr ) ) ); + } + } + break; + case OP_LH: + if( ( cpu->cp0r[ CP0_SR ] & SR_ISC ) != 0 ) + { + /* todo: */ + logerror( "%08x: LH SR_ISC not supported\n", cpu->pc ); + mips_stop(); + mips_advance_pc(cpu); + } + else if( ( cpu->cp0r[ CP0_SR ] & ( SR_RE | SR_KUC ) ) == ( SR_RE | SR_KUC ) ) + { + UINT32 n_adr; + n_adr = cpu->r[ INS_RS( cpu->op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ); + if( ( n_adr & ( ( ( cpu->cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 1 ) ) != 0 ) + { + mips_exception(cpu, EXC_ADEL ); + mips_set_cp0r(cpu, CP0_BADVADDR, n_adr ); + } + else + { + mips_delayed_load(cpu, INS_RT( cpu->op ), MIPS_WORD_EXTEND( program_read_word_32le( cpu, n_adr ^ 2 ) ) ); + } + } + else + { + UINT32 n_adr; + n_adr = cpu->r[ INS_RS( cpu->op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ); + if( ( n_adr & ( ( ( cpu->cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 1 ) ) != 0 ) + { + mips_exception(cpu, EXC_ADEL ); + mips_set_cp0r(cpu, CP0_BADVADDR, n_adr ); + } + else + { + mips_delayed_load(cpu, INS_RT( cpu->op ), MIPS_WORD_EXTEND( program_read_word_32le( cpu, n_adr ) ) ); + } + } + break; + case OP_LWL: + if( ( cpu->cp0r[ CP0_SR ] & SR_ISC ) != 0 ) + { + /* todo: */ + logerror( "%08x: LWL SR_ISC not supported\n", cpu->pc ); + mips_stop(); + mips_advance_pc(cpu); + } + else if( ( cpu->cp0r[ CP0_SR ] & ( SR_RE | SR_KUC ) ) == ( SR_RE | SR_KUC ) ) + { + UINT32 n_adr; + n_adr = cpu->r[ INS_RS( cpu->op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ); + if( ( n_adr & ( ( cpu->cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 ) + { + mips_exception(cpu, EXC_ADEL ); + mips_set_cp0r(cpu, CP0_BADVADDR, n_adr ); + } + else + { + switch( n_adr & 3 ) + { + case 0: + n_res = ( cpu->r[ INS_RT( cpu->op ) ] & 0x00ffffff ) | ( (UINT32)program_read_byte_32le( cpu, n_adr + 3 ) << 24 ); + break; + case 1: + n_res = ( cpu->r[ INS_RT( cpu->op ) ] & 0x0000ffff ) | ( (UINT32)program_read_word_32le( cpu, n_adr + 1 ) << 16 ); + break; + case 2: + n_res = ( cpu->r[ INS_RT( cpu->op ) ] & 0x000000ff ) | ( (UINT32)program_read_byte_32le( cpu, n_adr - 1 ) << 8 ) | ( (UINT32)program_read_word_32le( cpu, n_adr ) << 16 ); + break; + default: + n_res = program_read_dword_32le( cpu, n_adr - 3 ); + break; + } + mips_delayed_load(cpu, INS_RT( cpu->op ), n_res ); + } + } + else + { + UINT32 n_adr; + n_adr = cpu->r[ INS_RS( cpu->op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ); + if( ( n_adr & ( ( cpu->cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 ) + { + mips_exception(cpu, EXC_ADEL ); + mips_set_cp0r(cpu, CP0_BADVADDR, n_adr ); + } + else + { + switch( n_adr & 3 ) + { + case 0: + n_res = ( cpu->r[ INS_RT( cpu->op ) ] & 0x00ffffff ) | ( (UINT32)program_read_byte_32le( cpu, n_adr ) << 24 ); + break; + case 1: + n_res = ( cpu->r[ INS_RT( cpu->op ) ] & 0x0000ffff ) | ( (UINT32)program_read_word_32le( cpu, n_adr - 1 ) << 16 ); + break; + case 2: + n_res = ( cpu->r[ INS_RT( cpu->op ) ] & 0x000000ff ) | ( (UINT32)program_read_word_32le( cpu, n_adr - 2 ) << 8 ) | ( (UINT32)program_read_byte_32le( cpu, n_adr ) << 24 ); + break; + default: + n_res = program_read_dword_32le( cpu, n_adr - 3 ); + break; + } + mips_delayed_load(cpu, INS_RT( cpu->op ), n_res ); + } + } + break; + case OP_LW: + if( ( cpu->cp0r[ CP0_SR ] & SR_ISC ) != 0 ) + { + /* todo: */ + logerror( "%08x: LW SR_ISC not supported\n", cpu->pc ); + mips_stop(); + mips_advance_pc(cpu); + } + else + { + UINT32 n_adr; + n_adr = cpu->r[ INS_RS( cpu->op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ); +#if 0 + if( ( n_adr & ( ( ( cpu->cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 3 ) ) != 0 ) + { + printf("ADEL\n"); + mips_exception(cpu, EXC_ADEL ); + mips_set_cp0r(cpu, CP0_BADVADDR, n_adr ); + } + else +#endif + { + mips_delayed_load(cpu, INS_RT( cpu->op ), program_read_dword_32le( cpu, n_adr ) ); + } + } + break; + case OP_LBU: + if( ( cpu->cp0r[ CP0_SR ] & SR_ISC ) != 0 ) + { + /* todo: */ + logerror( "%08x: LBU SR_ISC not supported\n", cpu->pc ); + mips_stop(); + mips_advance_pc(cpu); + } + else if( ( cpu->cp0r[ CP0_SR ] & ( SR_RE | SR_KUC ) ) == ( SR_RE | SR_KUC ) ) + { + UINT32 n_adr; + n_adr = cpu->r[ INS_RS( cpu->op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ); + if( ( n_adr & ( ( cpu->cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 ) + { + mips_exception(cpu, EXC_ADEL ); + mips_set_cp0r(cpu, CP0_BADVADDR, n_adr ); + } + else + { + mips_delayed_load(cpu, INS_RT( cpu->op ), program_read_byte_32le( cpu, n_adr ^ 3 ) ); + } + } + else + { + UINT32 n_adr; + n_adr = cpu->r[ INS_RS( cpu->op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ); + if( ( n_adr & ( ( cpu->cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 ) + { + mips_exception(cpu, EXC_ADEL ); + mips_set_cp0r(cpu, CP0_BADVADDR, n_adr ); + } + else + { + mips_delayed_load(cpu, INS_RT( cpu->op ), program_read_byte_32le( cpu, n_adr ) ); + } + } + break; + case OP_LHU: + if( ( cpu->cp0r[ CP0_SR ] & SR_ISC ) != 0 ) + { + /* todo: */ + logerror( "%08x: LHU SR_ISC not supported\n", cpu->pc ); + mips_stop(); + mips_advance_pc(cpu); + } + else if( ( cpu->cp0r[ CP0_SR ] & ( SR_RE | SR_KUC ) ) == ( SR_RE | SR_KUC ) ) + { + UINT32 n_adr; + n_adr = cpu->r[ INS_RS( cpu->op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ); + if( ( n_adr & ( ( ( cpu->cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 1 ) ) != 0 ) + { + mips_exception(cpu, EXC_ADEL ); + mips_set_cp0r(cpu, CP0_BADVADDR, n_adr ); + } + else + { + mips_delayed_load(cpu, INS_RT( cpu->op ), program_read_word_32le( cpu, n_adr ^ 2 ) ); + } + } + else + { + UINT32 n_adr; + n_adr = cpu->r[ INS_RS( cpu->op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ); + if( ( n_adr & ( ( ( cpu->cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 1 ) ) != 0 ) + { + mips_exception(cpu, EXC_ADEL ); + mips_set_cp0r(cpu, CP0_BADVADDR, n_adr ); + } + else + { + mips_delayed_load(cpu, INS_RT( cpu->op ), program_read_word_32le( cpu, n_adr ) ); + } + } + break; + case OP_LWR: + if( ( cpu->cp0r[ CP0_SR ] & SR_ISC ) != 0 ) + { + /* todo: */ + logerror( "%08x: LWR SR_ISC not supported\n", cpu->pc ); + mips_stop(); + mips_advance_pc(cpu); + } + else if( ( cpu->cp0r[ CP0_SR ] & ( SR_RE | SR_KUC ) ) == ( SR_RE | SR_KUC ) ) + { + UINT32 n_adr; + n_adr = cpu->r[ INS_RS( cpu->op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ); + if( ( n_adr & ( ( cpu->cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 ) + { + mips_exception(cpu, EXC_ADEL ); + mips_set_cp0r(cpu, CP0_BADVADDR, n_adr ); + } + else + { + switch( n_adr & 3 ) + { + case 3: + n_res = ( cpu->r[ INS_RT( cpu->op ) ] & 0xffffff00 ) | program_read_byte_32le( cpu, n_adr - 3 ); + break; + case 2: + n_res = ( cpu->r[ INS_RT( cpu->op ) ] & 0xffff0000 ) | program_read_word_32le( cpu, n_adr - 2 ); + break; + case 1: + n_res = ( cpu->r[ INS_RT( cpu->op ) ] & 0xff000000 ) | program_read_word_32le( cpu, n_adr - 1 ) | ( (UINT32)program_read_byte_32le( cpu, n_adr + 1 ) << 16 ); + break; + default: + n_res = program_read_dword_32le( cpu, n_adr ); + break; + } + mips_delayed_load(cpu, INS_RT( cpu->op ), n_res ); + } + } + else + { + UINT32 n_adr; + n_adr = cpu->r[ INS_RS( cpu->op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ); + if( ( n_adr & ( ( cpu->cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 ) + { + mips_exception(cpu, EXC_ADEL ); + mips_set_cp0r(cpu, CP0_BADVADDR, n_adr ); + } + else + { + switch( n_adr & 3 ) + { + case 3: + n_res = ( cpu->r[ INS_RT( cpu->op ) ] & 0xffffff00 ) | program_read_byte_32le( cpu, n_adr ); + break; + case 2: + n_res = ( cpu->r[ INS_RT( cpu->op ) ] & 0xffff0000 ) | program_read_word_32le( cpu, n_adr ); + break; + case 1: + n_res = ( cpu->r[ INS_RT( cpu->op ) ] & 0xff000000 ) | program_read_byte_32le( cpu, n_adr ) | ( (UINT32)program_read_word_32le( cpu, n_adr + 1 ) << 8 ); + break; + default: + n_res = program_read_dword_32le( cpu, n_adr ); + break; + } + mips_delayed_load(cpu, INS_RT( cpu->op ), n_res ); + } + } + break; + case OP_SB: + if( ( cpu->cp0r[ CP0_SR ] & SR_ISC ) != 0 ) + { + /* todo: */ + logerror( "%08x: SB SR_ISC not supported\n", cpu->pc ); + mips_stop(); + mips_advance_pc(cpu); + } + else if( ( cpu->cp0r[ CP0_SR ] & ( SR_RE | SR_KUC ) ) == ( SR_RE | SR_KUC ) ) + { + UINT32 n_adr; + n_adr = cpu->r[ INS_RS( cpu->op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ); + if( ( n_adr & ( ( cpu->cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 ) + { + mips_exception(cpu, EXC_ADES ); + mips_set_cp0r(cpu, CP0_BADVADDR, n_adr ); + } + else + { + program_write_byte_32le( cpu, n_adr ^ 3, cpu->r[ INS_RT( cpu->op ) ] ); + mips_advance_pc(cpu); + } + } + else + { + UINT32 n_adr; + n_adr = cpu->r[ INS_RS( cpu->op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ); + if( ( n_adr & ( ( cpu->cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 ) + { + mips_exception(cpu, EXC_ADES ); + mips_set_cp0r(cpu, CP0_BADVADDR, n_adr ); + } + else + { + program_write_byte_32le( cpu, n_adr, cpu->r[ INS_RT( cpu->op ) ] ); + mips_advance_pc(cpu); + } + } + break; + case OP_SH: + if( ( cpu->cp0r[ CP0_SR ] & SR_ISC ) != 0 ) + { + /* todo: */ + logerror( "%08x: SH SR_ISC not supported\n", cpu->pc ); + mips_stop(); + mips_advance_pc(cpu); + } + else if( ( cpu->cp0r[ CP0_SR ] & ( SR_RE | SR_KUC ) ) == ( SR_RE | SR_KUC ) ) + { + UINT32 n_adr; + n_adr = cpu->r[ INS_RS( cpu->op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ); + if( ( n_adr & ( ( ( cpu->cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 1 ) ) != 0 ) + { + mips_exception(cpu, EXC_ADES ); + mips_set_cp0r(cpu, CP0_BADVADDR, n_adr ); + } + else + { + program_write_word_32le( cpu, n_adr ^ 2, cpu->r[ INS_RT( cpu->op ) ] ); + mips_advance_pc(cpu); + } + } + else + { + UINT32 n_adr; + n_adr = cpu->r[ INS_RS( cpu->op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ); + if( ( n_adr & ( ( ( cpu->cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 1 ) ) != 0 ) + { + mips_exception(cpu, EXC_ADES ); + mips_set_cp0r(cpu, CP0_BADVADDR, n_adr ); + } + else + { + program_write_word_32le( cpu, n_adr, cpu->r[ INS_RT( cpu->op ) ] ); + mips_advance_pc(cpu); + } + } + break; + case OP_SWL: + if( ( cpu->cp0r[ CP0_SR ] & SR_ISC ) != 0 ) + { + /* todo: */ + printf("SR_ISC not supported\n"); + logerror( "%08x: SWL SR_ISC not supported\n", cpu->pc ); + mips_stop(); + mips_advance_pc(cpu); + } + else if( ( cpu->cp0r[ CP0_SR ] & ( SR_RE | SR_KUC ) ) == ( SR_RE | SR_KUC ) ) + { + UINT32 n_adr; + n_adr = cpu->r[ INS_RS( cpu->op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ); + if( ( n_adr & ( ( cpu->cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 ) + { + printf("permission violation?\n"); + mips_exception(cpu, EXC_ADES ); + mips_set_cp0r(cpu, CP0_BADVADDR, n_adr ); + } + else + { + switch( n_adr & 3 ) + { + case 0: + program_write_byte_32le( cpu, n_adr + 3, cpu->r[ INS_RT( cpu->op ) ] >> 24 ); + break; + case 1: + program_write_word_32le( cpu, n_adr + 1, cpu->r[ INS_RT( cpu->op ) ] >> 16 ); + break; + case 2: + program_write_byte_32le( cpu, n_adr - 1, cpu->r[ INS_RT( cpu->op ) ] >> 8 ); + program_write_word_32le( cpu, n_adr, cpu->r[ INS_RT( cpu->op ) ] >> 16 ); + break; + case 3: + program_write_dword_32le( cpu, n_adr - 3, cpu->r[ INS_RT( cpu->op ) ] ); + break; + } + mips_advance_pc(cpu); + } + } + else + { + UINT32 n_adr; + n_adr = cpu->r[ INS_RS( cpu->op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ); + if( ( n_adr & ( ( cpu->cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 ) + { + printf("permission violation 2\n"); + mips_exception(cpu, EXC_ADES ); + mips_set_cp0r(cpu, CP0_BADVADDR, n_adr ); + } + else + { + switch( n_adr & 3 ) + { + case 0: + program_write_byte_32le( cpu, n_adr, cpu->r[ INS_RT( cpu->op ) ] >> 24 ); + break; + case 1: + program_write_word_32le( cpu, n_adr - 1, cpu->r[ INS_RT( cpu->op ) ] >> 16 ); + break; + case 2: + program_write_word_32le( cpu, n_adr - 2, cpu->r[ INS_RT( cpu->op ) ] >> 8 ); + program_write_byte_32le( cpu, n_adr, cpu->r[ INS_RT( cpu->op ) ] >> 24 ); + break; + case 3: + program_write_dword_32le( cpu, n_adr - 3, cpu->r[ INS_RT( cpu->op ) ] ); + break; + } + mips_advance_pc(cpu); + } + } + break; + case OP_SW: + if( ( cpu->cp0r[ CP0_SR ] & SR_ISC ) != 0 ) + { + /* todo: */ +/* used by bootstrap + logerror( "%08x: SW SR_ISC not supported\n", cpu->pc ); + mips_stop(); +*/ + mips_advance_pc(cpu); + } + else + { + UINT32 n_adr; + n_adr = cpu->r[ INS_RS( cpu->op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ); + if(0) // ( n_adr & ( ( ( cpu->cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 3 ) ) != 0 ) + { + mips_exception(cpu, EXC_ADES ); + mips_set_cp0r(cpu, CP0_BADVADDR, n_adr ); + } + else + { + program_write_dword_32le( cpu, n_adr, cpu->r[ INS_RT( cpu->op ) ] ); + mips_advance_pc(cpu); + } + } + break; + case OP_SWR: + if( ( cpu->cp0r[ CP0_SR ] & SR_ISC ) != 0 ) + { + /* todo: */ + logerror( "%08x: SWR SR_ISC not supported\n", cpu->pc ); + mips_stop(); + mips_advance_pc(cpu); + } + else if( ( cpu->cp0r[ CP0_SR ] & ( SR_RE | SR_KUC ) ) == ( SR_RE | SR_KUC ) ) + { + UINT32 n_adr; + n_adr = cpu->r[ INS_RS( cpu->op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ); + if( ( n_adr & ( ( cpu->cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 ) + { + mips_exception(cpu, EXC_ADES ); + mips_set_cp0r(cpu, CP0_BADVADDR, n_adr ); + } + else + { + switch( n_adr & 3 ) + { + case 0: + program_write_dword_32le( cpu, n_adr, cpu->r[ INS_RT( cpu->op ) ] ); + break; + case 1: + program_write_word_32le( cpu, n_adr - 1, cpu->r[ INS_RT( cpu->op ) ] ); + program_write_byte_32le( cpu, n_adr + 1, cpu->r[ INS_RT( cpu->op ) ] >> 16 ); + break; + case 2: + program_write_word_32le( cpu, n_adr - 2, cpu->r[ INS_RT( cpu->op ) ] ); + break; + case 3: + program_write_byte_32le( cpu, n_adr - 3, cpu->r[ INS_RT( cpu->op ) ] ); + break; + } + mips_advance_pc(cpu); + } + } + else + { + UINT32 n_adr; + n_adr = cpu->r[ INS_RS( cpu->op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ); + if( ( n_adr & ( ( cpu->cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 ) + { + mips_exception(cpu, EXC_ADES ); + mips_set_cp0r(cpu, CP0_BADVADDR, n_adr ); + } + else + { + switch( n_adr & 3 ) + { + case 0: + program_write_dword_32le( cpu, n_adr, cpu->r[ INS_RT( cpu->op ) ] ); + break; + case 1: + program_write_byte_32le( cpu, n_adr, cpu->r[ INS_RT( cpu->op ) ] ); + program_write_word_32le( cpu, n_adr + 1, cpu->r[ INS_RT( cpu->op ) ] >> 8 ); + break; + case 2: + program_write_word_32le( cpu, n_adr, cpu->r[ INS_RT( cpu->op ) ] ); + break; + case 3: + program_write_byte_32le( cpu, n_adr, cpu->r[ INS_RT( cpu->op ) ] ); + break; + } + mips_advance_pc(cpu); + } + } + break; + case OP_LWC1: + /* todo: */ + logerror( "%08x: COP1 LWC not supported\n", cpu->pc ); + mips_stop(); + mips_advance_pc(cpu); + break; + case OP_LWC2: + if( ( cpu->cp0r[ CP0_SR ] & SR_CU2 ) == 0 ) + { + mips_exception(cpu, EXC_CPU ); + mips_set_cp0r(cpu, CP0_CAUSE, ( cpu->cp0r[ CP0_CAUSE ] & ~CAUSE_CE ) | CAUSE_CE2 ); + } + else if( ( cpu->cp0r[ CP0_SR ] & SR_ISC ) != 0 ) + { + /* todo: */ + logerror( "%08x: LWC2 SR_ISC not supported\n", cpu->pc ); + mips_stop(); + mips_advance_pc(cpu); + } + else + { + UINT32 n_adr; + n_adr = cpu->r[ INS_RS( cpu->op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ); + if( ( n_adr & ( ( ( cpu->cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 3 ) ) != 0 ) + { + mips_exception(cpu, EXC_ADEL ); + mips_set_cp0r(cpu, CP0_BADVADDR, n_adr ); + } + else + { + /* todo: delay? */ + setcp2dr(cpu, INS_RT( cpu->op ), program_read_dword_32le( cpu, n_adr ) ); + mips_advance_pc(cpu); + } + } + break; + case OP_SWC1: + /* todo: */ + logerror( "%08x: COP1 SWC not supported\n", cpu->pc ); + mips_stop(); + mips_advance_pc(cpu); + break; + case OP_SWC2: + if( ( cpu->cp0r[ CP0_SR ] & SR_CU2 ) == 0 ) + { + mips_exception(cpu, EXC_CPU ); + mips_set_cp0r(cpu, CP0_CAUSE, ( cpu->cp0r[ CP0_CAUSE ] & ~CAUSE_CE ) | CAUSE_CE2 ); + } + else if( ( cpu->cp0r[ CP0_SR ] & SR_ISC ) != 0 ) + { + /* todo: */ + logerror( "%08x: SWC2 SR_ISC not supported\n", cpu->pc ); + mips_stop(); + mips_advance_pc(cpu); + } + else + { + UINT32 n_adr; + n_adr = cpu->r[ INS_RS( cpu->op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( cpu->op ) ); + if( ( n_adr & ( ( ( cpu->cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 3 ) ) != 0 ) + { + mips_exception(cpu, EXC_ADES ); + mips_set_cp0r(cpu, CP0_BADVADDR, n_adr ); + } + else + { + program_write_dword_32le( cpu, n_adr, getcp2dr(cpu, INS_RT( cpu->op ) ) ); + mips_advance_pc(cpu); + } + } + break; + default: +// printf( "%08x: unknown opcode %08x (prev %08x, RA %08x)\n", cpu->pc, cpu->op, cpu->prevpc, cpu->r[31] ); +// mips_stop(); +// mips_exception(cpu, EXC_RI ); + break; + } +//skipinterp: // unused label + cpu->mips_ICount--; + } while( cpu->mips_ICount > 0 ); + + return cycles - cpu->mips_ICount; +} + +#if 0 +static void mips_get_context( void *dst ) +{ + if( dst ) + { + *(mips_cpu_context *)dst = mipscpu; + } +} + +static void mips_set_context( void *src ) +{ + if( src ) + { + mipscpu = *(mips_cpu_context *)src; + change_pc( cpu->pc ); + } +} +#endif + +static void set_irq_line( mips_cpu_context *cpu, int irqline, int state ) +{ + UINT32 ip; + + switch( irqline ) + { + case MIPS_IRQ0: + ip = CAUSE_IP2; + break; + case MIPS_IRQ1: + ip = CAUSE_IP3; + break; + case MIPS_IRQ2: + ip = CAUSE_IP4; + break; + case MIPS_IRQ3: + ip = CAUSE_IP5; + break; + case MIPS_IRQ4: + ip = CAUSE_IP6; + break; + case MIPS_IRQ5: + ip = CAUSE_IP7; + break; + default: + return; + } + + switch( state ) + { + case CLEAR_LINE: + mips_set_cp0r(cpu, CP0_CAUSE, cpu->cp0r[ CP0_CAUSE ] & ~ip ); + break; + case ASSERT_LINE: + mips_set_cp0r(cpu, CP0_CAUSE, cpu->cp0r[ CP0_CAUSE ] |= ip ); + if( cpu->irq_callback ) + { + /* HOLD_LINE interrupts are not supported by the architecture. + By acknowledging the interupt here they are treated like PULSE_LINE + interrupts, so if the interrupt isn't enabled it will be ignored. + There is also a problem with PULSE_LINE interrupts as the interrupt + pending bits aren't latched the emulated code won't know what caused + the interrupt. */ + (*cpu->irq_callback)( cpu, irqline ); + } + break; + } +} + +/**************************************************************************** + * Return a formatted string for a register + ****************************************************************************/ + +offs_t mips_dasm( mips_cpu_context *cpu, char *buffer, offs_t pc ) +{ + offs_t ret; + change_pc( pc ); +#ifdef MAME_DEBUG + ret = DasmMIPS( buffer, pc ); +#else + sprintf( buffer, "$%08x", cpu_readop32( pc ) ); + ret = 4; +#endif + change_pc( cpu->pc ); + return ret; +} + +/* preliminary gte code */ + +#define VXY0 ( cpu->cp2dr[ 0 ].d ) +#define VX0 ( cpu->cp2dr[ 0 ].w.l ) +#define VY0 ( cpu->cp2dr[ 0 ].w.h ) +#define VZ0 ( cpu->cp2dr[ 1 ].w.l ) +#define VXY1 ( cpu->cp2dr[ 2 ].d ) +#define VX1 ( cpu->cp2dr[ 2 ].w.l ) +#define VY1 ( cpu->cp2dr[ 2 ].w.h ) +#define VZ1 ( cpu->cp2dr[ 3 ].w.l ) +#define VXY2 ( cpu->cp2dr[ 4 ].d ) +#define VX2 ( cpu->cp2dr[ 4 ].w.l ) +#define VY2 ( cpu->cp2dr[ 4 ].w.h ) +#define VZ2 ( cpu->cp2dr[ 5 ].w.l ) +#define RGB ( cpu->cp2dr[ 6 ].d ) +#define R ( cpu->cp2dr[ 6 ].b.l ) +#define G ( cpu->cp2dr[ 6 ].b.h ) +#define B ( cpu->cp2dr[ 6 ].b.h2 ) +#define CODE ( cpu->cp2dr[ 6 ].b.h3 ) +#define OTZ ( cpu->cp2dr[ 7 ].w.l ) +#define IR0 ( cpu->cp2dr[ 8 ].d ) +#define IR1 ( cpu->cp2dr[ 9 ].d ) +#define IR2 ( cpu->cp2dr[ 10 ].d ) +#define IR3 ( cpu->cp2dr[ 11 ].d ) +#define SXY0 ( cpu->cp2dr[ 12 ].d ) +#define SX0 ( cpu->cp2dr[ 12 ].w.l ) +#define SY0 ( cpu->cp2dr[ 12 ].w.h ) +#define SXY1 ( cpu->cp2dr[ 13 ].d ) +#define SX1 ( cpu->cp2dr[ 13 ].w.l ) +#define SY1 ( cpu->cp2dr[ 13 ].w.h ) +#define SXY2 ( cpu->cp2dr[ 14 ].d ) +#define SX2 ( cpu->cp2dr[ 14 ].w.l ) +#define SY2 ( cpu->cp2dr[ 14 ].w.h ) +#define SXYP ( cpu->cp2dr[ 15 ].d ) +#define SXP ( cpu->cp2dr[ 15 ].w.l ) +#define SYP ( cpu->cp2dr[ 15 ].w.h ) +#define SZ0 ( cpu->cp2dr[ 16 ].w.l ) +#define SZ1 ( cpu->cp2dr[ 17 ].w.l ) +#define SZ2 ( cpu->cp2dr[ 18 ].w.l ) +#define SZ3 ( cpu->cp2dr[ 19 ].w.l ) +#define RGB0 ( cpu->cp2dr[ 20 ].d ) +#define R0 ( cpu->cp2dr[ 20 ].b.l ) +#define G0 ( cpu->cp2dr[ 20 ].b.h ) +#define B0 ( cpu->cp2dr[ 20 ].b.h2 ) +#define CD0 ( cpu->cp2dr[ 20 ].b.h3 ) +#define RGB1 ( cpu->cp2dr[ 21 ].d ) +#define R1 ( cpu->cp2dr[ 21 ].b.l ) +#define G1 ( cpu->cp2dr[ 21 ].b.h ) +#define B1 ( cpu->cp2dr[ 21 ].b.h2 ) +#define CD1 ( cpu->cp2dr[ 21 ].b.h3 ) +#define RGB2 ( cpu->cp2dr[ 22 ].d ) +#define R2 ( cpu->cp2dr[ 22 ].b.l ) +#define G2 ( cpu->cp2dr[ 22 ].b.h ) +#define B2 ( cpu->cp2dr[ 22 ].b.h2 ) +#define CD2 ( cpu->cp2dr[ 22 ].b.h3 ) +#define RES1 ( cpu->cp2dr[ 23 ].d ) +#define MAC0 ( cpu->cp2dr[ 24 ].d ) +#define MAC1 ( cpu->cp2dr[ 25 ].d ) +#define MAC2 ( cpu->cp2dr[ 26 ].d ) +#define MAC3 ( cpu->cp2dr[ 27 ].d ) +#define IRGB ( cpu->cp2dr[ 28 ].d ) +#define ORGB ( cpu->cp2dr[ 29 ].d ) +#define LZCS ( cpu->cp2dr[ 30 ].d ) +#define LZCR ( cpu->cp2dr[ 31 ].d ) + +#define D1 ( cpu->cp2cr[ 0 ].d ) +#define R11 ( cpu->cp2cr[ 0 ].w.l ) +#define R12 ( cpu->cp2cr[ 0 ].w.h ) +#define R13 ( cpu->cp2cr[ 1 ].w.l ) +#define R21 ( cpu->cp2cr[ 1 ].w.h ) +#define D2 ( cpu->cp2cr[ 2 ].d ) +#define R22 ( cpu->cp2cr[ 2 ].w.l ) +#define R23 ( cpu->cp2cr[ 2 ].w.h ) +#define R31 ( cpu->cp2cr[ 3 ].w.l ) +#define R32 ( cpu->cp2cr[ 3 ].w.h ) +#define D3 ( cpu->cp2cr[ 4 ].d ) +#define R33 ( cpu->cp2cr[ 4 ].w.l ) +#define TRX ( cpu->cp2cr[ 5 ].d ) +#define TRY ( cpu->cp2cr[ 6 ].d ) +#define TRZ ( cpu->cp2cr[ 7 ].d ) +#define L11 ( cpu->cp2cr[ 8 ].w.l ) +#define L12 ( cpu->cp2cr[ 8 ].w.h ) +#define L13 ( cpu->cp2cr[ 9 ].w.l ) +#define L21 ( cpu->cp2cr[ 9 ].w.h ) +#define L22 ( cpu->cp2cr[ 10 ].w.l ) +#define L23 ( cpu->cp2cr[ 10 ].w.h ) +#define L31 ( cpu->cp2cr[ 11 ].w.l ) +#define L32 ( cpu->cp2cr[ 11 ].w.h ) +#define L33 ( cpu->cp2cr[ 12 ].w.l ) +#define RBK ( cpu->cp2cr[ 13 ].d ) +#define GBK ( cpu->cp2cr[ 14 ].d ) +#define BBK ( cpu->cp2cr[ 15 ].d ) +#define LR1 ( cpu->cp2cr[ 16 ].w.l ) +#define LR2 ( cpu->cp2cr[ 16 ].w.h ) +#define LR3 ( cpu->cp2cr[ 17 ].w.l ) +#define LG1 ( cpu->cp2cr[ 17 ].w.h ) +#define LG2 ( cpu->cp2cr[ 18 ].w.l ) +#define LG3 ( cpu->cp2cr[ 18 ].w.h ) +#define LB1 ( cpu->cp2cr[ 19 ].w.l ) +#define LB2 ( cpu->cp2cr[ 19 ].w.h ) +#define LB3 ( cpu->cp2cr[ 20 ].w.l ) +#define RFC ( cpu->cp2cr[ 21 ].d ) +#define GFC ( cpu->cp2cr[ 22 ].d ) +#define BFC ( cpu->cp2cr[ 23 ].d ) +#define OFX ( cpu->cp2cr[ 24 ].d ) +#define OFY ( cpu->cp2cr[ 25 ].d ) +#define H ( cpu->cp2cr[ 26 ].w.l ) +#define DQA ( cpu->cp2cr[ 27 ].w.l ) +#define DQB ( cpu->cp2cr[ 28 ].d ) +#define ZSF3 ( cpu->cp2cr[ 29 ].w.l ) +#define ZSF4 ( cpu->cp2cr[ 30 ].w.l ) +#define FLAG ( cpu->cp2cr[ 31 ].d ) + +static UINT32 getcp2dr(mips_cpu_context *cpu, int n_reg ) +{ + if( n_reg == 1 || n_reg == 3 || n_reg == 5 || n_reg == 8 || n_reg == 9 || n_reg == 10 || n_reg == 11 ) + { + cpu->cp2dr[ n_reg ].d = (INT32)(INT16)cpu->cp2dr[ n_reg ].d; + } + else if( n_reg == 17 || n_reg == 18 || n_reg == 19 ) + { + cpu->cp2dr[ n_reg ].d = (UINT32)(UINT16)cpu->cp2dr[ n_reg ].d; + } + else if( n_reg == 29 ) + { + ORGB = ( ( IR1 >> 7 ) & 0x1f ) | ( ( IR2 >> 2 ) & 0x3e0 ) | ( ( IR3 << 3 ) & 0x7c00 ); + } + GTELOG( "get CP2DR%u=%08x", n_reg, cpu->cp2dr[ n_reg ].d ); + return cpu->cp2dr[ n_reg ].d; +} + +static void setcp2dr(mips_cpu_context *cpu, int n_reg, UINT32 n_value ) +{ + GTELOG( "set CP2DR%u=%08x", n_reg, n_value ); + cpu->cp2dr[ n_reg ].d = n_value; + + if( n_reg == 15 ) + { + SXY0 = SXY1; + SXY1 = SXY2; + SXY2 = SXYP; + } + else if( n_reg == 28 ) + { + IR1 = ( IRGB & 0x1f ) << 4; + IR2 = ( IRGB & 0x3e0 ) >> 1; + IR3 = ( IRGB & 0x7c00 ) >> 6; + } + else if( n_reg == 30 ) + { + UINT32 n_lzcs = LZCS; + UINT32 n_lzcr = 0; + + if( ( n_lzcs & 0x80000000 ) == 0 ) + { + n_lzcs = ~n_lzcs; + } + while( ( n_lzcs & 0x80000000 ) != 0 ) + { + n_lzcr++; + n_lzcs <<= 1; + } + LZCR = n_lzcr; + } +} + +static UINT32 getcp2cr(mips_cpu_context *cpu, int n_reg ) +{ + GTELOG( "get CP2CR%u=%08x", n_reg, cpu->cp2cr[ n_reg ].d ); + return cpu->cp2cr[ n_reg ].d; +} + +static void setcp2cr(mips_cpu_context *cpu, int n_reg, UINT32 n_value ) +{ + GTELOG( "set CP2CR%u=%08x", n_reg, n_value ); + cpu->cp2cr[ n_reg ].d = n_value; +} + +INLINE INT32 LIM( mips_cpu_context *cpu, INT32 n_value, INT32 n_max, INT32 n_min, UINT32 n_flag ) +{ + if( n_value > n_max ) + { + FLAG |= n_flag; + return n_max; + } + else if( n_value < n_min ) + { + FLAG |= n_flag; + return n_min; + } + return n_value; +} + +INLINE INT64 BOUNDS( mips_cpu_context *cpu, INT64 n_value, INT64 n_max, int n_maxflag, INT64 n_min, int n_minflag ) +{ + if( n_value > n_max ) + { + FLAG |= n_maxflag; + } + else if( n_value < n_min ) + { + FLAG |= n_minflag; + } + return n_value; +} + +#define A1( a ) BOUNDS( cpu, ( a ), 0x7fffffff, 30, -(INT64)0x80000000, ( 1 << 27 ) ) +#define A2( a ) BOUNDS( cpu, ( a ), 0x7fffffff, 29, -(INT64)0x80000000, ( 1 << 26 ) ) +#define A3( a ) BOUNDS( cpu, ( a ), 0x7fffffff, 28, -(INT64)0x80000000, ( 1 << 25 ) ) +#define Lm_B1( a, l ) LIM( cpu, ( a ), 0x7fff, -0x8000 * !l, ( 1 << 31 ) | ( 1 << 24 ) ) +#define Lm_B2( a, l ) LIM( cpu, ( a ), 0x7fff, -0x8000 * !l, ( 1 << 31 ) | ( 1 << 23 ) ) +#define Lm_B3( a, l ) LIM( cpu, ( a ), 0x7fff, -0x8000 * !l, ( 1 << 22 ) ) +#define Lm_C1( a ) LIM( cpu, ( a ), 0x00ff, 0x0000, ( 1 << 21 ) ) +#define Lm_C2( a ) LIM( cpu, ( a ), 0x00ff, 0x0000, ( 1 << 20 ) ) +#define Lm_C3( a ) LIM( cpu, ( a ), 0x00ff, 0x0000, ( 1 << 19 ) ) +#define Lm_D( a ) LIM( cpu, ( a ), 0xffff, 0x0000, ( 1 << 31 ) | ( 1 << 18 ) ) + +INLINE UINT32 Lm_E( mips_cpu_context *cpu, UINT32 n_z ) +{ + if( n_z <= H / 2 ) + { + n_z = H / 2; + FLAG |= ( 1 << 31 ) | ( 1 << 17 ); + } + if( n_z == 0 ) + { + n_z = 1; + } + return n_z; +} + +#define F( a ) BOUNDS( cpu, ( a ), 0x7fffffff, ( 1 << 31 ) | ( 1 << 16 ), -(INT64)0x80000000, ( 1 << 31 ) | ( 1 << 15 ) ) +#define Lm_G1( a ) LIM( cpu, ( a ), 0x3ff, -0x400, ( 1 << 31 ) | ( 1 << 14 ) ) +#define Lm_G2( a ) LIM( cpu, ( a ), 0x3ff, -0x400, ( 1 << 31 ) | ( 1 << 13 ) ) +#define Lm_H( a ) LIM( cpu, ( a ), 0xfff, 0x000, ( 1 << 12 ) ) + +static void docop2(mips_cpu_context *cpu, int gteop ) +{ + int n_sf; + int n_v; + int n_lm; + int n_pass; + UINT16 n_v1; + UINT16 n_v2; + UINT16 n_v3; + UINT16 **p_n_mx; + UINT32 **p_n_cv; + UINT16 n_zm = 0; + UINT32 n_zc = 0; + UINT16 *p_n_vx[] = { &VX0, &VX1, &VX2 }; + UINT16 *p_n_vy[] = { &VY0, &VY1, &VY2 }; + UINT16 *p_n_vz[] = { &VZ0, &VZ1, &VZ2 }; + UINT16 *p_n_rm[] = { &R11, &R12, &R13, &R21, &R22, &R23, &R31, &R32, &R33 }; + UINT16 *p_n_lm[] = { &L11, &L12, &L13, &L21, &L22, &L23, &L31, &L32, &L33 }; + UINT16 *p_n_cm[] = { &LR1, &LR2, &LR3, &LG1, &LG2, &LG3, &LB1, &LB2, &LB3 }; + UINT16 *p_n_zm[] = { &n_zm, &n_zm, &n_zm, &n_zm, &n_zm, &n_zm, &n_zm, &n_zm, &n_zm }; + UINT16 **p_p_n_mx[] = { p_n_rm, p_n_lm, p_n_cm, p_n_zm }; + UINT32 *p_n_tr[] = { &TRX, &TRY, &TRZ }; + UINT32 *p_n_bk[] = { &RBK, &GBK, &BBK }; + UINT32 *p_n_fc[] = { &RFC, &GFC, &BFC }; + UINT32 *p_n_zc[] = { &n_zc, &n_zc, &n_zc }; + UINT32 **p_p_n_cv[] = { p_n_tr, p_n_bk, p_n_fc, p_n_zc }; + + switch( GTE_FUNCT( gteop ) ) + { + case 0x01: + if( gteop == 0x0180001 ) + { + GTELOG( "RTPS" ); + FLAG = 0; + + MAC1 = A1( ( ( (INT64)(INT32)TRX << 12 ) + ( (INT16)R11 * (INT16)VX0 ) + ( (INT16)R12 * (INT16)VY0 ) + ( (INT16)R13 * (INT16)VZ0 ) ) >> 12 ); + MAC2 = A2( ( ( (INT64)(INT32)TRY << 12 ) + ( (INT16)R21 * (INT16)VX0 ) + ( (INT16)R22 * (INT16)VY0 ) + ( (INT16)R23 * (INT16)VZ0 ) ) >> 12 ); + MAC3 = A3( ( ( (INT64)(INT32)TRZ << 12 ) + ( (INT16)R31 * (INT16)VX0 ) + ( (INT16)R32 * (INT16)VY0 ) + ( (INT16)R33 * (INT16)VZ0 ) ) >> 12 ); + IR1 = Lm_B1( (INT32)MAC1, 0 ); + IR2 = Lm_B2( (INT32)MAC2, 0 ); + IR3 = Lm_B3( (INT32)MAC3, 0 ); + SZ0 = SZ1; + SZ1 = SZ2; + SZ2 = SZ3; + SZ3 = Lm_D( (INT32)MAC3 ); + SXY0 = SXY1; + SXY1 = SXY2; + SX2 = Lm_G1( F( (INT64)(INT32)OFX + ( (INT64)(INT16)IR1 * ( ( (UINT32)H << 16 ) / Lm_E( cpu, SZ3 ) ) ) ) >> 16 ); + SY2 = Lm_G2( F( (INT64)(INT32)OFY + ( (INT64)(INT16)IR2 * ( ( (UINT32)H << 16 ) / Lm_E( cpu, SZ3 ) ) ) ) >> 16 ); + MAC0 = F( (INT64)(INT32)DQB + ( (INT64)(INT16)DQA * ( ( (UINT32)H << 16 ) / Lm_E( cpu, SZ3 ) ) ) ); + IR0 = Lm_H( (INT32)MAC0 >> 12 ); + return; + } + break; + case 0x06: + if( gteop == 0x0400006 || + gteop == 0x1400006 || + gteop == 0x0155cc6 ) + { + GTELOG( "NCLIP" ); + FLAG = 0; + + MAC0 = F( ( (INT64)(INT16)SX0 * (INT16)SY1 ) + ( (INT16)SX1 * (INT16)SY2 ) + ( (INT16)SX2 * (INT16)SY0 ) - ( (INT16)SX0 * (INT16)SY2 ) - ( (INT16)SX1 * (INT16)SY0 ) - ( (INT16)SX2 * (INT16)SY1 ) ); + return; + } + break; + case 0x0c: + if( GTE_OP( gteop ) == 0x17 ) + { + GTELOG( "OP" ); + n_sf = 12 * GTE_SF( gteop ); + FLAG = 0; + + MAC1 = A1( ( ( (INT64)(INT32)D2 * (INT16)IR3 ) - ( (INT64)(INT32)D3 * (INT16)IR2 ) ) >> n_sf ); + MAC2 = A2( ( ( (INT64)(INT32)D3 * (INT16)IR1 ) - ( (INT64)(INT32)D1 * (INT16)IR3 ) ) >> n_sf ); + MAC3 = A3( ( ( (INT64)(INT32)D1 * (INT16)IR2 ) - ( (INT64)(INT32)D2 * (INT16)IR1 ) ) >> n_sf ); + IR1 = Lm_B1( (INT32)MAC1, 0 ); + IR2 = Lm_B2( (INT32)MAC2, 0 ); + IR3 = Lm_B3( (INT32)MAC3, 0 ); + return; + } + break; + case 0x10: + if( gteop == 0x0780010 ) + { + GTELOG( "DPCS" ); + FLAG = 0; + + MAC1 = A1( ( ( (INT64)R << 16 ) + ( (INT64)(INT16)IR0 * ( Lm_B1( (INT32)RFC - ( R << 4 ), 0 ) ) ) ) >> 12 ); + MAC2 = A2( ( ( (INT64)G << 16 ) + ( (INT64)(INT16)IR0 * ( Lm_B1( (INT32)GFC - ( G << 4 ), 0 ) ) ) ) >> 12 ); + MAC3 = A3( ( ( (INT64)B << 16 ) + ( (INT64)(INT16)IR0 * ( Lm_B1( (INT32)BFC - ( B << 4 ), 0 ) ) ) ) >> 12 ); + IR1 = Lm_B1( (INT32)MAC1, 0 ); + IR2 = Lm_B2( (INT32)MAC2, 0 ); + IR3 = Lm_B3( (INT32)MAC3, 0 ); + CD0 = CD1; + CD1 = CD2; + CD2 = CODE; + R0 = R1; + R1 = R2; + R2 = Lm_C1( (INT32)MAC1 >> 4 ); + G0 = G1; + G1 = G2; + G2 = Lm_C2( (INT32)MAC2 >> 4 ); + B0 = B1; + B1 = B2; + B2 = Lm_C3( (INT32)MAC3 >> 4 ); + return; + } + break; + case 0x11: + if( gteop == 0x0980011 ) + { + GTELOG( "INTPL" ); + FLAG = 0; + + MAC1 = A1( ( ( (INT64)(INT16)IR1 << 12 ) + ( (INT64)(INT16)IR0 * ( Lm_B1( (INT32)RFC - (INT16)IR1, 0 ) ) ) ) >> 12 ); + MAC2 = A2( ( ( (INT64)(INT16)IR2 << 12 ) + ( (INT64)(INT16)IR0 * ( Lm_B1( (INT32)GFC - (INT16)IR2, 0 ) ) ) ) >> 12 ); + MAC3 = A3( ( ( (INT64)(INT16)IR3 << 12 ) + ( (INT64)(INT16)IR0 * ( Lm_B1( (INT32)BFC - (INT16)IR3, 0 ) ) ) ) >> 12 ); + IR1 = Lm_B1( (INT32)MAC1, 0 ); + IR2 = Lm_B2( (INT32)MAC2, 0 ); + IR3 = Lm_B3( (INT32)MAC3, 0 ); + CD0 = CD1; + CD1 = CD2; + CD2 = CODE; + R0 = R1; + R1 = R2; + R2 = Lm_C1( (INT32)MAC1 ); + G0 = G1; + G1 = G2; + G2 = Lm_C2( (INT32)MAC2 ); + B0 = B1; + B1 = B2; + B2 = Lm_C3( (INT32)MAC3 ); + return; + } + break; + case 0x12: + if( GTE_OP( gteop ) == 0x04 ) + { + GTELOG( "MVMVA" ); + n_sf = 12 * GTE_SF( gteop ); + p_n_mx = p_p_n_mx[ GTE_MX( gteop ) ]; + n_v = GTE_V( gteop ); + if( n_v < 3 ) + { + n_v1 = *p_n_vx[ n_v ]; + n_v2 = *p_n_vy[ n_v ]; + n_v3 = *p_n_vz[ n_v ]; + } + else + { + n_v1 = IR1; + n_v2 = IR2; + n_v3 = IR3; + } + p_n_cv = p_p_n_cv[ GTE_CV( gteop ) ]; + n_lm = GTE_LM( gteop ); + FLAG = 0; + + MAC1 = A1( ( ( (INT64)(INT32)*p_n_cv[ 0 ] << 12 ) + ( (INT16)*p_n_mx[ 0 ] * (INT16)n_v1 ) + ( (INT16)*p_n_mx[ 1 ] * (INT16)n_v2 ) + ( (INT16)*p_n_mx[ 2 ] * (INT16)n_v3 ) ) >> n_sf ); + MAC2 = A2( ( ( (INT64)(INT32)*p_n_cv[ 1 ] << 12 ) + ( (INT16)*p_n_mx[ 3 ] * (INT16)n_v1 ) + ( (INT16)*p_n_mx[ 4 ] * (INT16)n_v2 ) + ( (INT16)*p_n_mx[ 5 ] * (INT16)n_v3 ) ) >> n_sf ); + MAC3 = A3( ( ( (INT64)(INT32)*p_n_cv[ 2 ] << 12 ) + ( (INT16)*p_n_mx[ 6 ] * (INT16)n_v1 ) + ( (INT16)*p_n_mx[ 7 ] * (INT16)n_v2 ) + ( (INT16)*p_n_mx[ 8 ] * (INT16)n_v3 ) ) >> n_sf ); + + IR1 = Lm_B1( (INT32)MAC1, n_lm ); + IR2 = Lm_B2( (INT32)MAC2, n_lm ); + IR3 = Lm_B3( (INT32)MAC3, n_lm ); + return; + } + break; + case 0x13: + if( gteop == 0x0e80413 ) + { + GTELOG( "NCDS" ); + FLAG = 0; + + MAC1 = A1( ( ( (INT64)(INT16)L11 * (INT16)VX0 ) + ( (INT16)L12 * (INT16)VY0 ) + ( (INT16)L13 * (INT16)VZ0 ) ) >> 12 ); + MAC2 = A2( ( ( (INT64)(INT16)L21 * (INT16)VX0 ) + ( (INT16)L22 * (INT16)VY0 ) + ( (INT16)L23 * (INT16)VZ0 ) ) >> 12 ); + MAC3 = A3( ( ( (INT64)(INT16)L31 * (INT16)VX0 ) + ( (INT16)L32 * (INT16)VY0 ) + ( (INT16)L33 * (INT16)VZ0 ) ) >> 12 ); + IR1 = Lm_B1( (INT32)MAC1, 1 ); + IR2 = Lm_B2( (INT32)MAC2, 1 ); + IR3 = Lm_B3( (INT32)MAC3, 1 ); + MAC1 = A1( ( ( (INT64)RBK << 12 ) + ( (INT16)LR1 * (INT16)IR1 ) + ( (INT16)LR2 * (INT16)IR2 ) + ( (INT16)LR3 * (INT16)IR3 ) ) >> 12 ); + MAC2 = A2( ( ( (INT64)GBK << 12 ) + ( (INT16)LG1 * (INT16)IR1 ) + ( (INT16)LG2 * (INT16)IR2 ) + ( (INT16)LG3 * (INT16)IR3 ) ) >> 12 ); + MAC3 = A3( ( ( (INT64)BBK << 12 ) + ( (INT16)LB1 * (INT16)IR1 ) + ( (INT16)LB2 * (INT16)IR2 ) + ( (INT16)LB3 * (INT16)IR3 ) ) >> 12 ); + IR1 = Lm_B1( (INT32)MAC1, 1 ); + IR2 = Lm_B2( (INT32)MAC2, 1 ); + IR3 = Lm_B3( (INT32)MAC3, 1 ); + MAC1 = A1( ( ( ( (INT64)R << 4 ) * (INT16)IR1 ) + ( (INT16)IR0 * Lm_B1( (INT32)RFC - ( ( R * (INT16)IR1 ) >> 8 ), 0 ) ) ) >> 12 ); + MAC2 = A2( ( ( ( (INT64)G << 4 ) * (INT16)IR2 ) + ( (INT16)IR0 * Lm_B2( (INT32)GFC - ( ( G * (INT16)IR2 ) >> 8 ), 0 ) ) ) >> 12 ); + MAC3 = A3( ( ( ( (INT64)B << 4 ) * (INT16)IR3 ) + ( (INT16)IR0 * Lm_B3( (INT32)BFC - ( ( B * (INT16)IR3 ) >> 8 ), 0 ) ) ) >> 12 ); + IR1 = Lm_B1( (INT32)MAC1, 1 ); + IR2 = Lm_B2( (INT32)MAC2, 1 ); + IR3 = Lm_B3( (INT32)MAC3, 1 ); + CD0 = CD1; + CD1 = CD2; + CD2 = CODE; + R0 = R1; + R1 = R2; + R2 = Lm_C1( (INT32)MAC1 >> 4 ); + G0 = G1; + G1 = G2; + G2 = Lm_C2( (INT32)MAC2 >> 4 ); + B0 = B1; + B1 = B2; + B2 = Lm_C3( (INT32)MAC3 >> 4 ); + return; + } + break; + case 0x14: + if( gteop == 0x1280414 ) + { + GTELOG( "CDP" ); + FLAG = 0; + + MAC1 = A1( ( ( (INT64)RBK << 12 ) + ( (INT16)LR1 * (INT16)IR1 ) + ( (INT16)LR2 * (INT16)IR2 ) + ( (INT16)LR3 * (INT16)IR3 ) ) >> 12 ); + MAC2 = A2( ( ( (INT64)GBK << 12 ) + ( (INT16)LG1 * (INT16)IR1 ) + ( (INT16)LG2 * (INT16)IR2 ) + ( (INT16)LG3 * (INT16)IR3 ) ) >> 12 ); + MAC3 = A3( ( ( (INT64)BBK << 12 ) + ( (INT16)LB1 * (INT16)IR1 ) + ( (INT16)LB2 * (INT16)IR2 ) + ( (INT16)LB3 * (INT16)IR3 ) ) >> 12 ); + IR1 = Lm_B1( MAC1, 1 ); + IR2 = Lm_B2( MAC2, 1 ); + IR3 = Lm_B3( MAC3, 1 ); + MAC1 = A1( ( ( ( (INT64)R << 4 ) * (INT16)IR1 ) + ( (INT16)IR0 * Lm_B1( (INT32)RFC - ( ( R * (INT16)IR1 ) >> 8 ), 0 ) ) ) >> 12 ); + MAC2 = A2( ( ( ( (INT64)G << 4 ) * (INT16)IR2 ) + ( (INT16)IR0 * Lm_B2( (INT32)GFC - ( ( G * (INT16)IR2 ) >> 8 ), 0 ) ) ) >> 12 ); + MAC3 = A3( ( ( ( (INT64)B << 4 ) * (INT16)IR3 ) + ( (INT16)IR0 * Lm_B3( (INT32)BFC - ( ( B * (INT16)IR3 ) >> 8 ), 0 ) ) ) >> 12 ); + IR1 = Lm_B1( MAC1, 1 ); + IR2 = Lm_B2( MAC2, 1 ); + IR3 = Lm_B3( MAC3, 1 ); + CD0 = CD1; + CD1 = CD2; + CD2 = CODE; + R0 = R1; + R1 = R2; + R2 = Lm_C1( (INT32)MAC1 >> 4 ); + G0 = G1; + G1 = G2; + G2 = Lm_C2( (INT32)MAC2 >> 4 ); + B0 = B1; + B1 = B2; + B2 = Lm_C3( (INT32)MAC3 >> 4 ); + return; + } + break; + case 0x16: + if( gteop == 0x0f80416 ) + { + GTELOG( "NCDT" ); + FLAG = 0; + + for( n_v = 0; n_v < 3; n_v++ ) + { + MAC1 = A1( ( ( (INT64)(INT16)L11 * (INT16)*p_n_vx[ n_v ] ) + ( (INT16)L12 * (INT16)*p_n_vy[ n_v ] ) + ( (INT16)L13 * (INT16)*p_n_vz[ n_v ] ) ) >> 12 ); + MAC2 = A2( ( ( (INT64)(INT16)L21 * (INT16)*p_n_vx[ n_v ] ) + ( (INT16)L22 * (INT16)*p_n_vy[ n_v ] ) + ( (INT16)L23 * (INT16)*p_n_vz[ n_v ] ) ) >> 12 ); + MAC3 = A3( ( ( (INT64)(INT16)L31 * (INT16)*p_n_vx[ n_v ] ) + ( (INT16)L32 * (INT16)*p_n_vy[ n_v ] ) + ( (INT16)L33 * (INT16)*p_n_vz[ n_v ] ) ) >> 12 ); + IR1 = Lm_B1( (INT32)MAC1, 1 ); + IR2 = Lm_B2( (INT32)MAC2, 1 ); + IR3 = Lm_B3( (INT32)MAC3, 1 ); + MAC1 = A1( ( ( (INT64)RBK << 12 ) + ( (INT16)LR1 * (INT16)IR1 ) + ( (INT16)LR2 * (INT16)IR2 ) + ( (INT16)LR3 * (INT16)IR3 ) ) >> 12 ); + MAC2 = A2( ( ( (INT64)GBK << 12 ) + ( (INT16)LG1 * (INT16)IR1 ) + ( (INT16)LG2 * (INT16)IR2 ) + ( (INT16)LG3 * (INT16)IR3 ) ) >> 12 ); + MAC3 = A3( ( ( (INT64)BBK << 12 ) + ( (INT16)LB1 * (INT16)IR1 ) + ( (INT16)LB2 * (INT16)IR2 ) + ( (INT16)LB3 * (INT16)IR3 ) ) >> 12 ); + IR1 = Lm_B1( (INT32)MAC1, 1 ); + IR2 = Lm_B2( (INT32)MAC2, 1 ); + IR3 = Lm_B3( (INT32)MAC3, 1 ); + MAC1 = A1( ( ( ( (INT64)R << 4 ) * (INT16)IR1 ) + ( (INT16)IR0 * Lm_B1( (INT32)RFC - ( ( R * (INT16)IR1 ) >> 8 ), 0 ) ) ) >> 12 ); + MAC2 = A2( ( ( ( (INT64)G << 4 ) * (INT16)IR2 ) + ( (INT16)IR0 * Lm_B2( (INT32)GFC - ( ( G * (INT16)IR2 ) >> 8 ), 0 ) ) ) >> 12 ); + MAC3 = A3( ( ( ( (INT64)B << 4 ) * (INT16)IR3 ) + ( (INT16)IR0 * Lm_B3( (INT32)BFC - ( ( B * (INT16)IR3 ) >> 8 ), 0 ) ) ) >> 12 ); + IR1 = Lm_B1( (INT32)MAC1, 1 ); + IR2 = Lm_B2( (INT32)MAC2, 1 ); + IR3 = Lm_B3( (INT32)MAC3, 1 ); + CD0 = CD1; + CD1 = CD2; + CD2 = CODE; + R0 = R1; + R1 = R2; + R2 = Lm_C1( (INT32)MAC1 >> 4 ); + G0 = G1; + G1 = G2; + G2 = Lm_C2( (INT32)MAC2 >> 4 ); + B0 = B1; + B1 = B2; + B2 = Lm_C3( (INT32)MAC3 >> 4 ); + } + return; + } + break; + case 0x1b: + if( gteop == 0x108041b ) + { + GTELOG( "NCCS" ); + FLAG = 0; + + MAC1 = A1( ( ( (INT64)(INT16)L11 * (INT16)VX0 ) + ( (INT16)L12 * (INT16)VY0 ) + ( (INT16)L13 * (INT16)VZ0 ) ) >> 12 ); + MAC2 = A2( ( ( (INT64)(INT16)L21 * (INT16)VX0 ) + ( (INT16)L22 * (INT16)VY0 ) + ( (INT16)L23 * (INT16)VZ0 ) ) >> 12 ); + MAC3 = A3( ( ( (INT64)(INT16)L31 * (INT16)VX0 ) + ( (INT16)L32 * (INT16)VY0 ) + ( (INT16)L33 * (INT16)VZ0 ) ) >> 12 ); + IR1 = Lm_B1( (INT32)MAC1, 1 ); + IR2 = Lm_B2( (INT32)MAC2, 1 ); + IR3 = Lm_B3( (INT32)MAC3, 1 ); + MAC1 = A1( ( ( (INT64)RBK << 12 ) + ( (INT16)LR1 * (INT16)IR1 ) + ( (INT16)LR2 * (INT16)IR2 ) + ( (INT16)LR3 * (INT16)IR3 ) ) >> 12 ); + MAC2 = A2( ( ( (INT64)GBK << 12 ) + ( (INT16)LG1 * (INT16)IR1 ) + ( (INT16)LG2 * (INT16)IR2 ) + ( (INT16)LG3 * (INT16)IR3 ) ) >> 12 ); + MAC3 = A3( ( ( (INT64)BBK << 12 ) + ( (INT16)LB1 * (INT16)IR1 ) + ( (INT16)LB2 * (INT16)IR2 ) + ( (INT16)LB3 * (INT16)IR3 ) ) >> 12 ); + IR1 = Lm_B1( (INT32)MAC1, 1 ); + IR2 = Lm_B2( (INT32)MAC2, 1 ); + IR3 = Lm_B3( (INT32)MAC3, 1 ); + MAC1 = A1( ( (INT64)R * (INT16)IR1 ) >> 8 ); + MAC2 = A2( ( (INT64)G * (INT16)IR2 ) >> 8 ); + MAC3 = A3( ( (INT64)B * (INT16)IR3 ) >> 8 ); + IR1 = Lm_B1( (INT32)MAC1, 1 ); + IR2 = Lm_B2( (INT32)MAC2, 1 ); + IR3 = Lm_B3( (INT32)MAC3, 1 ); + CD0 = CD1; + CD1 = CD2; + CD2 = CODE; + R0 = R1; + R1 = R2; + R2 = Lm_C1( (INT32)MAC1 >> 4 ); + G0 = G1; + G1 = G2; + G2 = Lm_C2( (INT32)MAC2 >> 4 ); + B0 = B1; + B1 = B2; + B2 = Lm_C3( (INT32)MAC3 >> 4 ); + return; + } + break; + case 0x1c: + if( gteop == 0x138041c ) + { + GTELOG( "CC" ); + FLAG = 0; + + MAC1 = A1( ( ( (INT64)RBK << 12 ) + ( (INT16)LR1 * (INT16)IR1 ) + ( (INT16)LR2 * (INT16)IR2 ) + ( (INT16)LR3 * (INT16)IR3 ) ) >> 12 ); + MAC2 = A2( ( ( (INT64)GBK << 12 ) + ( (INT16)LG1 * (INT16)IR1 ) + ( (INT16)LG2 * (INT16)IR2 ) + ( (INT16)LG3 * (INT16)IR3 ) ) >> 12 ); + MAC3 = A3( ( ( (INT64)BBK << 12 ) + ( (INT16)LB1 * (INT16)IR1 ) + ( (INT16)LB2 * (INT16)IR2 ) + ( (INT16)LB3 * (INT16)IR3 ) ) >> 12 ); + IR1 = Lm_B1( MAC1, 1 ); + IR2 = Lm_B2( MAC2, 1 ); + IR3 = Lm_B3( MAC3, 1 ); + MAC1 = A1( ( (INT64)R * (INT16)IR1 ) >> 8 ); + MAC2 = A2( ( (INT64)G * (INT16)IR2 ) >> 8 ); + MAC3 = A3( ( (INT64)B * (INT16)IR3 ) >> 8 ); + IR1 = Lm_B1( MAC1, 1 ); + IR2 = Lm_B2( MAC2, 1 ); + IR3 = Lm_B3( MAC3, 1 ); + CD0 = CD1; + CD1 = CD2; + CD2 = CODE; + R0 = R1; + R1 = R2; + R2 = Lm_C1( (INT32)MAC1 >> 4 ); + G0 = G1; + G1 = G2; + G2 = Lm_C2( (INT32)MAC2 >> 4 ); + B0 = B1; + B1 = B2; + B2 = Lm_C3( (INT32)MAC3 >> 4 ); + return; + } + break; + case 0x1e: + if( gteop == 0x0c8041e ) + { + GTELOG( "NCS" ); + FLAG = 0; + + MAC1 = A1( ( ( (INT64)(INT16)L11 * (INT16)VX0 ) + ( (INT16)L12 * (INT16)VY0 ) + ( (INT16)L13 * (INT16)VZ0 ) ) >> 12 ); + MAC2 = A2( ( ( (INT64)(INT16)L21 * (INT16)VX0 ) + ( (INT16)L22 * (INT16)VY0 ) + ( (INT16)L23 * (INT16)VZ0 ) ) >> 12 ); + MAC3 = A3( ( ( (INT64)(INT16)L31 * (INT16)VX0 ) + ( (INT16)L32 * (INT16)VY0 ) + ( (INT16)L33 * (INT16)VZ0 ) ) >> 12 ); + IR1 = Lm_B1( (INT32)MAC1, 1 ); + IR2 = Lm_B2( (INT32)MAC2, 1 ); + IR3 = Lm_B3( (INT32)MAC3, 1 ); + MAC1 = A1( ( ( (INT64)RBK << 12 ) + ( (INT16)LR1 * (INT16)IR1 ) + ( (INT16)LR2 * (INT16)IR2 ) + ( (INT16)LR3 * (INT16)IR3 ) ) >> 12 ); + MAC2 = A2( ( ( (INT64)GBK << 12 ) + ( (INT16)LG1 * (INT16)IR1 ) + ( (INT16)LG2 * (INT16)IR2 ) + ( (INT16)LG3 * (INT16)IR3 ) ) >> 12 ); + MAC3 = A3( ( ( (INT64)BBK << 12 ) + ( (INT16)LB1 * (INT16)IR1 ) + ( (INT16)LB2 * (INT16)IR2 ) + ( (INT16)LB3 * (INT16)IR3 ) ) >> 12 ); + IR1 = Lm_B1( (INT32)MAC1, 1 ); + IR2 = Lm_B2( (INT32)MAC2, 1 ); + IR3 = Lm_B3( (INT32)MAC3, 1 ); + CD0 = CD1; + CD1 = CD2; + CD2 = CODE; + R0 = R1; + R1 = R2; + R2 = Lm_C1( (INT32)MAC1 >> 4 ); + G0 = G1; + G1 = G2; + G2 = Lm_C2( (INT32)MAC2 >> 4 ); + B0 = B1; + B1 = B2; + B2 = Lm_C3( (INT32)MAC3 >> 4 ); + return; + } + break; + case 0x20: + if( gteop == 0x0d80420 ) + { + GTELOG( "NCT" ); + FLAG = 0; + + for( n_v = 0; n_v < 3; n_v++ ) + { + MAC1 = A1( ( ( (INT64)(INT16)L11 * (INT16)*p_n_vx[ n_v ] ) + ( (INT16)L12 * (INT16)*p_n_vy[ n_v ] ) + ( (INT16)L13 * (INT16)*p_n_vz[ n_v ] ) ) >> 12 ); + MAC2 = A2( ( ( (INT64)(INT16)L21 * (INT16)*p_n_vx[ n_v ] ) + ( (INT16)L22 * (INT16)*p_n_vy[ n_v ] ) + ( (INT16)L23 * (INT16)*p_n_vz[ n_v ] ) ) >> 12 ); + MAC3 = A3( ( ( (INT64)(INT16)L31 * (INT16)*p_n_vx[ n_v ] ) + ( (INT16)L32 * (INT16)*p_n_vy[ n_v ] ) + ( (INT16)L33 * (INT16)*p_n_vz[ n_v ] ) ) >> 12 ); + IR1 = Lm_B1( (INT32)MAC1, 1 ); + IR2 = Lm_B2( (INT32)MAC2, 1 ); + IR3 = Lm_B3( (INT32)MAC3, 1 ); + MAC1 = A1( ( ( (INT64)RBK << 12 ) + ( (INT16)LR1 * (INT16)IR1 ) + ( (INT16)LR2 * (INT16)IR2 ) + ( (INT16)LR3 * (INT16)IR3 ) ) >> 12 ); + MAC2 = A2( ( ( (INT64)GBK << 12 ) + ( (INT16)LG1 * (INT16)IR1 ) + ( (INT16)LG2 * (INT16)IR2 ) + ( (INT16)LG3 * (INT16)IR3 ) ) >> 12 ); + MAC3 = A3( ( ( (INT64)BBK << 12 ) + ( (INT16)LB1 * (INT16)IR1 ) + ( (INT16)LB2 * (INT16)IR2 ) + ( (INT16)LB3 * (INT16)IR3 ) ) >> 12 ); + IR1 = Lm_B1( (INT32)MAC1, 1 ); + IR2 = Lm_B2( (INT32)MAC2, 1 ); + IR3 = Lm_B3( (INT32)MAC3, 1 ); + CD0 = CD1; + CD1 = CD2; + CD2 = CODE; + R0 = R1; + R1 = R2; + R2 = Lm_C1( (INT32)MAC1 >> 4 ); + G0 = G1; + G1 = G2; + G2 = Lm_C2( (INT32)MAC2 >> 4 ); + B0 = B1; + B1 = B2; + B2 = Lm_C3( (INT32)MAC3 >> 4 ); + } + return; + } + break; + case 0x28: + if( GTE_OP( gteop ) == 0x0a && GTE_LM( gteop ) == 1 ) + { + GTELOG( "SQR" ); + n_sf = 12 * GTE_SF( gteop ); + FLAG = 0; + + MAC1 = A1( ( (INT64)(INT16)IR1 * (INT16)IR1 ) >> n_sf ); + MAC2 = A2( ( (INT64)(INT16)IR2 * (INT16)IR2 ) >> n_sf ); + MAC3 = A3( ( (INT64)(INT16)IR3 * (INT16)IR3 ) >> n_sf ); + IR1 = Lm_B1( MAC1, 1 ); + IR2 = Lm_B2( MAC2, 1 ); + IR3 = Lm_B3( MAC3, 1 ); + return; + } + break; + // DCPL 0x29 + case 0x2a: + if( gteop == 0x0f8002a ) + { + GTELOG( "DPCT" ); + FLAG = 0; + + for( n_pass = 0; n_pass < 3; n_pass++ ) + { + MAC1 = A1( ( ( (INT64)R0 << 16 ) + ( (INT64)(INT16)IR0 * ( Lm_B1( (INT32)RFC - ( R0 << 4 ), 0 ) ) ) ) >> 12 ); + MAC2 = A2( ( ( (INT64)G0 << 16 ) + ( (INT64)(INT16)IR0 * ( Lm_B1( (INT32)GFC - ( G0 << 4 ), 0 ) ) ) ) >> 12 ); + MAC3 = A3( ( ( (INT64)B0 << 16 ) + ( (INT64)(INT16)IR0 * ( Lm_B1( (INT32)BFC - ( B0 << 4 ), 0 ) ) ) ) >> 12 ); + IR1 = Lm_B1( (INT32)MAC1, 0 ); + IR2 = Lm_B2( (INT32)MAC2, 0 ); + IR3 = Lm_B3( (INT32)MAC3, 0 ); + CD0 = CD1; + CD1 = CD2; + CD2 = CODE; + R0 = R1; + R1 = R2; + R2 = Lm_C1( (INT32)MAC1 >> 4 ); + G0 = G1; + G1 = G2; + G2 = Lm_C2( (INT32)MAC2 >> 4 ); + B0 = B1; + B1 = B2; + B2 = Lm_C3( (INT32)MAC3 >> 4 ); + } + return; + } + break; + case 0x2d: + if( gteop == 0x158002d ) + { + GTELOG( "AVSZ3" ); + FLAG = 0; + + MAC0 = F( ( (INT64)(INT16)ZSF3 * SZ1 ) + ( (INT16)ZSF3 * SZ2 ) + ( (INT16)ZSF3 * SZ3 ) ); + OTZ = Lm_D( (INT32)MAC0 >> 12 ); + return; + } + break; + case 0x2e: + if( gteop == 0x168002e ) + { + GTELOG( "AVSZ4" ); + FLAG = 0; + + MAC0 = F( ( (INT64)(INT16)ZSF4 * SZ0 ) + ( (INT16)ZSF4 * SZ1 ) + ( (INT16)ZSF4 * SZ2 ) + ( (INT16)ZSF4 * SZ3 ) ); + OTZ = Lm_D( (INT32)MAC0 >> 12 ); + return; + } + break; + case 0x30: + if( gteop == 0x0280030 ) + { + GTELOG( "RTPT" ); + FLAG = 0; + + for( n_v = 0; n_v < 3; n_v++ ) + { + MAC1 = A1( ( ( (INT64)(INT32)TRX << 12 ) + ( (INT16)R11 * (INT16)*p_n_vx[ n_v ] ) + ( (INT16)R12 * (INT16)*p_n_vy[ n_v ] ) + ( (INT16)R13 * (INT16)*p_n_vz[ n_v ] ) ) >> 12 ); + MAC2 = A2( ( ( (INT64)(INT32)TRY << 12 ) + ( (INT16)R21 * (INT16)*p_n_vx[ n_v ] ) + ( (INT16)R22 * (INT16)*p_n_vy[ n_v ] ) + ( (INT16)R23 * (INT16)*p_n_vz[ n_v ] ) ) >> 12 ); + MAC3 = A3( ( ( (INT64)(INT32)TRZ << 12 ) + ( (INT16)R31 * (INT16)*p_n_vx[ n_v ] ) + ( (INT16)R32 * (INT16)*p_n_vy[ n_v ] ) + ( (INT16)R33 * (INT16)*p_n_vz[ n_v ] ) ) >> 12 ); + IR1 = Lm_B1( (INT32)MAC1, 0 ); + IR2 = Lm_B2( (INT32)MAC2, 0 ); + IR3 = Lm_B3( (INT32)MAC3, 0 ); + SZ0 = SZ1; + SZ1 = SZ2; + SZ2 = SZ3; + SZ3 = Lm_D( (INT32)MAC3 ); + SXY0 = SXY1; + SXY1 = SXY2; + SX2 = Lm_G1( F( ( (INT64)(INT32)OFX + ( (INT64)(INT16)IR1 * ( ( (UINT32)H << 16 ) / Lm_E( cpu, SZ3 ) ) ) ) >> 16 ) ); + SY2 = Lm_G2( F( ( (INT64)(INT32)OFY + ( (INT64)(INT16)IR2 * ( ( (UINT32)H << 16 ) / Lm_E( cpu, SZ3 ) ) ) ) >> 16 ) ); + MAC0 = F( (INT64)(INT32)DQB + ( (INT64)(INT16)DQA * ( ( (UINT32)H << 16 ) / Lm_E( cpu, SZ3 ) ) ) ); + IR0 = Lm_H( (INT32)MAC0 >> 12 ); + } + return; + } + break; + case 0x3d: + if( GTE_OP( gteop ) == 0x09 || + GTE_OP( gteop ) == 0x19 ) + { + GTELOG( "GPF" ); + n_sf = 12 * GTE_SF( gteop ); + FLAG = 0; + + MAC1 = A1( ( (INT64)(INT16)IR0 * (INT16)IR1 ) >> n_sf ); + MAC2 = A2( ( (INT64)(INT16)IR0 * (INT16)IR2 ) >> n_sf ); + MAC3 = A3( ( (INT64)(INT16)IR0 * (INT16)IR3 ) >> n_sf ); + IR1 = Lm_B1( (INT32)MAC1, 0 ); + IR2 = Lm_B2( (INT32)MAC2, 0 ); + IR3 = Lm_B3( (INT32)MAC3, 0 ); + CD0 = CD1; + CD1 = CD2; + CD2 = CODE; + R0 = R1; + R1 = R2; + R2 = Lm_C1( (INT32)MAC1 >> 4 ); + G0 = G1; + G1 = G2; + G2 = Lm_C2( (INT32)MAC2 >> 4 ); + B0 = B1; + B1 = B2; + B2 = Lm_C3( (INT32)MAC3 >> 4 ); + return; + } + break; + case 0x3e: + if( GTE_OP( gteop ) == 0x1a ) + { + GTELOG( "GPL" ); + n_sf = 12 * GTE_SF( gteop ); + FLAG = 0; + + MAC1 = A1( ( ( (INT64)(INT32)MAC1 << n_sf ) + ( (INT16)IR0 * (INT16)IR1 ) ) >> n_sf ); + MAC2 = A2( ( ( (INT64)(INT32)MAC2 << n_sf ) + ( (INT16)IR0 * (INT16)IR2 ) ) >> n_sf ); + MAC3 = A3( ( ( (INT64)(INT32)MAC3 << n_sf ) + ( (INT16)IR0 * (INT16)IR3 ) ) >> n_sf ); + IR1 = Lm_B1( (INT32)MAC1, 0 ); + IR2 = Lm_B2( (INT32)MAC2, 0 ); + IR3 = Lm_B3( (INT32)MAC3, 0 ); + CD0 = CD1; + CD1 = CD2; + CD2 = CODE; + R0 = R1; + R1 = R2; + R2 = Lm_C1( (INT32)MAC1 >> 4 ); + G0 = G1; + G1 = G2; + G2 = Lm_C2( (INT32)MAC2 >> 4 ); + B0 = B1; + B1 = B2; + B2 = Lm_C3( (INT32)MAC3 >> 4 ); + return; + } + break; + case 0x3f: + if( gteop == 0x108043f || + gteop == 0x118043f ) + { + GTELOG( "NCCT" ); + FLAG = 0; + + for( n_v = 0; n_v < 3; n_v++ ) + { + MAC1 = A1( ( ( (INT64)(INT16)L11 * (INT16)*p_n_vx[ n_v ] ) + ( (INT16)L12 * (INT16)*p_n_vy[ n_v ] ) + ( (INT16)L13 * (INT16)*p_n_vz[ n_v ] ) ) >> 12 ); + MAC2 = A2( ( ( (INT64)(INT16)L21 * (INT16)*p_n_vx[ n_v ] ) + ( (INT16)L22 * (INT16)*p_n_vy[ n_v ] ) + ( (INT16)L23 * (INT16)*p_n_vz[ n_v ] ) ) >> 12 ); + MAC3 = A3( ( ( (INT64)(INT16)L31 * (INT16)*p_n_vx[ n_v ] ) + ( (INT16)L32 * (INT16)*p_n_vy[ n_v ] ) + ( (INT16)L33 * (INT16)*p_n_vz[ n_v ] ) ) >> 12 ); + IR1 = Lm_B1( (INT32)MAC1, 1 ); + IR2 = Lm_B2( (INT32)MAC2, 1 ); + IR3 = Lm_B3( (INT32)MAC3, 1 ); + MAC1 = A1( ( ( (INT64)RBK << 12 ) + ( (INT16)LR1 * (INT16)IR1 ) + ( (INT16)LR2 * (INT16)IR2 ) + ( (INT16)LR3 * (INT16)IR3 ) ) >> 12 ); + MAC2 = A2( ( ( (INT64)GBK << 12 ) + ( (INT16)LG1 * (INT16)IR1 ) + ( (INT16)LG2 * (INT16)IR2 ) + ( (INT16)LG3 * (INT16)IR3 ) ) >> 12 ); + MAC3 = A3( ( ( (INT64)BBK << 12 ) + ( (INT16)LB1 * (INT16)IR1 ) + ( (INT16)LB2 * (INT16)IR2 ) + ( (INT16)LB3 * (INT16)IR3 ) ) >> 12 ); + IR1 = Lm_B1( (INT32)MAC1, 1 ); + IR2 = Lm_B2( (INT32)MAC2, 1 ); + IR3 = Lm_B3( (INT32)MAC3, 1 ); + MAC1 = A1( ( (INT64)R * (INT16)IR1 ) >> 8 ); + MAC2 = A2( ( (INT64)G * (INT16)IR2 ) >> 8 ); + MAC3 = A3( ( (INT64)B * (INT16)IR3 ) >> 8 ); + IR1 = Lm_B1( (INT32)MAC1, 1 ); + IR2 = Lm_B2( (INT32)MAC2, 1 ); + IR3 = Lm_B3( (INT32)MAC3, 1 ); + CD0 = CD1; + CD1 = CD2; + CD2 = CODE; + R0 = R1; + R1 = R2; + R2 = Lm_C1( (INT32)MAC1 >> 4 ); + G0 = G1; + G1 = G2; + G2 = Lm_C2( (INT32)MAC2 >> 4 ); + B0 = B1; + B1 = B2; + B2 = Lm_C3( (INT32)MAC3 >> 4 ); + } + return; + } + break; + } +// usrintf_showmessage_secs( 1, "unknown GTE op %08x", gteop ); + logerror( "%08x: unknown GTE op %08x\n", cpu->pc, gteop ); + mips_stop(); +} + +/************************************************************************** + * Generic set_info + **************************************************************************/ + +void mips_set_info(mips_cpu_context *cpu, UINT32 state, union cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are set as 64-bit signed integers --- */ + case CPUINFO_INT_INPUT_STATE + MIPS_IRQ0: set_irq_line(cpu, MIPS_IRQ0, info->i); break; + case CPUINFO_INT_INPUT_STATE + MIPS_IRQ1: set_irq_line(cpu, MIPS_IRQ1, info->i); break; + case CPUINFO_INT_INPUT_STATE + MIPS_IRQ2: set_irq_line(cpu, MIPS_IRQ2, info->i); break; + case CPUINFO_INT_INPUT_STATE + MIPS_IRQ3: set_irq_line(cpu, MIPS_IRQ3, info->i); break; + case CPUINFO_INT_INPUT_STATE + MIPS_IRQ4: set_irq_line(cpu, MIPS_IRQ4, info->i); break; + case CPUINFO_INT_INPUT_STATE + MIPS_IRQ5: set_irq_line(cpu, MIPS_IRQ5, info->i); break; + + case CPUINFO_INT_PC: mips_set_pc (cpu, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_PC: mips_set_pc (cpu, info->i ); break; + case CPUINFO_INT_SP: /* no stack */ break; + case CPUINFO_INT_REGISTER + MIPS_DELAYV: cpu->delayv = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_DELAYR: if( info->i <= REGPC ) cpu->delayr = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_HI: cpu->hi = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_LO: cpu->lo = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R0: cpu->r[ 0 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R1: cpu->r[ 1 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R2: cpu->r[ 2 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R3: cpu->r[ 3 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R4: cpu->r[ 4 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R5: cpu->r[ 5 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R6: cpu->r[ 6 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R7: cpu->r[ 7 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R8: cpu->r[ 8 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R9: cpu->r[ 9 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R10: cpu->r[ 10 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R11: cpu->r[ 11 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R12: cpu->r[ 12 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R13: cpu->r[ 13 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R14: cpu->r[ 14 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R15: cpu->r[ 15 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R16: cpu->r[ 16 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R17: cpu->r[ 17 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R18: cpu->r[ 18 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R19: cpu->r[ 19 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R20: cpu->r[ 20 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R21: cpu->r[ 21 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R22: cpu->r[ 22 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R23: cpu->r[ 23 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R24: cpu->r[ 24 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R25: cpu->r[ 25 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R26: cpu->r[ 26 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R27: cpu->r[ 27 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R28: cpu->r[ 28 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R29: cpu->r[ 29 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R30: cpu->r[ 30 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_R31: cpu->r[ 31 ] = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R0: mips_set_cp0r(cpu, 0, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R1: mips_set_cp0r(cpu, 1, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R2: mips_set_cp0r(cpu, 2, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R3: mips_set_cp0r(cpu, 3, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R4: mips_set_cp0r(cpu, 4, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R5: mips_set_cp0r(cpu, 5, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R6: mips_set_cp0r(cpu, 6, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R7: mips_set_cp0r(cpu, 7, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R8: mips_set_cp0r(cpu, 8, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R9: mips_set_cp0r(cpu, 9, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R10: mips_set_cp0r(cpu, 10, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R11: mips_set_cp0r(cpu, 11, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R12: mips_set_cp0r(cpu, 12, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R13: mips_set_cp0r(cpu, 13, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R14: mips_set_cp0r(cpu, 14, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R15: mips_set_cp0r(cpu, 15, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R16: mips_set_cp0r(cpu, 16, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R17: mips_set_cp0r(cpu, 17, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R18: mips_set_cp0r(cpu, 18, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R19: mips_set_cp0r(cpu, 19, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R20: mips_set_cp0r(cpu, 20, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R21: mips_set_cp0r(cpu, 21, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R22: mips_set_cp0r(cpu, 22, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R23: mips_set_cp0r(cpu, 23, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R24: mips_set_cp0r(cpu, 24, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R25: mips_set_cp0r(cpu, 25, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R26: mips_set_cp0r(cpu, 26, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R27: mips_set_cp0r(cpu, 27, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R28: mips_set_cp0r(cpu, 28, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R29: mips_set_cp0r(cpu, 29, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R30: mips_set_cp0r(cpu, 30, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP0R31: mips_set_cp0r(cpu, 31, info->i ); break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR0: cpu->cp2dr[ 0 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR1: cpu->cp2dr[ 1 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR2: cpu->cp2dr[ 2 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR3: cpu->cp2dr[ 3 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR4: cpu->cp2dr[ 4 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR5: cpu->cp2dr[ 5 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR6: cpu->cp2dr[ 6 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR7: cpu->cp2dr[ 7 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR8: cpu->cp2dr[ 8 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR9: cpu->cp2dr[ 9 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR10: cpu->cp2dr[ 10 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR11: cpu->cp2dr[ 11 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR12: cpu->cp2dr[ 12 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR13: cpu->cp2dr[ 13 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR14: cpu->cp2dr[ 14 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR15: cpu->cp2dr[ 15 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR16: cpu->cp2dr[ 16 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR17: cpu->cp2dr[ 17 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR18: cpu->cp2dr[ 18 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR19: cpu->cp2dr[ 19 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR20: cpu->cp2dr[ 20 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR21: cpu->cp2dr[ 21 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR22: cpu->cp2dr[ 22 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR23: cpu->cp2dr[ 23 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR24: cpu->cp2dr[ 24 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR25: cpu->cp2dr[ 25 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR26: cpu->cp2dr[ 26 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR27: cpu->cp2dr[ 27 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR28: cpu->cp2dr[ 28 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR29: cpu->cp2dr[ 29 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR30: cpu->cp2dr[ 30 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR31: cpu->cp2dr[ 31 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR0: cpu->cp2cr[ 0 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR1: cpu->cp2cr[ 1 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR2: cpu->cp2cr[ 2 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR3: cpu->cp2cr[ 3 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR4: cpu->cp2cr[ 4 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR5: cpu->cp2cr[ 5 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR6: cpu->cp2cr[ 6 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR7: cpu->cp2cr[ 7 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR8: cpu->cp2cr[ 8 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR9: cpu->cp2cr[ 9 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR10: cpu->cp2cr[ 10 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR11: cpu->cp2cr[ 11 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR12: cpu->cp2cr[ 12 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR13: cpu->cp2cr[ 13 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR14: cpu->cp2cr[ 14 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR15: cpu->cp2cr[ 15 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR16: cpu->cp2cr[ 16 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR17: cpu->cp2cr[ 17 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR18: cpu->cp2cr[ 18 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR19: cpu->cp2cr[ 19 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR20: cpu->cp2cr[ 20 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR21: cpu->cp2cr[ 21 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR22: cpu->cp2cr[ 22 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR23: cpu->cp2cr[ 23 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR24: cpu->cp2cr[ 24 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR25: cpu->cp2cr[ 25 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR26: cpu->cp2cr[ 26 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR27: cpu->cp2cr[ 27 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR28: cpu->cp2cr[ 28 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR29: cpu->cp2cr[ 29 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR30: cpu->cp2cr[ 30 ].d = info->i; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR31: cpu->cp2cr[ 31 ].d = info->i; break; + + /* --- the following bits of info are set as pointers to data or functions --- */ + case CPUINFO_PTR_IRQ_CALLBACK: cpu->irq_callback = info->irqcallback; break; + } +} + + + +/************************************************************************** + * Generic get_info + **************************************************************************/ + +void mips_get_info(mips_cpu_context *cpu, UINT32 state, union cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(mips_cpu_context); break; + case CPUINFO_INT_INPUT_LINES: info->i = 6; break; + case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break; + case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_LE; break; + case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break; + case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 4; break; + case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break; + case CPUINFO_INT_MIN_CYCLES: info->i = 1; break; + case CPUINFO_INT_MAX_CYCLES: info->i = 40; break; + + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break; + + case CPUINFO_INT_INPUT_STATE + MIPS_IRQ0: info->i = (cpu->cp0r[ CP0_CAUSE ] & 0x400) ? ASSERT_LINE : CLEAR_LINE; break; + case CPUINFO_INT_INPUT_STATE + MIPS_IRQ1: info->i = (cpu->cp0r[ CP0_CAUSE ] & 0x800) ? ASSERT_LINE : CLEAR_LINE; break; + case CPUINFO_INT_INPUT_STATE + MIPS_IRQ2: info->i = (cpu->cp0r[ CP0_CAUSE ] & 0x1000) ? ASSERT_LINE : CLEAR_LINE; break; + case CPUINFO_INT_INPUT_STATE + MIPS_IRQ3: info->i = (cpu->cp0r[ CP0_CAUSE ] & 0x2000) ? ASSERT_LINE : CLEAR_LINE; break; + case CPUINFO_INT_INPUT_STATE + MIPS_IRQ4: info->i = (cpu->cp0r[ CP0_CAUSE ] & 0x4000) ? ASSERT_LINE : CLEAR_LINE; break; + case CPUINFO_INT_INPUT_STATE + MIPS_IRQ5: info->i = (cpu->cp0r[ CP0_CAUSE ] & 0x8000) ? ASSERT_LINE : CLEAR_LINE; break; + + case CPUINFO_INT_PREVIOUSPC: /* not implemented */ break; + + case CPUINFO_INT_PC: info->i = cpu->pc; break; + case CPUINFO_INT_REGISTER + MIPS_PC: info->i = cpu->pc; break; + case CPUINFO_INT_SP: + /* because there is no hardware stack and the pipeline causes the cpu to execute the + instruction after a subroutine call before the subroutine is executed there is little + chance of cmd_step_over() in mamedbg.c working. */ + info->i = 0; break; + case CPUINFO_INT_REGISTER + MIPS_DELAYV: info->i = cpu->delayv; break; + case CPUINFO_INT_REGISTER + MIPS_DELAYR: info->i = cpu->delayr; break; + case CPUINFO_INT_REGISTER + MIPS_HI: info->i = cpu->hi; break; + case CPUINFO_INT_REGISTER + MIPS_LO: info->i = cpu->lo; break; + case CPUINFO_INT_REGISTER + MIPS_R0: info->i = cpu->r[ 0 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R1: info->i = cpu->r[ 1 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R2: info->i = cpu->r[ 2 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R3: info->i = cpu->r[ 3 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R4: info->i = cpu->r[ 4 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R5: info->i = cpu->r[ 5 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R6: info->i = cpu->r[ 6 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R7: info->i = cpu->r[ 7 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R8: info->i = cpu->r[ 8 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R9: info->i = cpu->r[ 9 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R10: info->i = cpu->r[ 10 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R11: info->i = cpu->r[ 11 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R12: info->i = cpu->r[ 12 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R13: info->i = cpu->r[ 13 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R14: info->i = cpu->r[ 14 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R15: info->i = cpu->r[ 15 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R16: info->i = cpu->r[ 16 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R17: info->i = cpu->r[ 17 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R18: info->i = cpu->r[ 18 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R19: info->i = cpu->r[ 19 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R20: info->i = cpu->r[ 20 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R21: info->i = cpu->r[ 21 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R22: info->i = cpu->r[ 22 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R23: info->i = cpu->r[ 23 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R24: info->i = cpu->r[ 24 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R25: info->i = cpu->r[ 25 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R26: info->i = cpu->r[ 26 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R27: info->i = cpu->r[ 27 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R28: info->i = cpu->r[ 28 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R29: info->i = cpu->r[ 29 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R30: info->i = cpu->r[ 30 ]; break; + case CPUINFO_INT_REGISTER + MIPS_R31: info->i = cpu->r[ 31 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R0: info->i = cpu->cp0r[ 0 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R1: info->i = cpu->cp0r[ 1 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R2: info->i = cpu->cp0r[ 2 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R3: info->i = cpu->cp0r[ 3 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R4: info->i = cpu->cp0r[ 4 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R5: info->i = cpu->cp0r[ 5 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R6: info->i = cpu->cp0r[ 6 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R7: info->i = cpu->cp0r[ 7 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R8: info->i = cpu->cp0r[ 8 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R9: info->i = cpu->cp0r[ 9 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R10: info->i = cpu->cp0r[ 10 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R11: info->i = cpu->cp0r[ 11 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R12: info->i = cpu->cp0r[ 12 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R13: info->i = cpu->cp0r[ 13 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R14: info->i = cpu->cp0r[ 14 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R15: info->i = cpu->cp0r[ 15 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R16: info->i = cpu->cp0r[ 16 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R17: info->i = cpu->cp0r[ 17 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R18: info->i = cpu->cp0r[ 18 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R19: info->i = cpu->cp0r[ 19 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R20: info->i = cpu->cp0r[ 20 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R21: info->i = cpu->cp0r[ 21 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R22: info->i = cpu->cp0r[ 22 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R23: info->i = cpu->cp0r[ 23 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R24: info->i = cpu->cp0r[ 24 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R25: info->i = cpu->cp0r[ 25 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R26: info->i = cpu->cp0r[ 26 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R27: info->i = cpu->cp0r[ 27 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R28: info->i = cpu->cp0r[ 28 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R29: info->i = cpu->cp0r[ 29 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R30: info->i = cpu->cp0r[ 30 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP0R31: info->i = cpu->cp0r[ 31 ]; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR0: info->i = cpu->cp2dr[ 0 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR1: info->i = cpu->cp2dr[ 1 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR2: info->i = cpu->cp2dr[ 2 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR3: info->i = cpu->cp2dr[ 3 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR4: info->i = cpu->cp2dr[ 4 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR5: info->i = cpu->cp2dr[ 5 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR6: info->i = cpu->cp2dr[ 6 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR7: info->i = cpu->cp2dr[ 7 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR8: info->i = cpu->cp2dr[ 8 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR9: info->i = cpu->cp2dr[ 9 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR10: info->i = cpu->cp2dr[ 10 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR11: info->i = cpu->cp2dr[ 11 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR12: info->i = cpu->cp2dr[ 12 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR13: info->i = cpu->cp2dr[ 13 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR14: info->i = cpu->cp2dr[ 14 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR15: info->i = cpu->cp2dr[ 15 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR16: info->i = cpu->cp2dr[ 16 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR17: info->i = cpu->cp2dr[ 17 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR18: info->i = cpu->cp2dr[ 18 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR19: info->i = cpu->cp2dr[ 19 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR20: info->i = cpu->cp2dr[ 20 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR21: info->i = cpu->cp2dr[ 21 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR22: info->i = cpu->cp2dr[ 22 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR23: info->i = cpu->cp2dr[ 23 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR24: info->i = cpu->cp2dr[ 24 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR25: info->i = cpu->cp2dr[ 25 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR26: info->i = cpu->cp2dr[ 26 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR27: info->i = cpu->cp2dr[ 27 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR28: info->i = cpu->cp2dr[ 28 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR29: info->i = cpu->cp2dr[ 29 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR30: info->i = cpu->cp2dr[ 30 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2DR31: info->i = cpu->cp2dr[ 31 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR0: info->i = cpu->cp2cr[ 0 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR1: info->i = cpu->cp2cr[ 1 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR2: info->i = cpu->cp2cr[ 2 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR3: info->i = cpu->cp2cr[ 3 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR4: info->i = cpu->cp2cr[ 4 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR5: info->i = cpu->cp2cr[ 5 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR6: info->i = cpu->cp2cr[ 6 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR7: info->i = cpu->cp2cr[ 7 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR8: info->i = cpu->cp2cr[ 8 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR9: info->i = cpu->cp2cr[ 9 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR10: info->i = cpu->cp2cr[ 10 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR11: info->i = cpu->cp2cr[ 11 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR12: info->i = cpu->cp2cr[ 12 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR13: info->i = cpu->cp2cr[ 13 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR14: info->i = cpu->cp2cr[ 14 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR15: info->i = cpu->cp2cr[ 15 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR16: info->i = cpu->cp2cr[ 16 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR17: info->i = cpu->cp2cr[ 17 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR18: info->i = cpu->cp2cr[ 18 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR19: info->i = cpu->cp2cr[ 19 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR20: info->i = cpu->cp2cr[ 20 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR21: info->i = cpu->cp2cr[ 21 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR22: info->i = cpu->cp2cr[ 22 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR23: info->i = cpu->cp2cr[ 23 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR24: info->i = cpu->cp2cr[ 24 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR25: info->i = cpu->cp2cr[ 25 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR26: info->i = cpu->cp2cr[ 26 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR27: info->i = cpu->cp2cr[ 27 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR28: info->i = cpu->cp2cr[ 28 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR29: info->i = cpu->cp2cr[ 29 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR30: info->i = cpu->cp2cr[ 30 ].d; break; + case CPUINFO_INT_REGISTER + MIPS_CP2CR31: info->i = cpu->cp2cr[ 31 ].d; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_SET_INFO: info->setinfo = mips_set_info; break; +// case CPUINFO_PTR_GET_CONTEXT: info->getcontext = mips_get_context; break; +// case CPUINFO_PTR_SET_CONTEXT: info->setcontext = mips_set_context; break; + case CPUINFO_PTR_INIT: info->init = mips_init; break; + case CPUINFO_PTR_RESET: info->reset = mips_reset; break; + case CPUINFO_PTR_EXIT: info->exit = mips_exit; break; + case CPUINFO_PTR_EXECUTE: info->execute = mips_execute; break; + case CPUINFO_PTR_BURN: info->burn = NULL; break; + case CPUINFO_PTR_DISASSEMBLE: info->disassemble = mips_dasm; break; + case CPUINFO_PTR_IRQ_CALLBACK: info->irqcallback = cpu->irq_callback; break; + case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpu->mips_ICount; break; + case CPUINFO_PTR_REGISTER_LAYOUT: info->p = mips_reg_layout; break; + case CPUINFO_PTR_WINDOW_LAYOUT: info->p = mips_win_layout; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ +#if 0 + case CPUINFO_STR_NAME: strcpy(info->s = cpuintrf_temp_str(), "PSX CPU"); break; + case CPUINFO_STR_CORE_FAMILY: strcpy(info->s = cpuintrf_temp_str(), "mipscpu"); break; + case CPUINFO_STR_CORE_VERSION: strcpy(info->s = cpuintrf_temp_str(), "1.4"); break; + case CPUINFO_STR_CORE_FILE: strcpy(info->s = cpuintrf_temp_str(), __FILE__); break; + case CPUINFO_STR_CORE_CREDITS: strcpy(info->s = cpuintrf_temp_str(), "Copyright 2003 smf"); break; + + case CPUINFO_STR_FLAGS: strcpy(info->s = cpuintrf_temp_str(), " "); break; + + case CPUINFO_STR_REGISTER + MIPS_PC: sprintf( info->s = cpuintrf_temp_str(), "pc :%08x", cpu->pc ); break; + case CPUINFO_STR_REGISTER + MIPS_DELAYV: sprintf( info->s = cpuintrf_temp_str(), "delay :%08x", cpu->delayv ); break; + case CPUINFO_STR_REGISTER + MIPS_DELAYR: sprintf( info->s = cpuintrf_temp_str(), "delay %s:%02x", delayn[ cpu->delayr ], cpu->delayr ); break; + case CPUINFO_STR_REGISTER + MIPS_HI: sprintf( info->s = cpuintrf_temp_str(), "hi :%08x", cpu->hi ); break; + case CPUINFO_STR_REGISTER + MIPS_LO: sprintf( info->s = cpuintrf_temp_str(), "lo :%08x", cpu->lo ); break; + case CPUINFO_STR_REGISTER + MIPS_R0: sprintf( info->s = cpuintrf_temp_str(), "zero :%08x", cpu->r[ 0 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R1: sprintf( info->s = cpuintrf_temp_str(), "at :%08x", cpu->r[ 1 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R2: sprintf( info->s = cpuintrf_temp_str(), "v0 :%08x", cpu->r[ 2 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R3: sprintf( info->s = cpuintrf_temp_str(), "v1 :%08x", cpu->r[ 3 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R4: sprintf( info->s = cpuintrf_temp_str(), "a0 :%08x", cpu->r[ 4 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R5: sprintf( info->s = cpuintrf_temp_str(), "a1 :%08x", cpu->r[ 5 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R6: sprintf( info->s = cpuintrf_temp_str(), "a2 :%08x", cpu->r[ 6 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R7: sprintf( info->s = cpuintrf_temp_str(), "a3 :%08x", cpu->r[ 7 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R8: sprintf( info->s = cpuintrf_temp_str(), "t0 :%08x", cpu->r[ 8 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R9: sprintf( info->s = cpuintrf_temp_str(), "t1 :%08x", cpu->r[ 9 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R10: sprintf( info->s = cpuintrf_temp_str(), "t2 :%08x", cpu->r[ 10 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R11: sprintf( info->s = cpuintrf_temp_str(), "t3 :%08x", cpu->r[ 11 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R12: sprintf( info->s = cpuintrf_temp_str(), "t4 :%08x", cpu->r[ 12 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R13: sprintf( info->s = cpuintrf_temp_str(), "t5 :%08x", cpu->r[ 13 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R14: sprintf( info->s = cpuintrf_temp_str(), "t6 :%08x", cpu->r[ 14 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R15: sprintf( info->s = cpuintrf_temp_str(), "t7 :%08x", cpu->r[ 15 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R16: sprintf( info->s = cpuintrf_temp_str(), "s0 :%08x", cpu->r[ 16 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R17: sprintf( info->s = cpuintrf_temp_str(), "s1 :%08x", cpu->r[ 17 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R18: sprintf( info->s = cpuintrf_temp_str(), "s2 :%08x", cpu->r[ 18 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R19: sprintf( info->s = cpuintrf_temp_str(), "s3 :%08x", cpu->r[ 19 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R20: sprintf( info->s = cpuintrf_temp_str(), "s4 :%08x", cpu->r[ 20 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R21: sprintf( info->s = cpuintrf_temp_str(), "s5 :%08x", cpu->r[ 21 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R22: sprintf( info->s = cpuintrf_temp_str(), "s6 :%08x", cpu->r[ 22 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R23: sprintf( info->s = cpuintrf_temp_str(), "s7 :%08x", cpu->r[ 23 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R24: sprintf( info->s = cpuintrf_temp_str(), "t8 :%08x", cpu->r[ 24 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R25: sprintf( info->s = cpuintrf_temp_str(), "t9 :%08x", cpu->r[ 25 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R26: sprintf( info->s = cpuintrf_temp_str(), "k0 :%08x", cpu->r[ 26 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R27: sprintf( info->s = cpuintrf_temp_str(), "k1 :%08x", cpu->r[ 27 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R28: sprintf( info->s = cpuintrf_temp_str(), "gp :%08x", cpu->r[ 28 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R29: sprintf( info->s = cpuintrf_temp_str(), "sp :%08x", cpu->r[ 29 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R30: sprintf( info->s = cpuintrf_temp_str(), "fp :%08x", cpu->r[ 30 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_R31: sprintf( info->s = cpuintrf_temp_str(), "ra :%08x", cpu->r[ 31 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R0: sprintf( info->s = cpuintrf_temp_str(), "Index :%08x", cpu->cp0r[ 0 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R1: sprintf( info->s = cpuintrf_temp_str(), "Random :%08x", cpu->cp0r[ 1 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R2: sprintf( info->s = cpuintrf_temp_str(), "EntryLo :%08x", cpu->cp0r[ 2 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R3: sprintf( info->s = cpuintrf_temp_str(), "cp0r3 :%08x", cpu->cp0r[ 3 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R4: sprintf( info->s = cpuintrf_temp_str(), "Context :%08x", cpu->cp0r[ 4 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R5: sprintf( info->s = cpuintrf_temp_str(), "cp0r5 :%08x", cpu->cp0r[ 5 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R6: sprintf( info->s = cpuintrf_temp_str(), "cp0r6 :%08x", cpu->cp0r[ 6 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R7: sprintf( info->s = cpuintrf_temp_str(), "cp0r7 :%08x", cpu->cp0r[ 7 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R8: sprintf( info->s = cpuintrf_temp_str(), "BadVAddr:%08x", cpu->cp0r[ 8 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R9: sprintf( info->s = cpuintrf_temp_str(), "cp0r9 :%08x", cpu->cp0r[ 9 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R10: sprintf( info->s = cpuintrf_temp_str(), "EntryHi :%08x", cpu->cp0r[ 10 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R11: sprintf( info->s = cpuintrf_temp_str(), "cp0r11 :%08x", cpu->cp0r[ 11 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R12: sprintf( info->s = cpuintrf_temp_str(), "SR :%08x", cpu->cp0r[ 12 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R13: sprintf( info->s = cpuintrf_temp_str(), "Cause :%08x", cpu->cp0r[ 13 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R14: sprintf( info->s = cpuintrf_temp_str(), "EPC :%08x", cpu->cp0r[ 14 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R15: sprintf( info->s = cpuintrf_temp_str(), "PRId :%08x", cpu->cp0r[ 15 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R16: sprintf( info->s = cpuintrf_temp_str(), "cp0r16 :%08x", cpu->cp0r[ 16 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R17: sprintf( info->s = cpuintrf_temp_str(), "cp0r17 :%08x", cpu->cp0r[ 17 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R18: sprintf( info->s = cpuintrf_temp_str(), "cp0r18 :%08x", cpu->cp0r[ 18 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R19: sprintf( info->s = cpuintrf_temp_str(), "cp0r19 :%08x", cpu->cp0r[ 19 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R20: sprintf( info->s = cpuintrf_temp_str(), "cp0r20 :%08x", cpu->cp0r[ 20 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R21: sprintf( info->s = cpuintrf_temp_str(), "cp0r21 :%08x", cpu->cp0r[ 21 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R22: sprintf( info->s = cpuintrf_temp_str(), "cp0r22 :%08x", cpu->cp0r[ 22 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R23: sprintf( info->s = cpuintrf_temp_str(), "cp0r23 :%08x", cpu->cp0r[ 23 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R24: sprintf( info->s = cpuintrf_temp_str(), "cp0r24 :%08x", cpu->cp0r[ 24 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R25: sprintf( info->s = cpuintrf_temp_str(), "cp0r25 :%08x", cpu->cp0r[ 25 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R26: sprintf( info->s = cpuintrf_temp_str(), "cp0r26 :%08x", cpu->cp0r[ 26 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R27: sprintf( info->s = cpuintrf_temp_str(), "cp0r27 :%08x", cpu->cp0r[ 27 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R28: sprintf( info->s = cpuintrf_temp_str(), "cp0r28 :%08x", cpu->cp0r[ 28 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R29: sprintf( info->s = cpuintrf_temp_str(), "cp0r29 :%08x", cpu->cp0r[ 29 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R30: sprintf( info->s = cpuintrf_temp_str(), "cp0r30 :%08x", cpu->cp0r[ 30 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP0R31: sprintf( info->s = cpuintrf_temp_str(), "cp0r31 :%08x", cpu->cp0r[ 31 ] ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR0: sprintf( info->s = cpuintrf_temp_str(), "vxy0 :%08x", cpu->cp2dr[ 0 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR1: sprintf( info->s = cpuintrf_temp_str(), "vz0 :%08x", cpu->cp2dr[ 1 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR2: sprintf( info->s = cpuintrf_temp_str(), "vxy1 :%08x", cpu->cp2dr[ 2 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR3: sprintf( info->s = cpuintrf_temp_str(), "vz1 :%08x", cpu->cp2dr[ 3 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR4: sprintf( info->s = cpuintrf_temp_str(), "vxy2 :%08x", cpu->cp2dr[ 4 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR5: sprintf( info->s = cpuintrf_temp_str(), "vz2 :%08x", cpu->cp2dr[ 5 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR6: sprintf( info->s = cpuintrf_temp_str(), "rgb :%08x", cpu->cp2dr[ 6 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR7: sprintf( info->s = cpuintrf_temp_str(), "otz :%08x", cpu->cp2dr[ 7 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR8: sprintf( info->s = cpuintrf_temp_str(), "ir0 :%08x", cpu->cp2dr[ 8 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR9: sprintf( info->s = cpuintrf_temp_str(), "ir1 :%08x", cpu->cp2dr[ 9 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR10: sprintf( info->s = cpuintrf_temp_str(), "ir2 :%08x", cpu->cp2dr[ 10 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR11: sprintf( info->s = cpuintrf_temp_str(), "ir3 :%08x", cpu->cp2dr[ 11 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR12: sprintf( info->s = cpuintrf_temp_str(), "sxy0 :%08x", cpu->cp2dr[ 12 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR13: sprintf( info->s = cpuintrf_temp_str(), "sxy1 :%08x", cpu->cp2dr[ 13 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR14: sprintf( info->s = cpuintrf_temp_str(), "sxy2 :%08x", cpu->cp2dr[ 14 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR15: sprintf( info->s = cpuintrf_temp_str(), "sxyp :%08x", cpu->cp2dr[ 15 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR16: sprintf( info->s = cpuintrf_temp_str(), "sz0 :%08x", cpu->cp2dr[ 16 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR17: sprintf( info->s = cpuintrf_temp_str(), "sz1 :%08x", cpu->cp2dr[ 17 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR18: sprintf( info->s = cpuintrf_temp_str(), "sz2 :%08x", cpu->cp2dr[ 18 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR19: sprintf( info->s = cpuintrf_temp_str(), "sz3 :%08x", cpu->cp2dr[ 19 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR20: sprintf( info->s = cpuintrf_temp_str(), "rgb0 :%08x", cpu->cp2dr[ 20 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR21: sprintf( info->s = cpuintrf_temp_str(), "rgb1 :%08x", cpu->cp2dr[ 21 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR22: sprintf( info->s = cpuintrf_temp_str(), "rgb2 :%08x", cpu->cp2dr[ 22 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR23: sprintf( info->s = cpuintrf_temp_str(), "res1 :%08x", cpu->cp2dr[ 23 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR24: sprintf( info->s = cpuintrf_temp_str(), "mac0 :%08x", cpu->cp2dr[ 24 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR25: sprintf( info->s = cpuintrf_temp_str(), "mac1 :%08x", cpu->cp2dr[ 25 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR26: sprintf( info->s = cpuintrf_temp_str(), "mac2 :%08x", cpu->cp2dr[ 26 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR27: sprintf( info->s = cpuintrf_temp_str(), "mac3 :%08x", cpu->cp2dr[ 27 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR28: sprintf( info->s = cpuintrf_temp_str(), "irgb :%08x", cpu->cp2dr[ 28 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR29: sprintf( info->s = cpuintrf_temp_str(), "orgb :%08x", cpu->cp2dr[ 29 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR30: sprintf( info->s = cpuintrf_temp_str(), "lzcs :%08x", cpu->cp2dr[ 30 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2DR31: sprintf( info->s = cpuintrf_temp_str(), "lzcr :%08x", cpu->cp2dr[ 31 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR0: sprintf( info->s = cpuintrf_temp_str(), "r11r12 :%08x", cpu->cp2cr[ 0 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR1: sprintf( info->s = cpuintrf_temp_str(), "r13r21 :%08x", cpu->cp2cr[ 1 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR2: sprintf( info->s = cpuintrf_temp_str(), "r22r23 :%08x", cpu->cp2cr[ 2 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR3: sprintf( info->s = cpuintrf_temp_str(), "r31r32 :%08x", cpu->cp2cr[ 3 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR4: sprintf( info->s = cpuintrf_temp_str(), "r33 :%08x", cpu->cp2cr[ 4 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR5: sprintf( info->s = cpuintrf_temp_str(), "trx :%08x", cpu->cp2cr[ 5 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR6: sprintf( info->s = cpuintrf_temp_str(), "try :%08x", cpu->cp2cr[ 6 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR7: sprintf( info->s = cpuintrf_temp_str(), "trz :%08x", cpu->cp2cr[ 7 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR8: sprintf( info->s = cpuintrf_temp_str(), "l11l12 :%08x", cpu->cp2cr[ 8 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR9: sprintf( info->s = cpuintrf_temp_str(), "l13l21 :%08x", cpu->cp2cr[ 9 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR10: sprintf( info->s = cpuintrf_temp_str(), "l22l23 :%08x", cpu->cp2cr[ 10 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR11: sprintf( info->s = cpuintrf_temp_str(), "l31l32 :%08x", cpu->cp2cr[ 11 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR12: sprintf( info->s = cpuintrf_temp_str(), "l33 :%08x", cpu->cp2cr[ 12 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR13: sprintf( info->s = cpuintrf_temp_str(), "rbk :%08x", cpu->cp2cr[ 13 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR14: sprintf( info->s = cpuintrf_temp_str(), "gbk :%08x", cpu->cp2cr[ 14 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR15: sprintf( info->s = cpuintrf_temp_str(), "bbk :%08x", cpu->cp2cr[ 15 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR16: sprintf( info->s = cpuintrf_temp_str(), "lr1lr2 :%08x", cpu->cp2cr[ 16 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR17: sprintf( info->s = cpuintrf_temp_str(), "lr31g1 :%08x", cpu->cp2cr[ 17 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR18: sprintf( info->s = cpuintrf_temp_str(), "lg2lg3 :%08x", cpu->cp2cr[ 18 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR19: sprintf( info->s = cpuintrf_temp_str(), "lb1lb2 :%08x", cpu->cp2cr[ 19 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR20: sprintf( info->s = cpuintrf_temp_str(), "lb3 :%08x", cpu->cp2cr[ 20 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR21: sprintf( info->s = cpuintrf_temp_str(), "rfc :%08x", cpu->cp2cr[ 21 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR22: sprintf( info->s = cpuintrf_temp_str(), "gfc :%08x", cpu->cp2cr[ 22 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR23: sprintf( info->s = cpuintrf_temp_str(), "bfc :%08x", cpu->cp2cr[ 23 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR24: sprintf( info->s = cpuintrf_temp_str(), "ofx :%08x", cpu->cp2cr[ 24 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR25: sprintf( info->s = cpuintrf_temp_str(), "ofy :%08x", cpu->cp2cr[ 25 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR26: sprintf( info->s = cpuintrf_temp_str(), "h :%08x", cpu->cp2cr[ 26 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR27: sprintf( info->s = cpuintrf_temp_str(), "dqa :%08x", cpu->cp2cr[ 27 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR28: sprintf( info->s = cpuintrf_temp_str(), "dqb :%08x", cpu->cp2cr[ 28 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR29: sprintf( info->s = cpuintrf_temp_str(), "zsf3 :%08x", cpu->cp2cr[ 29 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR30: sprintf( info->s = cpuintrf_temp_str(), "zsf4 :%08x", cpu->cp2cr[ 30 ].d ); break; + case CPUINFO_STR_REGISTER + MIPS_CP2CR31: sprintf( info->s = cpuintrf_temp_str(), "flag :%08x", cpu->cp2cr[ 31 ].d ); break; +#endif + } +} + +uint32 mips_get_cause(mips_cpu_context *cpu) +{ + return cpu->cp0r[ CP0_CAUSE ]; +} + +uint32 mips_get_status(mips_cpu_context *cpu) +{ + return cpu->cp0r[ CP0_SR ]; +} + +void mips_set_status(mips_cpu_context *cpu, uint32 status) +{ + cpu->cp0r[ CP0_SR ] = status; +} + +uint32 mips_get_ePC(mips_cpu_context *cpu) +{ + return cpu->cp0r[ CP0_EPC ]; +} + +int mips_get_icount(mips_cpu_context *cpu) +{ + return cpu->mips_ICount; +} + +void mips_set_icount(mips_cpu_context *cpu, int count) +{ + cpu->mips_ICount = count; +} + + +#if (HAS_PSXCPU) +/************************************************************************** + * CPU-specific set_info + **************************************************************************/ + +void psxcpu_get_info(mips_cpu_context *cpu, UINT32 state, union cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as NULL-terminated strings --- */ +// case CPUINFO_STR_NAME: strcpy(info->s = cpuintrf_temp_str(), "PSX CPU"); break; + + default: + mips_get_info(cpu, state, info); + break; + } +} +#endif diff --git a/plugins/ao/eng_psf/psx.h b/plugins/ao/eng_psf/psx.h new file mode 100644 index 00000000..12631f26 --- /dev/null +++ b/plugins/ao/eng_psf/psx.h @@ -0,0 +1,372 @@ +#ifndef _MIPS_H +#define _MIPS_H + +#include "ao.h" +#include "osd_cpu.h" +//#include "driver.h" + +typedef void genf(void); +typedef int offs_t; + +#define cpu_readop32(pc) program_read_dword_32le(cpu, pc) +#define change_pc(pc) \ + + +#ifdef __GNUC__ +#if (__GNUC__ < 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ <= 7)) +#define UNUSEDARG +#else +#define UNUSEDARG __attribute__((__unused__)) +#endif +#else +#define UNUSEDARG +#endif + +typedef int8 (*read8_handler) (UNUSEDARG offs_t offset); +typedef void (*write8_handler) (UNUSEDARG offs_t offset, UNUSEDARG int8 data); +typedef int16 (*read16_handler) (UNUSEDARG offs_t offset, UNUSEDARG int16 mem_mask); +typedef void (*write16_handler)(UNUSEDARG offs_t offset, UNUSEDARG int16 data, UNUSEDARG int16 mem_mask); +typedef int32 (*read32_handler) (UNUSEDARG offs_t offset, UNUSEDARG int32 mem_mask); +typedef void (*write32_handler)(UNUSEDARG offs_t offset, UNUSEDARG int32 data, UNUSEDARG int32 mem_mask); +typedef int64 (*read64_handler) (UNUSEDARG offs_t offset, UNUSEDARG int64 mem_mask); +typedef void (*write64_handler)(UNUSEDARG offs_t offset, UNUSEDARG int64 data, UNUSEDARG int64 mem_mask); + +union read_handlers_t +{ + genf * handler; + read8_handler handler8; + read16_handler handler16; + read32_handler handler32; + read64_handler handler64; +}; + +union write_handlers_t +{ + genf * handler; + write8_handler handler8; + write16_handler handler16; + write32_handler handler32; + write64_handler handler64; +}; + +struct address_map_t +{ + uint32 flags; /* flags and additional info about this entry */ + offs_t start, end; /* start/end (or mask/match) values */ + offs_t mirror; /* mirror bits */ + offs_t mask; /* mask bits */ + union read_handlers_t read; /* read handler callback */ + union write_handlers_t write; /* write handler callback */ + void * memory; /* pointer to memory backing this entry */ + uint32 share; /* index of a shared memory block */ + void ** base; /* receives pointer to memory (optional) */ + size_t * size; /* receives size of area in bytes (optional) */ +}; +typedef struct address_map_t *(*construct_map_t)(struct address_map_t *map); + +typedef struct mips_cpu_context_s +{ + UINT32 op; + UINT32 pc; + UINT32 prevpc; + UINT32 delayv; + UINT32 delayr; + UINT32 hi; + UINT32 lo; + UINT32 r[ 32 ]; + UINT32 cp0r[ 32 ]; + PAIR cp2cr[ 32 ]; + PAIR cp2dr[ 32 ]; + int (*irq_callback)(struct mips_cpu_context_s *cpu, int irqline); + int mips_ICount; + // PSX main RAM + uint32 psx_ram[(2*1024*1024)/4]; + uint32 psx_scratch[0x400]; + // backup image to restart songs + uint32 initial_ram[(2*1024*1024)/4]; + uint32 initial_scratch[0x400]; + + // spu + struct spu_state_s *spu; + struct spu2_state_s *spu2; + void (*spu_callback)(unsigned char *, long, void *); + void *spu_callback_data; +} mips_cpu_context; + +union cpuinfo +{ + int64 i; /* generic integers */ + void * p; /* generic pointers */ + genf * f; /* generic function pointers */ + char * s; /* generic strings */ + mips_cpu_context *cpu; + + void (*setinfo)(mips_cpu_context *cpu, UINT32 state, union cpuinfo *info);/* CPUINFO_PTR_SET_INFO */ +// void (*getcontext)(void *context); /* CPUINFO_PTR_GET_CONTEXT */ +// void (*setcontext)(void *context); /* CPUINFO_PTR_SET_CONTEXT */ + void (*init)(mips_cpu_context *cpu); /* CPUINFO_PTR_INIT */ + void (*reset)(mips_cpu_context *cpu, void *param); /* CPUINFO_PTR_RESET */ + void (*exit)(mips_cpu_context *cpu); /* CPUINFO_PTR_EXIT */ + int (*execute)(mips_cpu_context *cpu, int cycles); /* CPUINFO_PTR_EXECUTE */ + void (*burn)(mips_cpu_context *cpu, int cycles); /* CPUINFO_PTR_BURN */ + offs_t (*disassemble)(mips_cpu_context *cpu, char *buffer, offs_t pc); /* CPUINFO_PTR_DISASSEMBLE */ + int (*irqcallback)(mips_cpu_context *cpu, int state); /* CPUINFO_PTR_IRQCALLBACK */ + int * icount; /* CPUINFO_PTR_INSTRUCTION_COUNTER */ + construct_map_t internal_map; /* CPUINFO_PTR_INTERNAL_MEMORY_MAP */ +}; + +enum +{ + MIPS_PC = 1, + MIPS_DELAYV, MIPS_DELAYR, + MIPS_HI, MIPS_LO, + MIPS_R0, MIPS_R1, + MIPS_R2, MIPS_R3, + MIPS_R4, MIPS_R5, + MIPS_R6, MIPS_R7, + MIPS_R8, MIPS_R9, + MIPS_R10, MIPS_R11, + MIPS_R12, MIPS_R13, + MIPS_R14, MIPS_R15, + MIPS_R16, MIPS_R17, + MIPS_R18, MIPS_R19, + MIPS_R20, MIPS_R21, + MIPS_R22, MIPS_R23, + MIPS_R24, MIPS_R25, + MIPS_R26, MIPS_R27, + MIPS_R28, MIPS_R29, + MIPS_R30, MIPS_R31, + MIPS_CP0R0, MIPS_CP0R1, + MIPS_CP0R2, MIPS_CP0R3, + MIPS_CP0R4, MIPS_CP0R5, + MIPS_CP0R6, MIPS_CP0R7, + MIPS_CP0R8, MIPS_CP0R9, + MIPS_CP0R10, MIPS_CP0R11, + MIPS_CP0R12, MIPS_CP0R13, + MIPS_CP0R14, MIPS_CP0R15, + MIPS_CP0R16, MIPS_CP0R17, + MIPS_CP0R18, MIPS_CP0R19, + MIPS_CP0R20, MIPS_CP0R21, + MIPS_CP0R22, MIPS_CP0R23, + MIPS_CP0R24, MIPS_CP0R25, + MIPS_CP0R26, MIPS_CP0R27, + MIPS_CP0R28, MIPS_CP0R29, + MIPS_CP0R30, MIPS_CP0R31, + MIPS_CP2DR0, MIPS_CP2DR1, + MIPS_CP2DR2, MIPS_CP2DR3, + MIPS_CP2DR4, MIPS_CP2DR5, + MIPS_CP2DR6, MIPS_CP2DR7, + MIPS_CP2DR8, MIPS_CP2DR9, + MIPS_CP2DR10, MIPS_CP2DR11, + MIPS_CP2DR12, MIPS_CP2DR13, + MIPS_CP2DR14, MIPS_CP2DR15, + MIPS_CP2DR16, MIPS_CP2DR17, + MIPS_CP2DR18, MIPS_CP2DR19, + MIPS_CP2DR20, MIPS_CP2DR21, + MIPS_CP2DR22, MIPS_CP2DR23, + MIPS_CP2DR24, MIPS_CP2DR25, + MIPS_CP2DR26, MIPS_CP2DR27, + MIPS_CP2DR28, MIPS_CP2DR29, + MIPS_CP2DR30, MIPS_CP2DR31, + MIPS_CP2CR0, MIPS_CP2CR1, + MIPS_CP2CR2, MIPS_CP2CR3, + MIPS_CP2CR4, MIPS_CP2CR5, + MIPS_CP2CR6, MIPS_CP2CR7, + MIPS_CP2CR8, MIPS_CP2CR9, + MIPS_CP2CR10, MIPS_CP2CR11, + MIPS_CP2CR12, MIPS_CP2CR13, + MIPS_CP2CR14, MIPS_CP2CR15, + MIPS_CP2CR16, MIPS_CP2CR17, + MIPS_CP2CR18, MIPS_CP2CR19, + MIPS_CP2CR20, MIPS_CP2CR21, + MIPS_CP2CR22, MIPS_CP2CR23, + MIPS_CP2CR24, MIPS_CP2CR25, + MIPS_CP2CR26, MIPS_CP2CR27, + MIPS_CP2CR28, MIPS_CP2CR29, + MIPS_CP2CR30, MIPS_CP2CR31 +}; + +#define MIPS_INT_NONE ( -1 ) + +#define MIPS_IRQ0 ( 0 ) +#define MIPS_IRQ1 ( 1 ) +#define MIPS_IRQ2 ( 2 ) +#define MIPS_IRQ3 ( 3 ) +#define MIPS_IRQ4 ( 4 ) +#define MIPS_IRQ5 ( 5 ) + +#define MIPS_BYTE_EXTEND( a ) ( (INT32)(INT8)a ) +#define MIPS_WORD_EXTEND( a ) ( (INT32)(INT16)a ) + +#define INS_OP( op ) ( ( op >> 26 ) & 63 ) +#define INS_RS( op ) ( ( op >> 21 ) & 31 ) +#define INS_RT( op ) ( ( op >> 16 ) & 31 ) +#define INS_IMMEDIATE( op ) ( op & 0xffff ) +#define INS_TARGET( op ) ( op & 0x3ffffff ) +#define INS_RD( op ) ( ( op >> 11 ) & 31 ) +#define INS_SHAMT( op ) ( ( op >> 6 ) & 31 ) +#define INS_FUNCT( op ) ( op & 63 ) +#define INS_CODE( op ) ( ( op >> 6 ) & 0xfffff ) +#define INS_CO( op ) ( ( op >> 25 ) & 1 ) +#define INS_COFUN( op ) ( op & 0x1ffffff ) +#define INS_CF( op ) ( op & 63 ) + +#define GTE_OP( op ) ( ( op >> 20 ) & 31 ) +#define GTE_SF( op ) ( ( op >> 19 ) & 1 ) +#define GTE_MX( op ) ( ( op >> 17 ) & 3 ) +#define GTE_V( op ) ( ( op >> 15 ) & 3 ) +#define GTE_CV( op ) ( ( op >> 13 ) & 3 ) +#define GTE_CD( op ) ( ( op >> 11 ) & 3 ) /* not used */ +#define GTE_LM( op ) ( ( op >> 10 ) & 1 ) +#define GTE_CT( op ) ( ( op >> 6 ) & 15 ) /* not used */ +#define GTE_FUNCT( op ) ( op & 63 ) + +#define OP_SPECIAL ( 0 ) +#define OP_REGIMM ( 1 ) +#define OP_J ( 2 ) +#define OP_JAL ( 3 ) +#define OP_BEQ ( 4 ) +#define OP_BNE ( 5 ) +#define OP_BLEZ ( 6 ) +#define OP_BGTZ ( 7 ) +#define OP_ADDI ( 8 ) +#define OP_ADDIU ( 9 ) +#define OP_SLTI ( 10 ) +#define OP_SLTIU ( 11 ) +#define OP_ANDI ( 12 ) +#define OP_ORI ( 13 ) +#define OP_XORI ( 14 ) +#define OP_LUI ( 15 ) +#define OP_COP0 ( 16 ) +#define OP_COP1 ( 17 ) +#define OP_COP2 ( 18 ) +#define OP_LB ( 32 ) +#define OP_LH ( 33 ) +#define OP_LWL ( 34 ) +#define OP_LW ( 35 ) +#define OP_LBU ( 36 ) +#define OP_LHU ( 37 ) +#define OP_LWR ( 38 ) +#define OP_SB ( 40 ) +#define OP_SH ( 41 ) +#define OP_SWL ( 42 ) +#define OP_SW ( 43 ) +#define OP_SWR ( 46 ) +#define OP_LWC1 ( 49 ) +#define OP_LWC2 ( 50 ) +#define OP_SWC1 ( 57 ) +#define OP_SWC2 ( 58 ) + +/* OP_SPECIAL */ +#define FUNCT_SLL ( 0 ) +#define FUNCT_SRL ( 2 ) +#define FUNCT_SRA ( 3 ) +#define FUNCT_SLLV ( 4 ) +#define FUNCT_SRLV ( 6 ) +#define FUNCT_SRAV ( 7 ) +#define FUNCT_JR ( 8 ) +#define FUNCT_JALR ( 9 ) +#define FUNCT_HLECALL ( 11 ) +#define FUNCT_SYSCALL ( 12 ) +#define FUNCT_BREAK ( 13 ) +#define FUNCT_MFHI ( 16 ) +#define FUNCT_MTHI ( 17 ) +#define FUNCT_MFLO ( 18 ) +#define FUNCT_MTLO ( 19 ) +#define FUNCT_MULT ( 24 ) +#define FUNCT_MULTU ( 25 ) +#define FUNCT_DIV ( 26 ) +#define FUNCT_DIVU ( 27 ) +#define FUNCT_ADD ( 32 ) +#define FUNCT_ADDU ( 33 ) +#define FUNCT_SUB ( 34 ) +#define FUNCT_SUBU ( 35 ) +#define FUNCT_AND ( 36 ) +#define FUNCT_OR ( 37 ) +#define FUNCT_XOR ( 38 ) +#define FUNCT_NOR ( 39 ) +#define FUNCT_SLT ( 42 ) +#define FUNCT_SLTU ( 43 ) + +/* OP_REGIMM */ +#define RT_BLTZ ( 0 ) +#define RT_BGEZ ( 1 ) +#define RT_BLTZAL ( 16 ) +#define RT_BGEZAL ( 17 ) + +/* OP_COP0/OP_COP1/OP_COP2 */ +#define RS_MFC ( 0 ) +#define RS_CFC ( 2 ) +#define RS_MTC ( 4 ) +#define RS_CTC ( 6 ) +#define RS_BC ( 8 ) + +/* RS_BC */ +#define RT_BCF ( 0 ) +#define RT_BCT ( 1 ) + +/* OP_COP0 */ +#define CF_RFE ( 16 ) + +#ifdef MAME_DEBUG +unsigned DasmMIPS(char *buff, unsigned _pc); +#endif + +#if (HAS_PSXCPU) +void psxcpu_get_info(mips_cpu_context *cpu, UINT32 state, union cpuinfo *info); +#endif + +mips_cpu_context *mips_alloc(void); +void mips_free (mips_cpu_context *cpu); + +void mips_init(mips_cpu_context *cpu); +void mips_exit(mips_cpu_context *cpu); +void mips_reset(mips_cpu_context *cpu, void *param ); +int mips_execute(mips_cpu_context *cpu, int cycles ); +void mips_set_info(mips_cpu_context *cpu, UINT32 state, union cpuinfo *info); +void mips_get_info(mips_cpu_context *cpu, UINT32 state, union cpuinfo *info); +int mips_execute( mips_cpu_context *cpu, int cycles ); +int mips_get_icount(mips_cpu_context *cpu); +void mips_set_icount(mips_cpu_context *cpu, int count); + +uint32 mips_get_cause(mips_cpu_context *cpu); +uint32 mips_get_status(mips_cpu_context *cpu); +void mips_set_status(mips_cpu_context *cpu, uint32 status); +uint32 mips_get_ePC(mips_cpu_context *cpu); + + +void psx_hw_init(mips_cpu_context *cpu); +void psx_hw_slice(mips_cpu_context *cpu); +void psx_hw_frame(mips_cpu_context *cpu); +void ps2_hw_slice(mips_cpu_context *cpu); +void ps2_hw_frame(mips_cpu_context *cpu); + +void mips_shorten_frame(mips_cpu_context *cpu); +uint32 psf2_load_file(mips_cpu_context *cpu, char *file, uint8 *buf, uint32 buflen); +uint32 psf2_load_elf(mips_cpu_context *cpu, uint8 *start, uint32 len); +void psx_hw_runcounters(mips_cpu_context *cpu); + + +void psx_bios_hle(mips_cpu_context *cpu, uint32 pc); +void psx_iop_call(mips_cpu_context *cpu, uint32 pc, uint32 callnum); +uint8 program_read_byte_32le(mips_cpu_context *cpu, offs_t address); +uint16 program_read_word_32le(mips_cpu_context *cpu, offs_t address); +uint32 program_read_dword_32le(mips_cpu_context *cpu, offs_t address); +void program_write_byte_32le(mips_cpu_context *cpu, offs_t address, uint8 data); +void program_write_word_32le(mips_cpu_context *cpu, offs_t address, uint16 data); +void program_write_dword_32le(mips_cpu_context *cpu, offs_t address, uint32 data); + +// SPU1 +void setlength(struct spu_state_s *spu, s32 stop, s32 fade); + +// SPU2 +void SPU2write(mips_cpu_context *cpu, unsigned long reg, unsigned short val); +unsigned short SPU2read(mips_cpu_context *cpu, unsigned long reg); +void SPU2readDMA4Mem(mips_cpu_context *cpu, uint32 usPSXMem,int iSize); +void SPU2writeDMA4Mem(mips_cpu_context *cpu, uint32 usPSXMem,int iSize); +void SPU2readDMA7Mem(mips_cpu_context *cpu, uint32 usPSXMem,int iSize); +void SPU2writeDMA7Mem(mips_cpu_context *cpu, uint32 usPSXMem,int iSize); +void SPU2interruptDMA4(mips_cpu_context *cpu); +void SPU2interruptDMA7(mips_cpu_context *cpu); + +#endif diff --git a/plugins/ao/eng_psf/psx_hw.c b/plugins/ao/eng_psf/psx_hw.c new file mode 100644 index 00000000..d81d59a9 --- /dev/null +++ b/plugins/ao/eng_psf/psx_hw.c @@ -0,0 +1,3505 @@ +/* + Audio Overload SDK - PSX and IOP hardware emulation + + Copyright (c) 2007 R. Belmont and Richard Bannister. + + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + psx_hw.c - Minimal PSX/IOP hardware glue/emulation/whatever + + supported: main RAM (2 MB, mirrored to fill an 8 MB space like on real HW) + DMA channel 4 (SPURAM) in both directions (including completion IRQ) + VBL IRQ + Root counters 2 and 3 including completion events and IRQs + Some BIOS services including exception handling (via HLE) + HLE emulation of IOP operating system, including multithreading + SPU(2), SPU(2)RAM (via PEOpS) + + + + Special notes: + PSF1 + - Chocobo's Dungeon 2 contains an illegal code sequence (patched) + + PSF2 + - Shadow Hearts assumes that the wave buffer alloc will go to 0x80060000 and the sequence buffer to 0x80170000. + Our memory management doesn't work out that way, so we have to (wait for it) cheese it. +*/ + +#include <stdio.h> +#include "ao.h" +#include "cpuintrf.h" +#include "psx.h" +#include "peops/spu.h" +#include "peops/regs.h" + +#define DEBUG_HLE_BIOS (0) // debug PS1 HLE BIOS +#define DEBUG_HLE_IOP (0) // debug PS2 IOP OS calls +#define DEBUG_UNK_RW (0) // debug unknown reads/writes +#define DEBUG_THREADING (0) // debug PS2 IOP threading + +extern int psf_refresh; +extern int psxcpu_verbose; + +#define MAX_FILE_SLOTS (32) + +static volatile int softcall_target = 0; +static int filestat[MAX_FILE_SLOTS]; +static uint8 *filedata[MAX_FILE_SLOTS]; +static uint32 filesize[MAX_FILE_SLOTS], filepos[MAX_FILE_SLOTS]; +uint32 psf2_get_loadaddr(void); +void psf2_set_loadaddr(uint32 new); +static void call_irq_routine(mips_cpu_context *cpu, uint32 routine, uint32 parameter); +static int intr_susp = 0; + +static uint64 sys_time; +static int timerexp = 0; + +typedef struct +{ + char name[10]; + uint32 dispatch; +} ExternLibEntries; + +static int32 iNumLibs; +static ExternLibEntries reglibs[32]; + +typedef struct +{ + uint32 type; + uint32 value; + uint32 param; + int inUse; +} EventFlag; + +static int32 iNumFlags; +static EventFlag evflags[32]; + +typedef struct +{ + uint32 attr; + uint32 option; + int32 init; + int32 current; + int32 max; + int32 threadsWaiting; + int32 inuse; +} Semaphore; + +#define SEMA_MAX (64) + +static int32 iNumSema; +static Semaphore semaphores[SEMA_MAX]; + +// thread states +enum +{ + TS_RUNNING = 0, // now running + TS_READY, // ready to run + TS_WAITEVFLAG, // waiting on an event flag + TS_WAITSEMA, // waiting on a semaphore + TS_WAITDELAY, // waiting on a time delay + TS_SLEEPING, // sleeping + TS_CREATED, // newly created, hasn't run yet + + TS_MAXSTATE +}; + +typedef struct +{ + int32 iState; // state of thread + + uint32 flags; // flags + uint32 routine; // start of code for the thread + uint32 stackloc; // stack location in IOP RAM + uint32 stacksize; // stack size + uint32 refCon; // user value passed in at CreateThread time + + uint32 waitparm; // what we're waiting on if in one the TS_WAIT* states + + uint32 save_regs[37]; // CPU registers belonging to this thread +} Thread; + +static int32 iNumThreads, iCurThread; +static Thread threads[32]; + +#if DEBUG_THREADING +static char *_ThreadStateNames[TS_MAXSTATE] = { "RUNNING", "READY", "WAITEVFLAG", "WAITSEMA", "WAITDELAY", "SLEEPING", "CREATED" }; +#endif + +#if DEBUG_HLE_IOP +static char *seek_types[3] = { "SEEK_SET", "SEEK_CUR", "SEEK_END" }; +#endif + +typedef struct +{ + int32 iActive; + uint32 count; + uint32 target; + uint32 source; + uint32 prescale; + uint32 handler; + uint32 hparam; + uint32 mode; +} IOPTimer; + +static IOPTimer iop_timers[8]; +static int32 iNumTimers; + +typedef struct +{ + uint32 count; + uint32 mode; + uint32 target; + uint32 sysclock; +} Counter; + +static Counter root_cnts[3]; // 3 of the bastards + +#define CLOCK_DIV (8) // 33 MHz / this = what we run the R3000 at to keep the CPU usage not insane + +// counter modes +#define RC_EN (0x0001) // halt +#define RC_RESET (0x0008) // automatically wrap +#define RC_IQ1 (0x0010) // IRQ when target reached +#define RC_IQ2 (0x0040) // IRQ when target reached (pSX treats same as IQ1?) +#define RC_CLC (0x0100) // counter uses direct system clock +#define RC_DIV8 (0x0200) // (counter 2 only) system clock/8 + +typedef struct +{ + uint32 desc; + int32 status; + int32 mode; + uint32 fhandler; +} EvtCtrlBlk[32]; + +static EvtCtrlBlk *Event; +static EvtCtrlBlk *CounterEvent; + +// Sony event states +#define EvStUNUSED 0x0000 +#define EvStWAIT 0x1000 +#define EvStACTIVE 0x2000 +#define EvStALREADY 0x4000 + +// Sony event modes +#define EvMdINTR 0x1000 +#define EvMdNOINTR 0x2000 + +static uint32 spu_delay, dma_icr, irq_data, irq_mask, dma_timer, WAI; +static uint32 dma4_madr, dma4_bcr, dma4_chcr, dma4_delay; +static uint32 dma7_madr, dma7_bcr, dma7_chcr, dma7_delay; +static uint32 dma4_cb, dma7_cb, dma4_fval, dma4_flag, dma7_fval, dma7_flag; +static uint32 irq9_cb, irq9_fval, irq9_flag; + +// take a snapshot of the CPU state for a thread +static void FreezeThread(mips_cpu_context *cpu, int32 iThread, int flag) +{ + int i; + union cpuinfo mipsinfo; + + #if DEBUG_THREADING +// printf("IOP: FreezeThread(%d)\n", iThread); + #endif + + for (i = 0; i < 32; i++) + { + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_R0 + i, &mipsinfo); + threads[iThread].save_regs[i] = mipsinfo.i; + } + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_HI, &mipsinfo); + threads[iThread].save_regs[32] = mipsinfo.i; + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_LO, &mipsinfo); + threads[iThread].save_regs[33] = mipsinfo.i; + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_DELAYV, &mipsinfo); + threads[iThread].save_regs[35] = mipsinfo.i; + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_DELAYR, &mipsinfo); + threads[iThread].save_regs[36] = mipsinfo.i; + + + // if a thread is freezing itself due to a IOP syscall, we must save the RA as the PC + // to come back to or else the syscall will recurse + if (flag) + { + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo); + } + else + { + mips_get_info(cpu, CPUINFO_INT_PC, &mipsinfo); + } + threads[iThread].save_regs[34] = mipsinfo.i; + + #if DEBUG_THREADING + { + char buffer[256]; + + DasmMIPS(buffer, mipsinfo.i, &psx_ram[(mipsinfo.i & 0x7fffffff)/4]); + + printf("IOP: FreezeThread(%d) => %08x [%s]\n", iThread, threads[iThread].save_regs[34], buffer); + } + #endif + + // if thread was running, now it's ready + if (threads[iThread].iState == TS_RUNNING) + { + threads[iThread].iState = TS_READY; + } +} + +// restore the CPU state from a thread's snapshot +static void ThawThread(mips_cpu_context *cpu, int32 iThread) +{ + int i; + union cpuinfo mipsinfo; + + // the first time a thread is put on the CPU, + // some special setup is required + if (threads[iThread].iState == TS_CREATED) + { + // PC = starting routine + threads[iThread].save_regs[34] = threads[iThread].routine-4; // compensate for weird delay slot effects + // SP = thread's stack area + threads[iThread].save_regs[29] = (threads[iThread].stackloc + threads[iThread].stacksize) - 16; + threads[iThread].save_regs[29] |= 0x80000000; + + threads[iThread].save_regs[35] = threads[iThread].save_regs[36] = 0; + + #if DEBUG_THREADING +// printf("IOP: Initial setup for thread %d => PC %x SP %x\n", iThread, threads[iThread].save_regs[34]+4, threads[iThread].save_regs[29]); + #endif + } + + #if DEBUG_THREADING + { + char buffer[256]; + + mips_get_info(CPUINFO_INT_PC, &mipsinfo); + DasmMIPS(buffer, mipsinfo.i, &psx_ram[(mipsinfo.i & 0x7fffffff)/4]); + + printf("IOP: ThawThread(%d) => %08x [%s] (wake %d)\n", iThread, threads[iThread].save_regs[34], buffer, wakecount); + } + #endif + + for (i = 0; i < 32; i++) + { + mipsinfo.i = threads[iThread].save_regs[i]; + mips_set_info(cpu, CPUINFO_INT_REGISTER + MIPS_R0 + i, &mipsinfo); + } + + mipsinfo.i = threads[iThread].save_regs[32]; + mips_set_info(cpu, CPUINFO_INT_REGISTER + MIPS_HI, &mipsinfo); + mipsinfo.i = threads[iThread].save_regs[33]; + mips_set_info(cpu, CPUINFO_INT_REGISTER + MIPS_LO, &mipsinfo); + mipsinfo.i = threads[iThread].save_regs[34]; + mips_set_info(cpu, CPUINFO_INT_PC, &mipsinfo); + mipsinfo.i = threads[iThread].save_regs[35]; + mips_set_info(cpu, CPUINFO_INT_REGISTER + MIPS_DELAYV, &mipsinfo); + mipsinfo.i = threads[iThread].save_regs[36]; + mips_set_info(cpu, CPUINFO_INT_REGISTER + MIPS_DELAYR, &mipsinfo); + + threads[iThread].iState = TS_RUNNING; +} + +// find a new thread to run +static void ps2_reschedule(mips_cpu_context *cpu) +{ + int i, starti, iNextThread; + + iNextThread = -1; + + // see if any thread other than the current one is ready to run + i = iCurThread+1; + if (i >= iNumThreads) + { + i = 0; + } + + starti = i; + + // starting with the next thread after this one, + // see who wants to run + while (i < iNumThreads) + { + if (i != iCurThread) + { + if (threads[i].iState == TS_READY) + { + iNextThread = i; + break; + } + } + + i++; + } + + // if we started above thread 0 and didn't pick one, + // go around and try from zero + if ((starti > 0) && (iNextThread == -1)) + { + for (i = 0; i < iNumThreads; i++) + { + if (i != iCurThread) + { + if (threads[i].iState == TS_READY) + { + iNextThread = i; + break; + } + } + } + } + + if (iNextThread != -1) + { + #if DEBUG_THREADING + for (i = 0; i < iNumThreads; i++) + { + printf("Thread %02d: %s\n", i, _ThreadStateNames[threads[i].iState]); + } + #endif + + if (iCurThread != -1) + { + FreezeThread(cpu, iCurThread, 0); + } + ThawThread(cpu, iNextThread); + iCurThread = iNextThread; + threads[iCurThread].iState = TS_RUNNING; + } + else + { + // no thread to switch to, is the current one still running? + if (iCurThread != -1) + { + if (threads[iCurThread].iState != TS_RUNNING) + { + #if DEBUG_THREADING + printf("IOP: no threads to run\n"); + + for (i = 0; i < iNumThreads; i++) + { + printf("Thread %02d: %s\n", i, _ThreadStateNames[threads[i].iState]); + } + #endif + + mips_shorten_frame(cpu); // kill the CPU + iCurThread = -1; // no threads are active + } + } + else + { + mips_shorten_frame(cpu); // kill the CPU + iCurThread = -1; // no threads are active + } + } +} + +static void psx_irq_update(mips_cpu_context *cpu) +{ + union cpuinfo mipsinfo; + + if ((irq_data & irq_mask) != 0) + { // assert the line + WAI = 0; + mipsinfo.i = ASSERT_LINE; + mips_set_info( cpu, CPUINFO_INT_INPUT_STATE + MIPS_IRQ0, &mipsinfo ); + } + else + { + // clear the line + mipsinfo.i = CLEAR_LINE; + mips_set_info( cpu, CPUINFO_INT_INPUT_STATE + MIPS_IRQ0, &mipsinfo ); + } +} + +void psx_irq_set(mips_cpu_context *cpu, uint32 irq) +{ + irq_data |= irq; + + psx_irq_update(cpu); +} + +static uint32 gpu_stat = 0; + +uint32 psx_hw_read(mips_cpu_context *cpu, offs_t offset, uint32 mem_mask) +{ + if (offset >= 0x00000000 && offset <= 0x007fffff) + { + offset &= 0x1fffff; + return LE32(cpu->psx_ram[offset>>2]); + } + + if (offset >= 0x80000000 && offset <= 0x807fffff) + { + offset &= 0x1fffff; + return LE32(cpu->psx_ram[offset>>2]); + } + + if (offset == 0xbfc00180 || offset == 0xbfc00184) // exception vector + { + return FUNCT_HLECALL; + } + + if (offset == 0x1f801014) + { + return spu_delay; + } + + if (offset == 0xbf801014) + { + return spu_delay; + } + + if (offset == 0x1f801814) + { + gpu_stat ^= 0xffffffff; + return gpu_stat; + } + + if (offset >= 0x1f801c00 && offset <= 0x1f801dff) + { + if ((mem_mask == 0xffff0000) || (mem_mask == 0xffffff00)) + { + return SPUreadRegister(cpu, offset) & ~mem_mask; + } + else if (mem_mask == 0x0000ffff) + { + return SPUreadRegister(cpu, offset)<<16; + } + else printf("SPU: read unknown mask %08x\n", mem_mask); + } + + if (offset >= 0xbf900000 && offset <= 0xbf9007ff) + { + if ((mem_mask == 0xffff0000) || (mem_mask == 0xffffff00)) + { + return SPU2read(cpu, offset) & ~mem_mask; + } + else if (mem_mask == 0x0000ffff) + { + return SPU2read(cpu, offset)<<16; + } + else if (mem_mask == 0) + { + return SPU2read(cpu, offset) | SPU2read(cpu, offset+2)<<16; + } + else printf("SPU2: read unknown mask %08x\n", mem_mask); + } + + if (offset >= 0x1f801100 && offset <= 0x1f801128) + { + int cnt = (offset>>4) & 0xf; + + switch (offset & 0xf) + { + case 0: +// printf("RC: read counter %d count = %x\n", cnt, root_cnts[cnt].count); + return root_cnts[cnt].count; + break; + case 4: +// printf("RC: read counter %d mode\n", cnt); + return root_cnts[cnt].mode; + break; + case 8: +// printf("RC: read counter %d target\n", cnt); + return root_cnts[cnt].target; + break; + } + + return 0; + } + + if (offset == 0x1f8010f4) + { + return dma_icr; + } + else if (offset == 0x1f801070) + { +// printf("Read IRQ_data %x (mask %08x)\n", irq_data, mem_mask); + return irq_data; + } + else if (offset == 0x1f801074) + { + return irq_mask; + } + +/* if (offset == 0xbf801508) + { + return dma7_bcr; + }*/ + + if (offset == 0xbf920344) + { + return 0x80808080; + } + + #if DEBUG_UNK_RW + { + union cpuinfo mipsinfo; + + mips_get_info(cpu, CPUINFO_INT_PC, &mipsinfo); + printf("Unknown read: %08x, mask %08x (PC=%x)\n", offset&~3, mem_mask, mipsinfo.i); + } + #endif + return 0; +} + +static void psx_dma4(mips_cpu_context *cpu, uint32 madr, uint32 bcr, uint32 chcr) +{ + if (chcr == 0x01000201) // cpu to SPU + { +// printf("DMA4: RAM %08x to SPU\n", madr); + bcr = (bcr>>16) * (bcr & 0xffff) * 2; + SPUwriteDMAMem(cpu, madr&0x1fffff, bcr); + } + else + { +// printf("DMA4: SPU to RAM %08x\n", madr); + bcr = (bcr>>16) * (bcr & 0xffff) * 2; + SPUreadDMAMem(cpu, madr&0x1fffff, bcr); + } +} + +static void ps2_dma4(mips_cpu_context *cpu, uint32 madr, uint32 bcr, uint32 chcr) +{ + if (chcr == 0x01000201) // cpu to SPU2 + { + #if DEBUG_HLE_IOP + printf("DMA4: RAM %08x to SPU2\n", madr); + #endif + bcr = (bcr>>16) * (bcr & 0xffff) * 4; + SPU2writeDMA4Mem(cpu, madr&0x1fffff, bcr); + } + else + { + #if DEBUG_HLE_IOP + printf("DMA4: SPU2 to RAM %08x\n", madr); + #endif + bcr = (bcr>>16) * (bcr & 0xffff) * 4; + SPU2readDMA4Mem(cpu, madr&0x1fffff, bcr); + } + + dma4_delay = 80; +} + +static void ps2_dma7(mips_cpu_context *cpu, uint32 madr, uint32 bcr, uint32 chcr) +{ + if ((chcr == 0x01000201) || (chcr == 0x00100010) || (chcr == 0x000f0010) || (chcr == 0x00010010)) // cpu to SPU2 + { + #if DEBUG_HLE_IOP + printf("DMA7: RAM %08x to SPU2\n", madr); + #endif + bcr = (bcr>>16) * (bcr & 0xffff) * 4; + SPU2writeDMA7Mem(cpu, madr&0x1fffff, bcr); + } + else + { + #if DEBUG_HLE_IOP + printf("DMA7: SPU2 to RAM %08x\n", madr); + #endif + bcr = (bcr>>16) * (bcr & 0xffff) * 4; +// SPU2readDMA7Mem(madr&0x1fffff, bcr); + } + + dma7_delay = 80; +} + +void psx_hw_write(mips_cpu_context *cpu, offs_t offset, uint32 data, uint32 mem_mask) +{ + union cpuinfo mipsinfo; + + if (offset >= 0x00000000 && offset <= 0x007fffff) + { + offset &= 0x1fffff; +// if (offset < 0x10000) printf("Write %x to kernel @ %x\n", data, offset); + + mips_get_info(cpu, CPUINFO_INT_PC, &mipsinfo); + + cpu->psx_ram[offset>>2] &= LE32(mem_mask); + cpu->psx_ram[offset>>2] |= LE32(data); + return; + } + + if (offset >= 0x80000000 && offset <= 0x807fffff) + { + offset &= 0x1fffff; +// if (offset < 0x10000) printf("Write %x to kernel @ %x\n", data, offset); + mips_get_info(cpu, CPUINFO_INT_PC, &mipsinfo); + cpu->psx_ram[offset>>2] &= LE32(mem_mask); + cpu->psx_ram[offset>>2] |= LE32(data); + return; + } + + if (offset == 0x1f801014 || offset == 0xbf801014) + { + spu_delay &= mem_mask; + spu_delay |= data; + return; + } + + if (offset >= 0x1f801c00 && offset <= 0x1f801dff) + { + // printf("SPU2 wrote %x to SPU1 address %x!\n", data, offset); + if (mem_mask == 0xffff0000) + { + SPUwriteRegister(cpu, offset, data); + return; + } + else if (mem_mask == 0x0000ffff) + { + SPUwriteRegister(cpu, offset, data>>16); + return; + } + else printf("SPU: write unknown mask %08x\n", mem_mask); + } + + if (offset >= 0xbf900000 && offset <= 0xbf9007ff) + { + if (mem_mask == 0xffff0000) + { + SPU2write(cpu, offset, data); + return; + } + else if (mem_mask == 0x0000ffff) + { + SPU2write(cpu, offset, data>>16); + return; + } + else if (mem_mask == 0) + { + SPU2write(cpu, offset, data & 0xffff); + SPU2write(cpu, offset+2, data>>16); + return; + } + else printf("SPU2: write unknown mask %08x\n", mem_mask); + } + + if (offset >= 0x1f801100 && offset <= 0x1f801128) + { + int cnt = (offset>>4) & 0xf; + + switch (offset & 0xf) + { + case 0: + root_cnts[cnt].count = data; +// printf("RC: counter %d count = %x\n", cnt, data); + break; + case 4: + root_cnts[cnt].mode = data; +// printf("RC: counter %d mode = %x\n", cnt, data); + break; + case 8: + root_cnts[cnt].target = data; +// printf("RC: counter %d target = %x\n", cnt, data); + break; + } + + return; + } + + // DMA4 + if (offset == 0x1f8010c0) + { + dma4_madr = data; + return; + } + else if (offset == 0x1f8010c4) + { + dma4_bcr = data; + return; + } + else if (offset == 0x1f8010c8) + { + dma4_chcr = data; + psx_dma4(cpu, dma4_madr, dma4_bcr, dma4_chcr); + + if (dma_icr & (1 << (16+4))) + { + dma_timer = 3; + } + return; + } + else if (offset == 0x1f8010f4) + { + dma_icr = ( dma_icr & mem_mask ) | + ( ~mem_mask & 0x80000000 & dma_icr) | + ( ~data & ~mem_mask & 0x7f000000 & dma_icr) | + ( data & ~mem_mask & 0x00ffffff); + + if ((dma_icr & 0x7f000000) != 0) + { + dma_icr &= ~0x80000000; + } + + return; + } + else if (offset == 0x1f801070) + { + irq_data = (irq_data & mem_mask) | (irq_data & irq_mask & data); + psx_irq_update(cpu); + return; + } + else if (offset == 0x1f801074) + { + irq_mask &= mem_mask; + irq_mask |= data; + psx_irq_update(cpu); + return; + } + + // PS2 DMA4 + if (offset == 0xbf8010c0) + { + dma4_madr = data; + return; + } + else if (offset == 0xbf8010c8) + { + dma4_chcr = data; + ps2_dma4(cpu, dma4_madr, dma4_bcr, dma4_chcr); + + if (dma_icr & (1 << (16+4))) + { + dma_timer = 3; + } + return; + } + + if (offset == 0xbf8010c4 || offset == 0xbf8010c6) + { + dma4_bcr &= mem_mask; + dma4_bcr |= data; + return; + } + + // PS2 DMA7 + if (offset == 0xbf801500) + { + dma7_madr = data; + return; + } + else if (offset == 0xbf801504) + { + dma7_chcr = data; + ps2_dma7(cpu, dma7_madr, dma7_bcr, dma7_chcr); + return; + } + + if (offset == 0xbf801508 || offset == 0xbf80150a) + { + dma7_bcr &= mem_mask; + dma7_bcr |= data; + return; + } + + #if DEBUG_UNK_RW + { + union cpuinfo mipsinfo; + + mips_get_info(CPUINFO_INT_PC, &mipsinfo); + printf("Unknown write: %08x to %08x, mask %08x (PC=%x)\n", data, offset&~3, mem_mask, mipsinfo.i); + } + #endif +} + +// called per sample, 1/44100th of a second (768 clock cycles) +void psx_hw_slice(mips_cpu_context *cpu) +{ + psx_hw_runcounters(cpu); + + if (!WAI) + mips_execute(cpu, 768/CLOCK_DIV); + + if (dma_timer) + { + dma_timer--; + if (dma_timer == 0) + { + dma_icr |= (1 << (24+4)); + psx_irq_set(cpu, 0x0008); + } + } +} + +void ps2_hw_slice(mips_cpu_context *cpu) +{ + int i = 0; + + timerexp = 0; + psx_hw_runcounters(cpu); + + if (iCurThread != -1) + { + mips_execute(cpu, 836/CLOCK_DIV); + } + else // no thread, don't run CPU, just update counters + { + if (timerexp) + { + ps2_reschedule(cpu); + + if (iCurThread != -1) + { + mips_execute(cpu, (836/CLOCK_DIV)-i); + i = (836/CLOCK_DIV); + } + } + } +} + +static int fcnt = 0; + +void psx_hw_frame(mips_cpu_context *cpu) +{ + if (psf_refresh == 50) + { + fcnt++;; + + if (fcnt < 6) + { + psx_irq_set(cpu, 1); + } + else + { + fcnt = 0; + } + } + else // NTSC + { + psx_irq_set(cpu, 1); + } +} + +void ps2_hw_frame(mips_cpu_context *cpu) +{ + ps2_reschedule(cpu); +} + +// BIOS HLE + +// heap block struct offsets +enum +{ + BLK_STAT = 0, + BLK_SIZE = 4, + BLK_FD = 8, + BLK_BK = 12 +}; + +static uint32 heap_addr, entry_int = 0; + +static uint32 irq_regs[37]; + +static int irq_mutex = 0; + +static void call_irq_routine(mips_cpu_context *cpu, uint32 routine, uint32 parameter) +{ + int j, oldICount; + union cpuinfo mipsinfo; + + if (!irq_mutex) + { + irq_mutex = 1; + } + else + { + printf("IOP: ERROR! IRQ reentry!\n"); + return; + } + + // save regs for IRQ + for (j = 0; j < 32; j++) + { + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_R0 + j, &mipsinfo); + irq_regs[j] = mipsinfo.i; + } + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_HI, &mipsinfo); + irq_regs[32] = mipsinfo.i; + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_LO, &mipsinfo); + irq_regs[33] = mipsinfo.i; + mips_get_info(cpu, CPUINFO_INT_PC, &mipsinfo); + irq_regs[34] = mipsinfo.i; + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_DELAYV, &mipsinfo); + irq_regs[35] = mipsinfo.i; + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_DELAYR, &mipsinfo); + irq_regs[36] = mipsinfo.i; + + // PC = timer handler routine + mipsinfo.i = routine; + mips_set_info(cpu, CPUINFO_INT_PC, &mipsinfo); + + // parameter in a0 + mipsinfo.i = parameter; + mips_set_info(cpu, CPUINFO_INT_REGISTER + MIPS_R4, &mipsinfo); + + // RA = a trap address we can set + mipsinfo.i = 0x80001000; + mips_set_info(cpu, CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo); + + // make sure we're set + cpu->psx_ram[0x1000/4] = LE32(FUNCT_HLECALL); + + softcall_target = 0; + oldICount = mips_get_icount(cpu); + while (!softcall_target) + { + mips_execute(cpu, 10); + } + mips_set_icount(cpu,oldICount); + + // restore IRQ regs + for (j = 0; j < 32; j++) + { + mipsinfo.i = irq_regs[j]; + mips_set_info(cpu, CPUINFO_INT_REGISTER + MIPS_R0 + j, &mipsinfo); + } + + mipsinfo.i = irq_regs[32]; + mips_set_info(cpu, CPUINFO_INT_REGISTER + MIPS_HI, &mipsinfo); + mipsinfo.i = irq_regs[33]; + mips_set_info(cpu, CPUINFO_INT_REGISTER + MIPS_LO, &mipsinfo); + mipsinfo.i = irq_regs[34]; + mips_set_info(cpu, CPUINFO_INT_PC, &mipsinfo); + mipsinfo.i = irq_regs[35]; + mips_set_info(cpu, CPUINFO_INT_REGISTER + MIPS_DELAYV, &mipsinfo); + mipsinfo.i = irq_regs[36]; + mips_set_info(cpu, CPUINFO_INT_REGISTER + MIPS_DELAYR, &mipsinfo); + + irq_mutex = 0; +} + +void psx_bios_exception(mips_cpu_context *cpu, uint32 pc) +{ + uint32 a0, status; + union cpuinfo mipsinfo; + int i, oldICount; + +// printf("bios_exception: cause %x\n", mips_get_cause() & 0x3c); + + // get a0 + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_R4, &mipsinfo); + a0 = mipsinfo.i; + + switch (mips_get_cause(cpu) & 0x3c) + { + case 0: // IRQ +// printf("IRQ: %x, mask %x\n", irq_data, irq_mask); + // save all regs + for (i = 0; i < 32; i++) + { + mips_get_info(cpu,CPUINFO_INT_REGISTER + MIPS_R0 + i, &mipsinfo); + irq_regs[i] = mipsinfo.i; + } + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_HI, &mipsinfo); + irq_regs[32] = mipsinfo.i; + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_LO, &mipsinfo); + irq_regs[33] = mipsinfo.i; + + // check BIOS-driven interrupts + if (irq_data & 1) // VSync + { + if (CounterEvent[3][1].status == LE32(EvStACTIVE)) + { + // run the handler + mipsinfo.i = LE32(CounterEvent[3][1].fhandler); +// printf("Cause = %x, ePC = %x\n", mips_get_cause(), mips_get_ePC()); +// printf("VBL running handler @ %x\n", mipsinfo.i); + mips_set_info(cpu,CPUINFO_INT_PC, &mipsinfo); + mipsinfo.i = 0x80001000; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo); + + // make sure we're set + cpu->psx_ram[0x1000/4] = LE32(FUNCT_HLECALL); + + softcall_target = 0; + oldICount = mips_get_icount(cpu); + while (!softcall_target) + { + mips_execute(cpu, 10); + } + mips_set_icount(cpu, oldICount); + +// printf("Exiting softcall handler\n"); + + irq_data &= ~1; // clear the VBL IRQ if we handled it + } + } + else if (irq_data & 0x70) // root counters + { + for (i = 0; i < 3; i++) + { + if (irq_data & (1 << (i+4))) + { + if (CounterEvent[i][1].status == LE32(EvStACTIVE)) + { + // run the handler + mipsinfo.i = LE32(CounterEvent[i][1].fhandler); +// printf("Cause = %x, ePC = %x\n", mips_get_cause(), mips_get_ePC()); +// printf("Counter %d running handler @ %x\n", i, mipsinfo.i); + mips_set_info(cpu,CPUINFO_INT_PC, &mipsinfo); + mipsinfo.i = 0x80001000; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo); + + // make sure we're set + cpu->psx_ram[0x1000/4] = LE32(FUNCT_HLECALL); + + softcall_target = 0; + oldICount = mips_get_icount(cpu); + while (!softcall_target) + { + mips_execute(cpu, 10); + } + mips_set_icount(cpu,oldICount); + +// printf("Exiting softcall handler\n"); + irq_data &= ~(1 << (i+4)); + } + else + { +// printf("CEvt %d not active\n", i); + } + } + } + } + + if (entry_int) + { + psx_hw_write(cpu, 0x1f801070, 0xffffffff, 0); + + a0 = entry_int; + +// printf("taking entry_int\n"); + + // RA (and PC) + mipsinfo.i = LE32(cpu->psx_ram[((a0&0x1fffff)+0)/4]); + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo); + mips_set_info(cpu,CPUINFO_INT_PC, &mipsinfo); + // SP + mipsinfo.i = LE32(cpu->psx_ram[((a0&0x1fffff)+4)/4]); + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R29, &mipsinfo); + // FP + mipsinfo.i = LE32(cpu->psx_ram[((a0&0x1fffff)+8)/4]); + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R30, &mipsinfo); + + // S0-S7 are next + for (i = 0; i < 8; i++) + { + mipsinfo.i = LE32(cpu->psx_ram[((a0&0x1fffff)+12+(i*4))/4]); + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R16 + i, &mipsinfo); + } + + // GP + mipsinfo.i = LE32(cpu->psx_ram[((a0&0x1fffff)+44)/4]); + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R28, &mipsinfo); + + // v0 = 1 + mipsinfo.i = 1; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + } + else + { + psx_hw_write(cpu, 0x1f801070, 0, 0xffff0000); + + // note: the entry_int won't be bailing us out here, so do it ourselves + for (i = 0; i < 32; i++) + { + mipsinfo.i = irq_regs[i]; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R0 + i, &mipsinfo); + } + + mipsinfo.i = irq_regs[32]; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_HI, &mipsinfo); + mipsinfo.i = irq_regs[33]; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_LO, &mipsinfo); + mipsinfo.i = mips_get_ePC(cpu); + mips_set_info(cpu,CPUINFO_INT_PC, &mipsinfo); + + status = mips_get_status(cpu); + status = (status & 0xfffffff0) | ((status & 0x3c)>>2); + mips_set_status(cpu, status); + } + break; + + case 0x20: // syscall + // syscall always farks with the status, so get it now + status = mips_get_status(cpu); + + switch (a0) + { + case 1: // EnterCritical + #if DEBUG_HLE_BIOS + printf("HLEBIOS: EnterCritical\n"); + #endif + status &= ~0x0404; + break; + + case 2: // ExitCritical + #if DEBUG_HLE_BIOS + printf("HLEBIOS: ExitCritical\n"); + #endif + status |= 0x0404; + break; + + default: + #if DEBUG_HLE_BIOS + printf("HLEBIOS: Unknown syscall %x\n", a0); + #endif + break; + } + + // PC = ePC + 4 + mipsinfo.i = mips_get_ePC(cpu) + 4; + mips_set_info(cpu,CPUINFO_INT_PC, &mipsinfo); + + // and update the status accordingly + status = (status & 0xfffffff0) | ((status & 0x3c)>>2); + mips_set_status(cpu, status); + break; + + default: + #if DEBUG_HLE_BIOS + printf("HLEBIOS: Unknown exception %x\n", mips_get_cause()); + #endif + break; + } +} + +static uint32 calc_ev(uint32 a0) +{ + uint32 ev; + + ev = (a0 >> 24) & 0xf; + if (ev == 0xf) + { + ev = 0x5; + } + ev *= 32; + ev += (a0 & 0x1f); + + return ev; +} + +static uint32 calc_spec(uint32 a1) +{ + uint32 spec = 0; + int i; + + if (a1 == 0x301) + { + spec = 16; + } + else if (a1 == 0x302) + { + spec = 17; + } + else + { + for (i = 0; i < 16; i++) + { + if (a1 & (1<<i)) + { + spec = i; + break; + } + } + } + + return spec; +} + +void psx_hw_init(mips_cpu_context *cpu) +{ + timerexp = 0; + + memset(filestat, 0, sizeof(filestat)); + memset(filedata, 0, sizeof(filedata)); + + dma4_cb = dma7_cb = 0; + + sys_time = 0; + + // clear registered libraries table + memset(reglibs, 0, sizeof(reglibs)); + iNumLibs = 0; + + memset(evflags, 0, sizeof(evflags)); + iNumFlags = 0; + + memset(threads, 0, sizeof(threads)); + iNumThreads = 1; // we always have at least one thread + + memset(semaphores, 0, sizeof(semaphores)); + iNumSema = 0; + + // set the initial thread to "RUNNING" + threads[0].iState = TS_RUNNING; + iCurThread = 0; + + memset(iop_timers, 0, sizeof(iop_timers)); + iNumTimers = 0; + + // set PS1 BIOS HLE breakpoints + cpu->psx_ram[0xa0/4] = LE32(FUNCT_HLECALL); + cpu->psx_ram[0xb0/4] = LE32(FUNCT_HLECALL); + cpu->psx_ram[0xc0/4] = LE32(FUNCT_HLECALL); + + Event = (EvtCtrlBlk *)&cpu->psx_ram[0x1000/4]; + CounterEvent = (Event + (32*2)); + + dma_icr = 0; + spu_delay = 0; + irq_data = 0; + irq_mask = 0; + softcall_target = 0; + gpu_stat = 0; + dma4_madr = dma4_bcr = dma4_chcr = 0; + heap_addr = 0; + entry_int = 0; + + WAI = 0; + + root_cnts[0].mode = RC_EN; + root_cnts[1].mode = RC_EN; + root_cnts[2].mode = RC_EN; + root_cnts[0].sysclock = 0; + root_cnts[1].sysclock = 0; + root_cnts[2].sysclock = 0; +} + +void psx_bios_hle(mips_cpu_context *cpu, uint32 pc) +{ + uint32 subcall, status; + union cpuinfo mipsinfo; + uint32 a0, a1, a2, a3; + int i; + + if ((pc == 0) || (pc == 0x80000000)) // IOP "null" state + { + #if DEBUG_HLE_IOP + printf("IOP 'null' state\n"); + #endif +// ao_song_done = 1; + return; + } + + if (pc == 0xbfc00180 || pc == 0xbfc00184) // exception, not BIOS call + { + psx_bios_exception(cpu, pc); + return; + } + + if (pc == 0x80001000) + { +// printf("hit softcall target\n"); + softcall_target = 1; + return; + } + + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_R9, &mipsinfo); + + subcall = mipsinfo.i & 0xff; + + // most calls have a0/a1 as parameters, so prefetch them + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_R4, &mipsinfo); + a0 = mipsinfo.i; + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_R5, &mipsinfo); + a1 = mipsinfo.i; + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_R6, &mipsinfo); + a2 = mipsinfo.i; + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_R7, &mipsinfo); + a3 = mipsinfo.i; + +// mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo); +// printf("HLEBIOS: return is %08x\n", mipsinfo.i); + + switch (pc) + { + case 0xa0: // a0 syscalls + switch (subcall) + { + case 0x13: // setjmp + // RA + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo); + cpu->psx_ram[((a0&0x1fffff)+0)/4] = LE32(mipsinfo.i); + #if DEBUG_HLE_BIOS + printf("HLEBIOS: setjmp(%08x) => PC %08x\n", a0, mipsinfo.i); + #endif + // SP + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_R29, &mipsinfo); + cpu->psx_ram[((a0&0x1fffff)+4)/4] = LE32(mipsinfo.i); + // FP + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_R30, &mipsinfo); + cpu->psx_ram[((a0&0x1fffff)+8)/4] = LE32(mipsinfo.i); + + // S0-S7 are next + for (i = 0; i < 8; i++) + { + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_R16 + i, &mipsinfo); + cpu->psx_ram[((a0&0x1fffff)+12+(i*4))/4] = LE32(mipsinfo.i); + } + + // GP + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_R28, &mipsinfo); + cpu->psx_ram[((a0&0x1fffff)+44)/4] = LE32(mipsinfo.i); + + // v0 = 0 + mipsinfo.i = 0; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + case 0x18: // strncmp + { + uint8 *dst, *src; + + #if DEBUG_HLE_BIOS + printf("HLEBIOS: strncmp(%08x, %08x, %d)\n", a0, a1, a2); + #endif + + dst = (uint8 *)cpu->psx_ram; + src = (uint8 *)cpu->psx_ram; + dst += (a0 & 0x1fffff); + src += (a1 & 0x1fffff); + + // v0 = result + mipsinfo.i = strncmp((char *)dst, (char *)src, a2); + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + } + break; + + case 0x19: // strcpy + { + uint8 *dst, *src; + + #if DEBUG_HLE_BIOS + printf("HLEBIOS: strcpy(%08x, %08x)\n", a0, a1); + #endif + + dst = (uint8 *)cpu->psx_ram; + src = (uint8 *)cpu->psx_ram; + dst += (a0 & 0x1fffff); + src += (a1 & 0x1fffff); + + while (*src) + { + *dst = *src; + dst++; + src++; + } + + // v0 = a0 + mipsinfo.i = a0; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + } + break; + + case 0x28: // bzero + { + uint8 *dst; + + #if DEBUG_HLE_BIOS + printf("HLEBIOS: bzero(%08x, %08x)\n", a0, a1); + #endif + + dst = (uint8 *)cpu->psx_ram; + dst += (a0 & 0x1fffff); + memset(dst, 0, a1); + } + break; + + case 0x2a: // memcpy + { + uint8 *dst, *src; + + #if DEBUG_HLE_BIOS + printf("HLEBIOS: memcpy(%08x, %08x, %08x)\n", a0, a1, a2); + #endif + + dst = (uint8 *)cpu->psx_ram; + src = (uint8 *)cpu->psx_ram; + dst += (a0 & 0x1fffff); + src += (a1 & 0x1fffff); + + while (a2) + { + *dst = *src; + dst++; + src++; + a2--; + } + + // v0 = a0 + mipsinfo.i = a0; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + } + break; + + case 0x2b: // memset + { + uint8 *dst; + + #if DEBUG_HLE_BIOS + printf("HLEBIOS: memset(%08x, %08x, %08x)\n", a0, a1, a2); + #endif + + dst = (uint8 *)cpu->psx_ram; + dst += (a0 & 0x1fffff); + + while (a2) + { + *dst = a1; + dst++; + a2--; + } + + // v0 = a0 + mipsinfo.i = a0; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + } + break; + + case 0x2f: // rand + #if DEBUG_HLE_BIOS + printf("HLEBIOS: rand\n"); + #endif + + // v0 = result + mipsinfo.i = 1 + (int)(32767.0*rand()/(RAND_MAX+1.0)); + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + case 0x30: // srand + #if DEBUG_HLE_BIOS + printf("HLEBIOS: srand(%x)\n", a0); + #endif + srand(a0); + break; + + case 0x33: // malloc + { + uint32 chunk, fd; + + #if DEBUG_HLE_BIOS + printf("HLEBIOS: malloc(%x)\n", a0); + #endif + + chunk = heap_addr; + + // find a free block that's big enough + while ((a0 > LE32(cpu->psx_ram[(chunk+BLK_SIZE)/4])) || + (LE32(cpu->psx_ram[(chunk+BLK_STAT)/4]) == 1)) + { + chunk = LE32(cpu->psx_ram[(chunk+BLK_FD)]); + } + + // split free block + fd = chunk + 16 + a0; // free block starts after block record and allocation size + cpu->psx_ram[(fd+BLK_STAT)/4] = cpu->psx_ram[(chunk+BLK_STAT)/4]; + cpu->psx_ram[(fd+BLK_SIZE)/4] = LE32(LE32(cpu->psx_ram[(chunk+BLK_SIZE)/4]) - a0); + cpu->psx_ram[(fd+BLK_FD)/4] = cpu->psx_ram[(chunk+BLK_FD)/4]; + cpu->psx_ram[(fd+BLK_BK)/4] = chunk; + + cpu->psx_ram[(chunk+BLK_STAT)/4] = LE32(1); + cpu->psx_ram[(chunk+BLK_SIZE)/4] = LE32(a0); + cpu->psx_ram[(chunk+BLK_FD)/4] = LE32(fd); + + mipsinfo.i = chunk + 16; + mipsinfo.i |= 0x80000000; + #if DEBUG_HLE_BIOS + printf("== %08x\n", mipsinfo.i); + #endif + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + } + break; + + case 0x39: // InitHeap + // heap address in A0, length in A1 + #if DEBUG_HLE_BIOS + printf("HLEBIOS: InitHeap(%08x, %08x)\n", a0, a1); + #endif + + heap_addr = a0 & 0x3fffffff; + + cpu->psx_ram[(heap_addr+BLK_STAT)/4] = LE32(0); + cpu->psx_ram[(heap_addr+BLK_FD)/4] = LE32(0); + cpu->psx_ram[(heap_addr+BLK_BK)/4] = LE32(0); + + // if heap size out of range, clamp it + if (((a0 & 0x1fffff) + a1) >= 2*1024*1024) + { + cpu->psx_ram[(heap_addr+BLK_SIZE)/4] = LE32(0x1ffffc - (a0 & 0x1fffff)); + } + else + { + cpu->psx_ram[(heap_addr+BLK_SIZE)/4] = LE32(a1); + } + break; + + case 0x3f: // printf + #if DEBUG_HLE_BIOS + printf("HLEBIOS: printf(%08x) = %s\n", a0, &cpu->psx_ram[(a0&0x1fffff)/4]); + #endif + break; + + case 0x72: //__96_remove + #if DEBUG_HLE_BIOS + printf("HLEBIOS: __96_remove\n"); + #endif + break; + + default: + #if DEBUG_HLE_BIOS + printf("Unknown BIOS A0 call = %x\n", subcall); + #endif + break; + } + break; + + case 0xb0: // b0 syscalls + switch (subcall) + { + case 0x07: // DeliverEvent + { + int ev, spec; + + + ev = calc_ev(a0); + spec = calc_spec(a1); + + #if DEBUG_HLE_BIOS + printf("HLEBIOS: DeliverEvent(ev %d, spec %d)\n", ev, spec); + #endif + + if (Event[ev][spec].status != LE32(EvStACTIVE)) + { + #if DEBUG_HLE_BIOS + printf("event not active\n"); + #endif + return; + } + + // if interrupt mode, do the call + if (Event[ev][spec].mode == LE32(EvMdINTR)) + { + #if DEBUG_HLE_BIOS + printf("INTR type, need to call handler %x\n", LE32(Event[ev][spec].fhandler)); + #endif + } + else + { + Event[ev][spec].status = LE32(EvStALREADY); + } + } + break; + + case 0x08: // OpenEvent + { + int ev, spec; + + ev = calc_ev(a0); + spec = calc_spec(a1); + + #if DEBUG_HLE_BIOS + printf("HLEBIOS: OpenEvent(%08x, %08x, %08x, %08x) = ev %d spec %d\n", a0, a1, a2, a3, ev, spec); + if (ev >= 64 && ev <= 67) + { + printf("HLEBIOS: event %d maps to root counter %d\n", ev, ev-64); + } + #endif + + Event[ev][spec].status = LE32(EvStWAIT); + Event[ev][spec].mode = LE32(a2); + Event[ev][spec].fhandler = LE32(a3); + + // v0 = ev | spec<<8; + mipsinfo.i = ev | (spec<<8); + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + } + break; + + case 0x0a: // WaitEvent + { + int ev, spec; + + ev = a0 & 0xff; + spec = (a0 >> 8) & 0xff; + + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo); + #if DEBUG_HLE_BIOS + printf("HLEBIOS: WaitEvent(ev %d spec %d) PC=%x\n", ev, spec, mipsinfo.i); + #endif + + Event[ev][spec].status = LE32(EvStACTIVE); + + // v0 = 1 + mipsinfo.i = 1; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + + WAI = 1; + mips_shorten_frame(cpu); + } + break; + + case 0x0b: // TestEvent + { + int ev, spec; + + ev = a0 & 0xff; + spec = (a0 >> 8) & 0xff; + + #if DEBUG_HLE_BIOS + printf("HLEBIOS: TestEvent(ev %d spec %d)\n", ev, spec); + #endif + + // v0 = (is event ready?) + if (Event[ev][spec].status == LE32(EvStALREADY)) + { + Event[ev][spec].status = LE32(EvStACTIVE); + mipsinfo.i = 1; + } + else + { + mipsinfo.i = 0; + } + + WAI = 1; + + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + + // it looks like this sets v1 to something non-zero too + // (code in Crash 2 & 3 actually relies on that behavior) + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R3, &mipsinfo); + } + break; + + case 0x0c: // EnableEvent + { + int ev, spec; + + ev = a0 & 0xff; + spec = (a0 >> 8) & 0xff; + + #if DEBUG_HLE_BIOS + printf("HLEBIOS: EnableEvent(ev %d spec %d)\n", ev, spec); + #endif + + Event[ev][spec].status = LE32(EvStACTIVE); + + // v0 = 1 + mipsinfo.i = 1; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + } + break; + + case 0x0d: // DisableEvent + { + int ev, spec; + + ev = a0 & 0xff; + spec = (a0 >> 8) & 0xff; + + #if DEBUG_HLE_BIOS + printf("HLEBIOS: DisableEvent(ev %d spec %d)\n", ev, spec); + #endif + + Event[ev][spec].status = LE32(EvStWAIT); + + // v0 = 1 + mipsinfo.i = 1; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + } + break; + + case 0x17: // ReturnFromException + for (i = 0; i < 32; i++) + { + mipsinfo.i = irq_regs[i]; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R0 + i, &mipsinfo); + } + + mipsinfo.i = irq_regs[32]; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_HI, &mipsinfo); + mipsinfo.i = irq_regs[33]; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_LO, &mipsinfo); + mipsinfo.i = mips_get_ePC(cpu); +// printf("ReturnFromException: IRQ state %x\n", irq_data & irq_mask); +// printf("HLEBIOS: ReturnFromException, cause = %08x, PC = %08x\n", mips_get_cause(), mipsinfo.i); + mips_set_info(cpu,CPUINFO_INT_PC, &mipsinfo); + + status = mips_get_status(cpu); + status = (status & 0xfffffff0) | ((status & 0x3c)>>2); + mips_set_status(cpu, status); + return; // force return to avoid PC=RA below + break; + + case 0x19: // HookEntryInt + #if DEBUG_HLE_BIOS + printf("HLEBIOS: HookEntryInt(%08x)\n", a0); + #endif + entry_int = a0; + break; + + case 0x3f: // puts +// printf("HLEBIOS: puts\n"); + break; + + case 0x5b: // ChangeClearPAD + #if DEBUG_HLE_BIOS + printf("HLEBIOS: ChangeClearPAD\n"); + #endif + break; + + default: + #if DEBUG_HLE_BIOS + printf("Unknown BIOS B0 call = %x\n", subcall); + #endif + break; + } + break; + + case 0xc0: // c0 syscalls + switch (subcall) + { + case 0xa: // ChangeClearRCnt + #if DEBUG_HLE_BIOS + printf("HLEBIOS: ChangeClearRCnt(%08x, %08x)\n", a0, a1); + #endif + + // v0 = (a0*4)+0x8600 + mipsinfo.i = LE32(cpu->psx_ram[((a0<<2) + 0x8600)/4]); + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + + // (a0*4)+0x8600 = a1; + cpu->psx_ram[((a0<<2) + 0x8600)/4] = LE32(a1); + break; + + default: + #if DEBUG_HLE_BIOS + printf("Unknown BIOS C0 call = %x\n", subcall); + #endif + break; + } + break; + } + + // PC = RA + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo); + mips_set_info(cpu,CPUINFO_INT_PC, &mipsinfo); +} + +// root counters + +void psx_hw_runcounters(mips_cpu_context *cpu) +{ + int i, j; + union cpuinfo mipsinfo; + + // don't process any IRQ sources when interrupts are suspended + if (!intr_susp) + { + if (dma4_delay) + { + dma4_delay--; + + if (dma4_delay == 0) + { + SPU2interruptDMA4(cpu); + + if (dma4_cb) + { + call_irq_routine(cpu, dma4_cb, dma4_flag); + } + } + } + + if (dma7_delay) + { + dma7_delay--; + + if (dma7_delay == 0) + { + SPU2interruptDMA7(cpu); + + if (dma7_cb) + { + call_irq_routine(cpu, dma7_cb, dma7_flag); + } + } + } + + for (i = 0; i < iNumThreads; i++) + { + if (threads[i].iState == TS_WAITDELAY) + { + if (threads[i].waitparm > CLOCK_DIV) + { + threads[i].waitparm -= CLOCK_DIV; + } + else // time's up + { + threads[i].waitparm = 0; + threads[i].iState = TS_READY; + + timerexp = 1; + + ps2_reschedule(cpu); + } + } + } + + sys_time += 836; + + if (iNumTimers > 0) + { + for (i = 0; i < iNumTimers; i++) + { + if (iop_timers[i].iActive > 0) + { + iop_timers[i].count += 836; + if (iop_timers[i].count >= iop_timers[i].target) + { + iop_timers[i].count -= iop_timers[i].target; + + // printf("Timer %d: handler = %08x, param = %08x\n", i, iop_timers[i].handler, iop_timers[i].hparam); + call_irq_routine(cpu, iop_timers[i].handler, iop_timers[i].hparam); + + timerexp = 1; + } + } + } + } + } + +// PS1 root counters + for (i = 0; i < 3; i++) + { + if ((!(root_cnts[i].mode & RC_EN)) && (root_cnts[i].mode != 0)) + { + if (root_cnts[i].mode & RC_DIV8) + { + root_cnts[i].count += 768/8; + } + else + { + root_cnts[i].count += 768; + } + + if (root_cnts[i].count >= root_cnts[i].target) + { + if (!(root_cnts[i].mode & RC_RESET)) + { + root_cnts[i].mode |= RC_EN; + } + else + { + root_cnts[i].count %= root_cnts[i].target; + } + + psx_irq_set(cpu, 1<<(4+i)); + } + } + } +} + +// PEOpS callbacks + +void SPUirq(void) +{ +// psx_irq_set(0x200); +} + +// PSXCPU callbacks + +uint8 program_read_byte_32le(mips_cpu_context *cpu, offs_t address) +{ + switch (address & 0x3) + { + case 0: + return psx_hw_read(cpu, address, 0xffffff00); + break; + case 1: + return psx_hw_read(cpu, address, 0xffff00ff)>>8; + break; + case 2: + return psx_hw_read(cpu, address, 0xff00ffff)>>16; + break; + case 3: + return psx_hw_read(cpu, address, 0x00ffffff)>>24; + break; + } + return 0; +} + +uint16 program_read_word_32le(mips_cpu_context *cpu, offs_t address) +{ + if (address & 2) + return psx_hw_read(cpu, address, 0x0000ffff)>>16; + + return psx_hw_read(cpu, address, 0xffff0000); +} + +uint32 program_read_dword_32le(mips_cpu_context *cpu, offs_t address) +{ + return psx_hw_read(cpu, address, 0); +} + +void program_write_byte_32le(mips_cpu_context *cpu, offs_t address, uint8 data) +{ + switch (address & 0x3) + { + case 0: + psx_hw_write(cpu, address, data, 0xffffff00); + break; + case 1: + psx_hw_write(cpu, address, data<<8, 0xffff00ff); + break; + case 2: + psx_hw_write(cpu, address, data<<16, 0xff00ffff); + break; + case 3: + psx_hw_write(cpu, address, data<<24, 0x00ffffff); + break; + } +} + +void program_write_word_32le(mips_cpu_context *cpu, offs_t address, uint16 data) +{ + if (address & 2) + { + psx_hw_write(cpu, address, data<<16, 0x0000ffff); + return; + } + + psx_hw_write(cpu, address, data, 0xffff0000); +} + +void program_write_dword_32le(mips_cpu_context *cpu, offs_t address, uint32 data) +{ + psx_hw_write(cpu, address, data, 0); +} + +// sprintf replacement +static void iop_sprintf(mips_cpu_context *cpu, char *out, char *fmt, uint32 pstart) +{ + char temp[64], tfmt[64]; + char *cf, *pstr; + union cpuinfo mipsinfo; + int curparm, fp, isnum; + + curparm = pstart; + cf = fmt; + + while (*cf != '\0') + { + if (*cf != '%') + { + if (*cf == 27) + { + *out++ = '['; + *out++ = 'E'; + *out++ = 'S'; + *out++ = 'C'; + *out = ']'; + } + else + { + *out = *cf; + } + out++; + cf++; + } + else // got format + { + cf++; + + tfmt[0] = '%'; + fp = 1; + while (((*cf >= '0') && (*cf <= '9')) || (*cf == '.')) + { + tfmt[fp] = *cf; + fp++; + cf++; + } + + tfmt[fp] = *cf; + tfmt[fp+1] = '\0'; + + isnum = 0; + switch (*cf) + { + case 'x': + case 'X': + case 'd': + case 'D': + case 'c': + case 'C': + case 'u': + case 'U': + isnum = 1; + break; + } + +// printf("]]] temp format: [%s] [%d]\n", tfmt, isnum); + + if (isnum) + { + mips_get_info(cpu, curparm, &mipsinfo); +// printf("parameter %d = %x\n", curparm-pstart, mipsinfo.i); + curparm++; + sprintf(temp, tfmt, (int32)mipsinfo.i); + } + else + { + mips_get_info(cpu, curparm, &mipsinfo); + curparm++; + + pstr = (char *)cpu->psx_ram; + pstr += (mipsinfo.i & 0x1fffff); + + sprintf(temp, tfmt, pstr); + } + + pstr = &temp[0]; + while (*pstr != '\0') + { + *out = *pstr; + out++; + pstr++; + } + + cf++; + } + } + + *out = '\0'; +} + +// PS2 IOP callbacks +void psx_iop_call(mips_cpu_context *cpu, uint32 pc, uint32 callnum) +{ + uint32 scan; + char *mname, *str1, *str2, *str3, name[9], out[512]; + uint32 a0, a1, a2, a3; + union cpuinfo mipsinfo; + int i; + +// printf("IOP call @ %08x\n", pc); + + // prefetch parameters + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_R4, &mipsinfo); + a0 = mipsinfo.i; + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_R5, &mipsinfo); + a1 = mipsinfo.i; + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_R6, &mipsinfo); + a2 = mipsinfo.i; + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_R7, &mipsinfo); + a3 = mipsinfo.i; + + scan = (pc&0x0fffffff)/4; + while ((cpu->psx_ram[scan] != LE32(0x41e00000)) && (scan >= (0x10000/4))) + { + scan--; + } + + if (cpu->psx_ram[scan] != LE32(0x41e00000)) + { + printf("FATAL ERROR: couldn't find IOP link signature\n"); + return; + } + + scan += 3; // skip zero and version + memcpy(name, &cpu->psx_ram[scan], 8); + name[8] = '\0'; + +// printf("IOP: call module [%s] service %d (PC=%08x)\n", name, callnum, pc); + + if (!strcmp(name, "stdio")) + { + switch (callnum) + { + case 4: // printf + mname = (char *)cpu->psx_ram; + mname += a0 & 0x1fffff; + mname += (a0 & 3); + + iop_sprintf(cpu, out, mname, CPUINFO_INT_REGISTER + MIPS_R5); // a1 is first parm + + /* if (out[strlen(out)-1] != '\n') + { + strcat(out, "\n"); + }*/ + + #if DEBUG_HLE_IOP + printf("%s", out); + #endif + break; + + default: + printf("IOP: Unhandled service %d for module %s\n", callnum, name); + break; + } + } + else if (!strcmp(name, "sifman")) + { + switch (callnum) + { + case 5: // sceSifInit + #if DEBUG_HLE_IOP + printf("IOP: sceSifInit()\n"); + #endif + + mipsinfo.i = 0; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + case 7: // sceSifSetDma + #if DEBUG_HLE_IOP + printf("IOP: sceSifSetDma(%08x %08x)\n", a0, a1); + #endif + + mipsinfo.i = 1; // nonzero = success + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + case 8: // sceSifDmaStat + #if DEBUG_HLE_IOP + printf("IOP: sceSifDmaStat(%08x)\n", a0); + #endif + + mipsinfo.i = -1; // dma completed + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + case 29: // sceSifCheckInit + #if DEBUG_HLE_IOP + printf("IOP: sceSifCheckInit()\n"); + #endif + + mipsinfo.i = 1; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + default: + printf("IOP: Unhandled service %d for module %s\n", callnum, name); + break; + } + } + else if (!strcmp(name, "thbase")) + { + uint32 newAlloc; + + switch (callnum) + { + case 4: // CreateThread + #if DEBUG_THREADING + printf("IOP: CreateThread(%08x)\n", a0); + #endif + a0 &= 0x1fffff; + a0 /= 4; + #if DEBUG_THREADING + printf(" : flags %x routine %08x pri %x stacksize %d refCon %08x\n", + cpu->psx_ram[a0], cpu->psx_ram[a0+1], cpu->psx_ram[a0+2], cpu->psx_ram[a0+3], cpu->psx_ram[a0+4]); + #endif + + newAlloc = psf2_get_loadaddr(); + // force 16-byte alignment + if (newAlloc & 0xf) + { + newAlloc &= ~0xf; + newAlloc += 16; + } + psf2_set_loadaddr(newAlloc + LE32(cpu->psx_ram[a0+3])); + + threads[iNumThreads].iState = TS_CREATED; + threads[iNumThreads].stackloc = newAlloc; + threads[iNumThreads].flags = LE32(cpu->psx_ram[a0]); + threads[iNumThreads].routine = LE32(cpu->psx_ram[a0+2]); + threads[iNumThreads].stacksize = LE32(cpu->psx_ram[a0+3]); + threads[iNumThreads].refCon = LE32(cpu->psx_ram[a0+4]); + + mipsinfo.i = iNumThreads; + iNumThreads++; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + case 6: // StartThread + #if DEBUG_THREADING + printf("IOP: StartThread(%d %d)\n", a0, a1); + #endif + + FreezeThread(cpu, iCurThread, 1); + ThawThread(cpu, a0); + iCurThread = a0; + break; + + case 20:// GetThreadID + #if DEBUG_THREADING + printf("IOP: GetThreadId()\n"); + #endif + + mipsinfo.i = iCurThread; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + case 24:// SleepThread + #if DEBUG_THREADING + mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo); + printf("IOP: SleepThread() [curThread %d, PC=%x]\n", iCurThread, mipsinfo.i); + #endif + + FreezeThread(cpu, iCurThread, 1); + threads[iCurThread].iState = TS_SLEEPING; + iCurThread = -1; + + ps2_reschedule(cpu); + break; + + case 25:// WakeupThread + #if DEBUG_THREADING + printf("IOP: WakeupThread(%d)\n", a0); + #endif + + // set thread to "ready to go" + threads[a0].iState = TS_READY; + break; + + case 26:// iWakeupThread + #if DEBUG_THREADING + printf("IOP: iWakeupThread(%d)\n", a0); + #endif + + // set thread to "ready to go" if it's not running + if (threads[a0].iState != TS_RUNNING) + { + threads[a0].iState = TS_READY; + } + break; + + case 33:// DelayThread + { + double dTicks; + int i; + + #if DEBUG_THREADING + mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo); + printf("IOP: DelayThread(%d) (PC=%x) [curthread = %d]\n", a0, mipsinfo.i, iCurThread); + #endif + + if (a0 < 100) + { + a0 = 100; + } + dTicks = (double)a0; + + FreezeThread(cpu, iCurThread, 1); + threads[iCurThread].iState = TS_WAITDELAY; + dTicks /= (double)1000000.0; + dTicks *= (double)36864000.0; // 768*48000 = IOP native-mode clock rate + threads[iCurThread].waitparm = (uint32)dTicks; + iCurThread = -1; + + ps2_reschedule(cpu); + } + break; + + case 34://GetSystemTime + #if DEBUG_HLE_IOP + printf("IOP: GetSystemTime(%x)\n", a0); + #endif + + a0 &= 0x1fffff; + a0 /= 4; + + cpu->psx_ram[a0] = LE32(sys_time & 0xffffffff); // low + cpu->psx_ram[a0+1] = LE32(sys_time >> 32); // high + + mipsinfo.i = 0; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + case 39:// USec2SysClock + { + uint64 dTicks = (uint64)a0; + uint32 hi, lo; + + #if DEBUG_HLE_IOP + printf("IOP: USec2SysClock(%d %08x)\n", a0, a1); + #endif + + dTicks *= (uint64)36864000; + dTicks /= (uint64)1000000; + + hi = dTicks>>32; + lo = dTicks & 0xffffffff; + + cpu->psx_ram[((a1 & 0x1fffff)/4)] = LE32(lo); + cpu->psx_ram[((a1 & 0x1fffff)/4)+1] = LE32(hi); + + mipsinfo.i = 0; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + } + break; + + case 40://SysClock2USec + { + uint64 temp; + uint32 seconds, usec; + + #if DEBUG_HLE_IOP + printf("IOP: SysClock2USec(%08x %08x %08x)\n", a0, a1, a2); + #endif + + a0 &= 0x1fffff; + a1 &= 0x1fffff; + a2 &= 0x1fffff; + a0 /= 4; + a1 /= 4; + a2 /= 4; + + temp = LE32(cpu->psx_ram[a0]); + temp |= (uint64)LE32(cpu->psx_ram[a0+1])<<32; + + temp *= (uint64)1000000; + temp /= (uint64)36864000; + + // temp now is USec + seconds = (temp / 1000000) & 0xffffffff; + usec = (temp % 1000000) & 0xffffffff; + + cpu->psx_ram[a1] = LE32(seconds); + cpu->psx_ram[a2] = LE32(usec); + } + break; + + default: + printf("IOP: Unhandled service %d for module %s\n", callnum, name); + break; + } + } + else if (!strcmp(name, "thevent")) + { + switch (callnum) + { + case 4: // CreateEventFlag + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo); + #if DEBUG_HLE_IOP + printf("IOP: CreateEventFlag(%08x) (PC=%x)\n", a0, mipsinfo.i); + #endif + + a0 &= 0x1fffff; + a0 /= 4; + + evflags[iNumFlags].type = LE32(cpu->psx_ram[a0]); + evflags[iNumFlags].value = LE32(cpu->psx_ram[a0+1]); + evflags[iNumFlags].param = LE32(cpu->psx_ram[a0+2]); + evflags[iNumFlags].inUse = 1; + + #if DEBUG_HLE_IOP + printf(" Flag %02d: type %d init %08x param %08x\n", iNumFlags, evflags[iNumFlags].type, evflags[iNumFlags].value, evflags[iNumFlags].param); + #endif + + mipsinfo.i = iNumFlags+1; + iNumFlags++; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + case 6: // SetEventFlag + a0--; + #if DEBUG_HLE_IOP + printf("IOP: SetEventFlag(%d %08x)\n", a0, a1); + #endif + + evflags[a0].value |= a1; + + mipsinfo.i = 0; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + case 7: // iSetEventFlag + a0--; + #if DEBUG_HLE_IOP + printf("IOP: iSetEventFlag(%08x %08x)\n", a0, a1); + #endif + + evflags[a0].value |= a1; + + mipsinfo.i = 0; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + + for (i=0; i < iNumThreads; i++) + { + if ((threads[i].iState == TS_WAITEVFLAG) && (threads[i].waitparm == a0)) + { + threads[i].iState = TS_READY; + } + } + break; + + case 8: // ClearEventFlag + a0--; + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo); + #if DEBUG_HLE_IOP + printf("IOP: ClearEventFlag(%d %08x) (PC=%x)\n", a0, a1, mipsinfo.i); + #endif + + evflags[a0].value &= a1; + + mipsinfo.i = 0; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + case 9: // iClearEventFlag + a0--; + #if DEBUG_HLE_IOP + printf("IOP: iClearEventFlag(%d %08x)\n", a0, a1); + #endif + + evflags[a0].value &= a1; + + mipsinfo.i = 0; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + case 10:// WaitEventFlag + a0--; + #if DEBUG_HLE_IOP + mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo); + printf("IOP: WaitEventFlag(%d %08x %d %08x PC=%x)\n", a0, a1, a2, a3, mipsinfo.i); + #endif + + // if we're not set, freeze this thread + if (!(evflags[a0].value & a1)) + { + FreezeThread(cpu, iCurThread, 1); + threads[iCurThread].iState = TS_WAITEVFLAG; + threads[iCurThread].waitparm = a0; + iCurThread = -1; + + ps2_reschedule(cpu); + } + else + { + mipsinfo.i = 0; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + } + break; + + default: + printf("IOP: Unhandled service %d for module %s\n", callnum, name); + break; + } + } + else if (!strcmp(name, "thsemap")) + { + int foundthread; + + switch (callnum) + { + case 4: // CreateSema + #if DEBUG_HLE_IOP + printf("IOP: CreateSema(%08x)\n", a0); + #endif + + mipsinfo.i = -1; + for (i = 0; i < SEMA_MAX; i++) + { + if (!semaphores[i].inuse) + { + mipsinfo.i = i; + break; + } + } + + if (mipsinfo.i == -1) + { + printf("IOP: out of semaphores!\n"); + } + + a0 &= 0x7fffffff; + a0 /= 4; + +// printf("Sema %d Parms: %08x %08x %08x %08x\n", mipsinfo.i, cpu->psx_ram[a0], cpu->psx_ram[a0+1], cpu->psx_ram[a0+2], cpu->psx_ram[a0+3]); + + if (mipsinfo.i != -1) + { + semaphores[mipsinfo.i].attr = LE32(cpu->psx_ram[a0]); + semaphores[mipsinfo.i].option = LE32(cpu->psx_ram[a0+1]); + semaphores[mipsinfo.i].init = LE32(cpu->psx_ram[a0+2]); + semaphores[mipsinfo.i].max = LE32(cpu->psx_ram[a0+3]); + + semaphores[mipsinfo.i].current = semaphores[mipsinfo.i].init; + + semaphores[mipsinfo.i].inuse = 1; + } + + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + case 6: // SignalSema + #if DEBUG_HLE_IOP + printf("IOP: SignalSema(%d) (current %d)\n", a0, semaphores[a0].current); + #endif + + foundthread = 0; + for (i=0; i < iNumThreads; i++) + { + if ((threads[i].iState == TS_WAITSEMA) && (threads[i].waitparm == a0)) + { + threads[i].iState = TS_READY; + semaphores[a0].threadsWaiting--; + foundthread = 1; + break; + } + } + + mipsinfo.i = 0; + + if (!foundthread) + { + if (semaphores[a0].current < semaphores[a0].max) + { + semaphores[a0].current++; + } + else + { + mipsinfo.i = -420; // semaphore overflow + } + } + + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + case 7: // iSignalSema + #if DEBUG_HLE_IOP + printf("IOP: iSignalSema(%d)\n", a0); + #endif + + foundthread = 0; + for (i=0; i < iNumThreads; i++) + { + if ((threads[i].iState == TS_WAITSEMA) && (threads[i].waitparm == a0)) + { + threads[i].iState = TS_READY; + semaphores[a0].threadsWaiting--; + foundthread = 1; + break; + } + } + + mipsinfo.i = 0; + + if (!foundthread) + { + if (semaphores[a0].current < semaphores[a0].max) + { + semaphores[a0].current++; + } + else + { + mipsinfo.i = -420; // semaphore overflow + } + } + + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + case 8: // WaitSema + #if DEBUG_HLE_IOP + mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo); + printf("IOP: WaitSema(%d) (cnt %d) (th %d) (PC=%x)\n", a0, iCurThread, semaphores[a0].current, mipsinfo.i); + #endif + + if (semaphores[a0].current > 0) + { + semaphores[a0].current--; + } + else + { + FreezeThread(cpu,iCurThread, 1); + threads[iCurThread].iState = TS_WAITSEMA; + threads[iCurThread].waitparm = a0; + ps2_reschedule(cpu); + } + + mipsinfo.i = 0; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + default: + printf("IOP: Unhandled service %d for module %s\n", callnum, name); + break; + } + } + else if (!strcmp(name, "timrman")) + { + switch (callnum) + { + case 4: // AllocHardTimer + #if DEBUG_HLE_IOP + printf("IOP: AllocHardTimer(%d %d %d)\n", a0, a1, a2); + #endif + // source, size, prescale + + if (a1 != 32) + { + printf("IOP: AllocHardTimer doesn't support 16-bit timers!\n"); + } + + iop_timers[iNumTimers].source = a0; + iop_timers[iNumTimers].prescale = a2; + + mipsinfo.i = iNumTimers+1; + iNumTimers++; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + case 6: // FreeHardTimer + #if DEBUG_HLE_IOP + printf("IOP: FreeHardTimer(%d)\n", a0); + #endif + mipsinfo.i = 0; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + case 10:// GetTimerCounter + mipsinfo.i = iop_timers[a0-1].count; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + case 20: // SetTimerHandler + #if DEBUG_HLE_IOP + printf("IOP: SetTimerHandler(%d %d %08x %08x)\n", a0, a1, a2, a3); + #endif + // id, compare, handler, common (last is param for handler) + + iop_timers[a0-1].target = a1; + iop_timers[a0-1].handler = a2; + iop_timers[a0-1].hparam = a3; + + mipsinfo.i = 0; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + case 22: // SetupHardTimer + #if DEBUG_HLE_IOP + printf("IOP: SetupHardTimer(%d %d %d %d)\n", a0, a1, a2, a3); + #endif + // id, source, mode, prescale + + iop_timers[a0-1].source = a1; + iop_timers[a0-1].mode = a2; + iop_timers[a0-1].prescale = a3; + + mipsinfo.i = 0; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + case 23: // StartHardTimer + #if DEBUG_HLE_IOP + printf("IOP: StartHardTimer(%d)\n", a0); + #endif + + iop_timers[a0-1].iActive = 1; + iop_timers[a0-1].count = 0; + + mipsinfo.i = 0; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + case 24: // StopHardTimer + #if DEBUG_HLE_IOP + printf("IOP: StopHardTimer(%d)\n", a0); + #endif + + iop_timers[a0-1].iActive = 0; + + mipsinfo.i = 0; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + default: + printf("IOP: Unhandled service %d for module %s\n", callnum, name); + break; + } + } + else if (!strcmp(name, "sysclib")) + { + switch (callnum) + { + case 12: // memcpy + { + uint8 *dst, *src; + + #if DEBUG_HLE_IOP + printf("IOP: memcpy(%08x, %08x, %d)\n", a0, a1, a2); + #endif + + dst = (uint8 *)&cpu->psx_ram[(a0&0x1fffff)/4]; + src = (uint8 *)&cpu->psx_ram[(a1&0x1fffff)/4]; + // get exact byte alignment + dst += a0 % 4; + src += a1 % 4; + + while (a2) + { + *dst = *src; + dst++; + src++; + a2--; + } + + // v0 = a0 + mipsinfo.i = a0; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + } + break; + + case 13: // memmove + { + uint8 *dst, *src; + + #if DEBUG_HLE_IOP + printf("IOP: memmove(%08x, %08x, %d)\n", a0, a1, a2); + #endif + + dst = (uint8 *)&cpu->psx_ram[(a0&0x1fffff)/4]; + src = (uint8 *)&cpu->psx_ram[(a1&0x1fffff)/4]; + // get exact byte alignment + dst += a0 % 4; + src += a1 % 4; + + dst += a2 - 1; + src += a2 - 1; + + while (a2) + { + *dst = *src; + dst--; + src--; + a2--; + } + + // v0 = a0 + mipsinfo.i = a0; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + } + break; + + case 14: // memset + { + uint8 *dst; + + #if DEBUG_HLE_IOP + mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo); + printf("IOP: memset(%08x, %02x, %d) [PC=%x]\n", a0, a1, a2, mipsinfo.i); + #endif + + dst = (uint8 *)&cpu->psx_ram[(a0&0x1fffff)/4]; + dst += (a0 & 3); + + memset(dst, a1, a2); + } + break; + + case 17: // bzero + { + uint8 *dst; + + #if DEBUG_HLE_IOP + printf("IOP: bzero(%08x, %08x)\n", a0, a1); + #endif + + dst = (uint8 *)&cpu->psx_ram[(a0&0x1fffff)/4]; + dst += (a0 & 3); + memset(dst, 0, a1); + } + break; + + case 19: // sprintf + mname = (char *)cpu->psx_ram; + str1 = (char *)cpu->psx_ram; + mname += a0 & 0x1fffff; + str1 += a1 & 0x1fffff; + + #if DEBUG_HLE_IOP + mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo); + printf("IOP: sprintf(%08x, %s, ...) [PC=%08x]\n", a0, str1, (uint32)mipsinfo.i); + printf("%x %x %x %x\n", a0, a1, a2, a3); + #endif + + iop_sprintf(cpu, mname, str1, CPUINFO_INT_REGISTER + MIPS_R6); // a2 is first parameter + + #if DEBUG_HLE_IOP + printf(" = [%s]\n", mname); + #endif + break; + + case 23: // strcpy + { + uint8 *dst, *src; + + #if DEBUG_HLE_IOP + printf("IOP: strcpy(%08x, %08x)\n", a0, a1); + #endif + + dst = (uint8 *)&cpu->psx_ram[(a0&0x1fffff)/4]; + src = (uint8 *)&cpu->psx_ram[(a1&0x1fffff)/4]; + // get exact byte alignment + dst += a0 % 4; + src += a1 % 4; + + while (*src != '\0') + { + *dst = *src; + dst++; + src++; + } + *dst = '\0'; + + // v0 = a0 + mipsinfo.i = a0; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + } + break; + + case 27: // strlen + { + char *dst; + + #if DEBUG_HLE_IOP + mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo); + printf("IOP: strlen(%08x) [PC=%x]\n", a0, mipsinfo.i); + #endif + + dst = (char *)&cpu->psx_ram[(a0&0x1fffff)/4]; + dst += (a0 & 3); + mipsinfo.i = strlen(dst); + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + } + break; + + case 30: // strncpy + { + char *dst, *src; + + #if DEBUG_HLE_IOP + printf("IOP: strncpy(%08x, %08x, %d)\n", a0, a1, a2); + #endif + + dst = (char *)&cpu->psx_ram[(a0&0x1fffff)/4]; + src = (char *)&cpu->psx_ram[(a1&0x1fffff)/4]; + // get exact byte alignment + dst += a0 % 4; + src += a1 % 4; + + while ((*src != '\0') && (a2 > 0)) + { + *dst = *src; + dst++; + src++; + a2--; + } + *dst = '\0'; + + // v0 = a0 + mipsinfo.i = a0; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + } + break; + + + case 36: // strtol + mname = (char *)&cpu->psx_ram[(a0 & 0x1fffff)/4]; + mname += (a0 & 3); + + if (a1) + { + printf("IOP: Unhandled strtol with non-NULL second parm\n"); + } + + mipsinfo.i = strtol(mname, NULL, a2); + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + default: + printf("IOP: Unhandled service %d for module %s\n", callnum, name); + break; + } + } + else if (!strcmp(name, "intrman")) + { + switch (callnum) + { + case 4: // RegisterIntrHandler + #if DEBUG_HLE_IOP + printf("IOP: RegisterIntrHandler(%d %08x %08x %08x)\n", a0, a1, a2, a3); + #endif + + if (a0 == 9) + { + irq9_fval = a1; + irq9_cb = a2; + irq9_flag = a3; + } + + // DMA4? + if (a0 == 36) + { + dma4_fval = a1; + dma4_cb = a2; + dma4_flag = a3; + } + + // DMA7? + if (a0 == 40) + { + dma7_fval = a1; + dma7_cb = a2; + dma7_flag = a3; + } + break; + + case 5: // ReleaseIntrHandler + #if DEBUG_HLE_IOP + printf("IOP: ReleaseIntrHandler(%d)\n", a0); + #endif + break; + + case 6: // EnableIntr + #if DEBUG_HLE_IOP + printf("IOP: EnableIntr(%d)\n", a0); + #endif + break; + + case 7: // DisableIntr + #if DEBUG_HLE_IOP + printf("IOP: DisableIntr(%d)\n", a0); + #endif + break; + + case 8: // CpuDisableIntr + #if DEBUG_HLE_IOP + printf("IOP: CpuDisableIntr(%d)\n", a0); + #endif + break; + + case 9: // CpuEnableIntr + #if DEBUG_HLE_IOP + printf("IOP: CpuEnableIntr(%d)\n", a0); + #endif + break; + + case 17: // CpuSuspendIntr + #if DEBUG_HLE_IOP + printf("IOP: CpuSuspendIntr\n"); + #endif + + // if already suspended, return an error code + if (intr_susp) + { + mipsinfo.i = -102; + } + else + { + mipsinfo.i = 0; + } + intr_susp = 1; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + case 18: // CpuResumeIntr + #if DEBUG_HLE_IOP + printf("IOP: CpuResumeIntr\n"); + #endif + intr_susp = 0; + mipsinfo.i = 0; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + case 23: // QueryIntrContext + #if DEBUG_HLE_IOP + mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo); + printf("IOP: QueryIntrContext(PC=%x)\n", mipsinfo.i); + #endif + mipsinfo.i = 0; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + default: + printf("IOP: Unhandled service %d for module %s\n", callnum, name); + break; + } + } + else if (!strcmp(name, "loadcore")) + { + switch (callnum) + { + case 5: // FlushDcache + #if DEBUG_HLE_IOP + printf("IOP: FlushDcache()\n"); + #endif + break; + + case 6: // RegisterLibraryEntries + a0 &= 0x1fffff; + #if DEBUG_HLE_IOP + mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo); + printf("IOP: RegisterLibraryEntries(%08x) (PC=%x)\n", a0, mipsinfo.i); + #endif + + if (cpu->psx_ram[a0/4] == LE32(0x41c00000)) + { + a0 += 3*4; + memcpy(®libs[iNumLibs].name, &cpu->psx_ram[a0/4], 8); + reglibs[iNumLibs].name[8] = '\0'; + #if DEBUG_HLE_IOP + printf("Lib name [%s]\n", ®libs[iNumLibs].name); + #endif + a0 += 2*4; + reglibs[iNumLibs].dispatch = a0; + iNumLibs++; + } + else + { + printf("ERROR: Entry table signature missing\n"); + + } + + mipsinfo.i = 0; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + default: + printf("IOP: Unhandled service %d for module %s\n", callnum, name); + break; + } + } + else if (!strcmp(name, "sysmem")) + { + uint32 newAlloc; + + switch (callnum) + { + case 4: // AllocMemory + newAlloc = psf2_get_loadaddr(); + // make sure we're 16-byte aligned + if (newAlloc & 15) + { + newAlloc &= ~15; + newAlloc += 16; + } + + if (a1 & 15) + { + a1 &= ~15; + a1 += 16; + } + + if (a1 == 1114112) // HACK for crappy code in Shadow Hearts rip that assumes the buffer address + { + printf("SH Hack: was %x now %x\n", newAlloc, 0x60000); + newAlloc = 0x60000; + } + + psf2_set_loadaddr(newAlloc + a1); + + #if DEBUG_HLE_IOP + printf("IOP: AllocMemory(%d, %d, %x) = %08x\n", a0, a1, a2, newAlloc|0x80000000); + #endif + + mipsinfo.i = newAlloc; // | 0x80000000; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + case 5: // FreeMemory + #if DEBUG_HLE_IOP + printf("IOP: FreeMemory(%x)\n", a0); + #endif + break; + + case 7: // QueryMaxFreeMemSize + #if DEBUG_HLE_IOP + printf("IOP: QueryMaxFreeMemSize\n"); + #endif + + mipsinfo.i = (2*1024*1024) - psf2_get_loadaddr(); + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + case 8: // QueryTotalFreeMemSize + #if DEBUG_HLE_IOP + printf("IOP: QueryTotalFreeMemSize\n"); + #endif + + mipsinfo.i = (2*1024*1024) - psf2_get_loadaddr(); + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + case 14: // Kprintf + mname = (char *)cpu->psx_ram; + mname += a0 & 0x1fffff; + mname += (a0 & 3); + + iop_sprintf(cpu, out, mname, CPUINFO_INT_REGISTER + MIPS_R5); // a1 is first parm + + if (out[strlen(out)-1] != '\n') + { + strcat(out, "\n"); + } + + // filter out ESC characters + { + int ch; + + for (ch = 0; ch < strlen(out); ch++) + { + if (out[ch] == 27) + { + out[ch] = ']'; + } + } + } + + #if DEBUG_HLE_IOP + mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo); + printf("KTTY: %s [PC=%x]\n", out, mipsinfo.i); + #endif + + #if 0 + { + FILE *f; + f = fopen("psxram.bin", "wb"); + fwrite(cpu->psx_ram, 2*1024*1024, 1, f); + fclose(f); + } + #endif + break; + + default: + printf("IOP: Unhandled service %d for module %s\n", callnum, name); + break; + } + } + else if (!strcmp(name, "modload")) + { + uint8 *tempmem; + uint32 newAlloc; + + switch (callnum) + { + case 7: // LoadStartModule + mname = (char *)&cpu->psx_ram[(a0 & 0x1fffff)/4]; + mname += 8; + str1 = (char *)&cpu->psx_ram[(a2 & 0x1fffff)/4]; + #if DEBUG_HLE_IOP + printf("LoadStartModule: %s\n", mname); + #endif + + // get 2k for our parameters + newAlloc = psf2_get_loadaddr(); + // force 16-byte alignment + if (newAlloc & 0xf) + { + newAlloc &= ~0xf; + newAlloc += 16; + } + psf2_set_loadaddr(newAlloc + 2048); + + tempmem = (uint8 *)malloc(2*1024*1024); + if (psf2_load_file(cpu, mname, tempmem, 2*1024*1024) != 0xffffffff) + { + uint32 start; + int i; + + start = psf2_load_elf(cpu, tempmem, 2*1024*1024); + + if (start != 0xffffffff) + { + uint32 args[20], numargs = 1, argofs; + uint8 *argwalk = (uint8 *)cpu->psx_ram, *argbase; + + argwalk += (a2 & 0x1fffff); + argbase = argwalk; + + args[0] = a0; // program name is argc[0] + + argofs = 0; + + if (a1 > 0) + { + args[numargs] = a2; + numargs++; + + while (a1) + { + if ((*argwalk == 0) && (a1 > 1)) + { + args[numargs] = a2 + argofs + 1; + numargs++; + } + argwalk++; + argofs++; + a1--; + } + } + + for (i = 0; i < numargs; i++) + { + #if DEBUG_HLE_IOP +// printf("Arg %d: %08x [%s]\n", i, args[i], &argbase[args[i]-a2]); + #endif + cpu->psx_ram[(newAlloc/4)+i] = LE32(args[i]); + } + + // set argv and argc + mipsinfo.i = numargs; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R4, &mipsinfo); + mipsinfo.i = 0x80000000 | newAlloc; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R5, &mipsinfo); + + // leave RA alone, PC = module start + // (NOTE: we get called in the delay slot!) + mipsinfo.i = start - 4; + mips_set_info(cpu,CPUINFO_INT_PC, &mipsinfo); + } + } + free(tempmem); + break; + + default: + printf("IOP: Unhandled service %d for module %s\n", callnum, name); + break; + } + + } + else if (!strcmp(name, "ioman")) + { + switch (callnum) + { + case 4: // open + { + int i, slot2use; + + slot2use = -1; + for (i = 0; i < MAX_FILE_SLOTS; i++) + { + if (filestat[i] == 0) + { + slot2use = i; + break; + } + } + + if (slot2use == -1) + { + printf("IOP: out of file slots!\n"); + mipsinfo.i = 0xffffffff; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + return; + } + + mname = (char *)cpu->psx_ram; + mname += (a0 & 0x1fffff); + + if (!strncmp(mname, "aofile:", 7)) + { + mname += 8; + } + else if (!strncmp(mname, "hefile:", 7)) + { + mname += 8; + } + else if (!strncmp(mname, "host0:", 6)) + { + mname += 7; + } + + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo); + #if DEBUG_HLE_IOP + printf("IOP: open(\"%s\") (PC=%08x)\n", mname, mipsinfo.i); + #endif + + filedata[slot2use] = malloc(6*1024*1024); + filesize[slot2use] = psf2_load_file(cpu, mname, filedata[slot2use], 6*1024*1024); + filepos[slot2use] = 0; + filestat[slot2use] = 1; + + if (filesize[slot2use] == 0xffffffff) + { + mipsinfo.i = filesize[slot2use]; + } + else + { + mipsinfo.i = slot2use; + } + } + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + case 5: // close + #if DEBUG_HLE_IOP + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo); + printf("IOP: close(%d) (PC=%08x)\n", a0, mipsinfo.i); + #endif + free(filedata[a0]); + filedata[a0] = (uint8 *)NULL; + filepos[a0] = 0; + filesize[a0] = 0; + filestat[a0] = 0; + break; + + case 6: // read + #if DEBUG_HLE_IOP + printf("IOP: read(%x %x %d) [pos %d size %d]\n", a0, a1, a2, filepos[a0], filesize[a0]); + #endif + + if (filepos[a0] >= filesize[a0]) + { + mipsinfo.i = 0; + } + else + { + uint8 *rp; + + if ((filepos[a0] + a2) > filesize[a0]) + { + a2 = filesize[a0] - filepos[a0]; + } + + rp = (uint8 *)cpu->psx_ram; + rp += (a1 & 0x1fffff); + memcpy(rp, &filedata[a0][filepos[a0]], a2); + + filepos[a0] += a2; + mipsinfo.i = a2; + } + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + case 8: // lseek + #if DEBUG_HLE_IOP + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo); + printf("IOP: lseek(%d, %d, %s) (PC=%08x)\n", a0, a1, seek_types[a2], mipsinfo.i); + #endif + + switch (a2) + { + case 0: // SEEK_SET + if (a1 <= filesize[a0]) + { + filepos[a0] = a1; + } + break; + case 1: // SEEK_CUR + if ((a1 + filepos[a0]) < filesize[a0]) + { + filepos[a0] += a1; + } + break; + case 2: // SEEK_END + filepos[a0] = filesize[a0] - a1; + break; + } + + mipsinfo.i = filepos[a0]; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + case 20: // AddDrv + #if DEBUG_HLE_IOP + printf("IOP: AddDrv(%x)\n", a0); + #endif + + mipsinfo.i = 0; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + case 21: // DelDrv + #if DEBUG_HLE_IOP + printf("IOP: DelDrv(%x)\n", a0); + #endif + + mipsinfo.i = 0; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo); + break; + + default: + printf("IOP: Unhandled service %d for module %s\n", callnum, name); + } + } + else + { + int lib; + + if (iNumLibs > 0) + { + for (lib = 0; lib < iNumLibs; lib++) + { + if (!strcmp(name, reglibs[lib].name)) + { + #if DEBUG_HLE_IOP + uint32 PC; + + mips_get_info(cpu, CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo); + PC = mipsinfo.i; + #endif + + // zap the delay slot handling + mipsinfo.i = 0; + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_DELAYV, &mipsinfo); + mips_set_info(cpu,CPUINFO_INT_REGISTER + MIPS_DELAYR, &mipsinfo); + + mipsinfo.i = LE32(cpu->psx_ram[(reglibs[lib].dispatch/4) + callnum]); + + // (NOTE: we get called in the delay slot!) + #if DEBUG_HLE_IOP + printf("IOP: Calling %s (%d) service %d => %08x (parms %08x %08x %08x %08x) (PC=%x)\n", + reglibs[lib].name, + lib, + callnum, + (uint32)mipsinfo.i, + a0, a1, a2, a3, PC); + #endif + + #if 0 + if (!strcmp(reglibs[lib].name, "ssd")) + { + if (callnum == 37) + { + psxcpu_verbose = 4096; + } + } + #endif + + mipsinfo.i -= 4; + mips_set_info(cpu,CPUINFO_INT_PC, &mipsinfo); + + return; + } + } + } + + printf("IOP: Unhandled service %d for module %s\n", callnum, name); + } +} + diff --git a/plugins/ao/eng_qsf/eng_qsf.c b/plugins/ao/eng_qsf/eng_qsf.c new file mode 100644 index 00000000..32c6c13d --- /dev/null +++ b/plugins/ao/eng_qsf/eng_qsf.c @@ -0,0 +1,523 @@ +/* + Audio Overload SDK - QSF file engine + + Copyright (c) 2007, R. Belmont and Richard Bannister. + + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +// +// eng_qsf.c +// by R. Belmont +// + +/* +The program section of a QSF file, once decompressed, contains a series of +data blocks of the form: + +3 bytes - ASCII section name tag +4 bytes - Starting offset (LSB-first) +4 bytes - Length (N) (LSB-first) +N bytes - Data + +The data is then loaded to the given starting offset in the section described +by the ASCII tag. + +The following sections are defined: + +"KEY" - Kabuki decryption key. This section should be 11 bytes and contain + the following: + 4 bytes - swap_key1 (MSB-first) + 4 bytes - swap_key2 (MSB-first) + 2 bytes - addr_key (MSB-first) + 1 bytes - xor_key +"Z80" - Z80 program ROM. +"SMP" - QSound sample ROM. + +If the KEY section isn't given or both swap_keys are zero, then it is assumed +that no encryption is used. +*/ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "ao.h" +#include "qsound.h" +#include "z80.h" + +#include "corlett.h" + +#define DEBUG_LOADER (0) + +// timer rate is 285 Hz +static const int32 samples_per_tick = 44100/285; + +typedef struct { + corlett_t *c; + char qsfby[256]; + uint32 skey1, skey2; + uint16 akey; + uint8 xkey; + int32 uses_kabuki; + char *Z80ROM, *QSamples; + char RAM[0x1000], RAM2[0x1000]; + char initRAM[0x1000], initRAM2[0x1000]; + int32 cur_bank; + z80_state_t *z80; + qsound_state_t *qs; + int32 samples_to_next_tick; +} qsf_synth_t; + +static struct QSound_interface qsintf = +{ + QSOUND_CLOCK, + NULL +}; + +uint8 qsf_memory_read(qsf_synth_t *s, uint16 addr); +uint8 qsf_memory_readport(qsf_synth_t *s, uint16 addr); +void qsf_memory_write(qsf_synth_t *s, uint16 addr, uint8 byte); +void qsf_memory_writeport(qsf_synth_t *s, uint16 addr, uint8 byte); + +/* redirect stubs to interface the Z80 core to the QSF engine */ +uint8 memory_read(void *userdata, uint16 addr) +{ + return qsf_memory_read(userdata, addr); +} + +uint8 memory_readop(void *userdata, uint16 addr) +{ + return memory_read(userdata, addr); +} + +uint8 memory_readport(void *userdata, uint16 addr) +{ + return qsf_memory_readport(userdata, addr); +} + +void memory_write(void *userdata, uint16 addr, uint8 byte) +{ + qsf_memory_write(userdata, addr, byte); +} + +void memory_writeport(void *userdata, uint16 addr, uint8 byte) +{ + qsf_memory_writeport(userdata, addr, byte); +} + +int32 qsf_stop(void *handle); + +static void qsf_walktags(qsf_synth_t *s, uint8 *buffer, uint8 *end) +{ + uint8 *cbuf = buffer; + uint32 offset, length; + + while (cbuf < end) + { + #if DEBUG_LOADER + printf("cbuf: %08x end: %08x\n", (uint32)cbuf, (uint32)end); + #endif + offset = cbuf[3] | cbuf[4]<<8 | cbuf[5]<<16 | cbuf[6]<<24; + length = cbuf[7] | cbuf[8]<<8 | cbuf[9]<<16 | cbuf[10]<<24; + + #if DEBUG_LOADER + printf("Tag: %c%c%c @ %08x, length %08x\n", cbuf[0], cbuf[1], cbuf[2], offset, length); + #endif + + switch (cbuf[0]) + { + case 'Z': + memcpy(&s->Z80ROM[offset], &cbuf[11], length); + break; + + case 'S': + memcpy(&s->QSamples[offset], &cbuf[11], length); + break; + + case 'K': + s->skey1 = cbuf[11]<<24 | cbuf[12]<<16 | cbuf[13]<<8 | cbuf[14]; + s->skey2 = cbuf[15]<<24 | cbuf[16]<<16 | cbuf[17]<<8 | cbuf[18]; + s->akey = cbuf[19]<<8 | cbuf[20]; + s->xkey = cbuf[20]; + break; + + default: + printf("ERROR: Unknown QSF tag!\n"); + break; + } + + cbuf += 11; + cbuf += length; + } +} + +static int32 qsf_irq_cb(int param) +{ + return 0x000000ff; // RST_38 +} + +void *qsf_start(const char *path, uint8 *buffer, uint32 length) +{ + qsf_synth_t *s = malloc (sizeof (qsf_synth_t)); + memset (s, 0, sizeof (qsf_synth_t)); + + uint8 *file, *lib_decoded, *lib_raw_file; + uint64 file_len, lib_len, lib_raw_length; + corlett_t *lib; + + s->z80 = z80_init(); + s->z80->userdata = s; + + s->Z80ROM = malloc(512*1024); + s->QSamples = malloc(8*1024*1024); + + s->skey1 = s->skey2 = 0; + s->akey = 0; + s->xkey = 0; + s->cur_bank = 0; + + // Decode the current QSF + if (corlett_decode(buffer, length, &file, &file_len, &s->c) != AO_SUCCESS) + { + return AO_FAIL; + } + + // Get the library file + if (s->c->lib[0] != 0) + { + uint64 tmp_length; + + char libpath[PATH_MAX]; + const char *e = path + strlen(path); + while (e > path && *e != '/') { + e--; + } + if (*e == '/') { + e++; + memcpy (libpath, path, e-path); + libpath[e-path] = 0; + strcat (libpath, s->c->lib); + } + else { + strcpy (libpath, s->c->lib); + } + +#if DEBUG_LOADER + printf("Loading library: %s\n", libpath); +#endif + if (ao_get_lib(libpath, &lib_raw_file, &tmp_length) != AO_SUCCESS) + { + qsf_stop (s); + return NULL; + } + lib_raw_length = tmp_length; + + if (corlett_decode(lib_raw_file, lib_raw_length, &lib_decoded, &lib_len, &lib) != AO_SUCCESS) + { + free(lib_raw_file); + qsf_stop (s); + return NULL; + } + + // Free up raw file + free(lib_raw_file); + + // use the contents + qsf_walktags(s, lib_decoded, lib_decoded+lib_len); + + // Dispose the corlett structure for the lib - we don't use it + free(lib); + } + + // now patch the file into RAM OVER the libraries + qsf_walktags(s, file, file+file_len); + + free(file); + + if ((s->skey1 != 0) && (s->skey2 != 0)) + { + #if DEBUG_LOADER + printf("Decoding Kabuki: skey1 %08x skey2 %08x akey %04x xkey %02x\n", skey1, skey2, akey, xkey); + #endif + + s->uses_kabuki = 1; + cps1_decode((unsigned char *)s->Z80ROM, s->skey1, s->skey2, s->akey, s->xkey); + } + + // set qsfby tag + strcpy(s->qsfby, "n/a"); + if (s->c) + { + int i; + for (i = 0; i < MAX_UNKNOWN_TAGS; i++) + { + if (!strcasecmp(s->c->tag_name[i], "qsfby")) + { + strcpy(s->qsfby, s->c->tag_data[i]); + } + } + } + + memcpy (s->initRAM, s->RAM, 0x1000); + memcpy (s->initRAM2, s->RAM2, 0x1000); + + if (s->z80) { + z80_reset(s->z80, NULL); + z80_set_irq_callback(s->z80, qsf_irq_cb); + } + qsintf.sample_rom = s->QSamples; + s->qs = qsound_sh_start(&qsintf); + s->samples_to_next_tick = samples_per_tick; + + return s; +} + +static void timer_tick(qsf_synth_t *s) +{ + z80_set_irq_line(s->z80, 0, ASSERT_LINE); + z80_set_irq_line(s->z80, 0, CLEAR_LINE); +} + +int32 qsf_gen(qsf_synth_t *s, int16 *buffer, uint32 samples) +{ + int16 output[44100/30], output2[44100/30]; + int16 *stereo[2]; + int16 *outp = buffer; + int32 i, opos, tickinc, loops; + + // our largest possible step is samples_per_tick or samples, whichever is smaller + if (s->samples_to_next_tick > samples) + { + tickinc = samples; + } + else + { + tickinc = s->samples_to_next_tick; + } + + loops = samples / tickinc; + opos = 0; + + for (i = 0; i < loops; i++) + { + z80_execute(s->z80, (8000000/44100)*tickinc); + stereo[0] = &output[opos]; + stereo[1] = &output2[opos]; + qsound_update(s->qs, 0, stereo, tickinc); + + opos += tickinc; + s->samples_to_next_tick -= tickinc; + + if (s->samples_to_next_tick <= 0) + { + timer_tick(s); + s->samples_to_next_tick = samples_per_tick; + } + } + + // are there "leftovers"? + if (opos < samples) + { + z80_execute(s->z80, (8000000/44100)*(samples-opos)); + stereo[0] = &output[opos]; + stereo[1] = &output2[opos]; + qsound_update(s->qs, 0, stereo, (samples-opos)); + + s->samples_to_next_tick -= (samples-opos); + + if (s->samples_to_next_tick <= 0) + { + timer_tick(s); + s->samples_to_next_tick = samples_per_tick; + } + } + + for (i = 0; i < samples; i++) + { + *outp++ = output[i]; + *outp++ = output2[i]; + } + + return AO_SUCCESS; +} + +int32 qsf_stop(void *handle) +{ + qsf_synth_t *s = (qsf_synth_t *)handle; + free(s->Z80ROM); + free(s->QSamples); + if (s->z80) { + z80_free (s->z80); + } + if (s->qs) { + qsound_sh_stop (s->qs); + } + free(s); + + return AO_SUCCESS; +} + +int32 qsf_command(void *handle, int32 command, int32 parameter) +{ + qsf_synth_t *s = handle; + switch (command) + { + case COMMAND_RESTART: + memcpy (s->RAM, s->initRAM, 0x1000); + memcpy (s->RAM2, s->initRAM2, 0x1000); + + if (s->z80) { + z80_reset(s->z80, NULL); + z80_set_irq_callback(s->z80, qsf_irq_cb); + } + qsound_sh_stop (s->qs); + s->qs = qsound_sh_start(&qsintf); + s->samples_to_next_tick = samples_per_tick; + return AO_SUCCESS; + + } + return AO_FAIL; +} + +int32 qsf_fill_info(void *handle, ao_display_info *info) +{ + qsf_synth_t *s = handle; + if (s->c == NULL) + return AO_FAIL; + + strcpy(info->title[1], "Name: "); + sprintf(info->info[1], "%s", s->c->inf_title); + + strcpy(info->title[2], "Game: "); + sprintf(info->info[2], "%s", s->c->inf_game); + + strcpy(info->title[3], "Artist: "); + sprintf(info->info[3], "%s", s->c->inf_artist); + + strcpy(info->title[4], "Copyright: "); + sprintf(info->info[4], "%s", s->c->inf_copy); + + strcpy(info->title[5], "Year: "); + sprintf(info->info[5], "%s", s->c->inf_year); + + strcpy(info->title[6], "Length: "); + sprintf(info->info[6], "%s", s->c->inf_length); + + strcpy(info->title[7], "Fade: "); + sprintf(info->info[7], "%s", s->c->inf_fade); + + strcpy(info->title[8], "Ripper: "); + sprintf(info->info[8], "%s", s->qsfby); + + return AO_SUCCESS; +} + +uint8 qsf_memory_read(qsf_synth_t *s, uint16 addr) +{ + if (addr < 0x8000) + { + return s->Z80ROM[addr]; + } + else if (addr < 0xc000) + { + return s->Z80ROM[(addr - 0x8000) + s->cur_bank]; + } + else if (addr <= 0xcfff) + { + return s->RAM[addr - 0xc000]; + } + else if (addr == 0xd007) + { + return qsound_status_r(s->qs); + } + else if (addr >= 0xf000) + { + return s->RAM2[addr-0xf000]; + } + return 0; +} + +uint8 qsf_memory_readop(qsf_synth_t *s, uint16 addr) +{ + if (!s->uses_kabuki) + { + return qsf_memory_read(s, addr); + } + + if (addr < 0x8000) + { + return s->Z80ROM[addr + (256*1024)]; + } + + return qsf_memory_read(s, addr); +} + +uint8 qsf_memory_readport(qsf_synth_t *s, uint16 addr) +{ + return s->Z80ROM[0x11]; +} + +void qsf_memory_write(qsf_synth_t *s, uint16 addr, uint8 byte) +{ + if (addr >= 0xc000 && addr <= 0xcfff) + { + + s->RAM[addr-0xc000] = byte; + return; + } + else if (addr == 0xd000) + { + qsound_data_h_w(s->qs, byte); + return; + } + else if (addr == 0xd001) + { + qsound_data_l_w(s->qs, byte); + return; + } + else if (addr == 0xd002) + { + qsound_cmd_w(s->qs, byte); + return; + } + else if (addr == 0xd003) + { + s->cur_bank = (0x8000 + (byte & 0xf) * 0x4000); + if (s->cur_bank > (256*1024)) + { + s->cur_bank = 0; + } +// printf("Z80 bank to %x (%x)\n", cur_bank, byte); + return; + } + else if (addr >= 0xf000) + { + s->RAM2[addr-0xf000] = byte; + return; + } +} + +void qsf_memory_writeport(qsf_synth_t *s, uint16 addr, uint8 byte) +{ + printf("Unk port %x @ %x\n", byte, addr); +} + diff --git a/plugins/ao/eng_qsf/kabuki.c b/plugins/ao/eng_qsf/kabuki.c new file mode 100644 index 00000000..61100304 --- /dev/null +++ b/plugins/ao/eng_qsf/kabuki.c @@ -0,0 +1,156 @@ +/*************************************************************************** + +"Kabuki" Z80 encryption + + +The "Kabuki" is a custom Z80 module which runs encrypted code. The encryption +key is stored in some battery-backed RAM, therefore the chip has the annoying +habit of stopping working every few years, when the battery dies. +Check at the bottom of this text to see a list of all the known games which +use this chip. + + +How it works: +The base operation is a bit swap which affects couples of adjacent bits. +Each of the 4 couples may or may not be swapped, depending on the address of +the byte and on whether it is an opcode or data. +The decryption consists of these steps: +- bitswap +- ROL +- bitswap +- XOR with a key +- ROL +- bitswap +- ROL +- bitswap + +To know how to apply the bit swap, take the address of the byte to decode and: +- if the byte is an opcode, add addr_key to the address +- if the byte is data, XOR the address with 1FC0, add 1, and then add addr_key +You'll get a 16-bit word. The first two bitswaps depend on bits 0-7 of that +word, while the second two on bits 8-15. When a bit in the word is 1, swap the +two bits, oherwise don't. The exact couple of bits affected depends on the +game and is identified in this file with two keys: swap_key1 and swap_key2 +(which are just permutations of the numbers 0-7, not full 32-bit integers). + + +Key space size: +- swap_key1 8! = 40320 +- swap_key2 8! = 40320 +- addr_key 2^16 = 65536 +- xor_key 2^8 = 256 +- total 2.7274 * 10^16 + + +Weaknesses: +- 0x00 and 0xff, having all the bits set to the same value, are not affected + by bit permutations after the XOR. Therefore, their encryption is the same + regardless of the high 8 bits of the address, and of the value of + swap_key2. If there is a long stream of 0x00 or 0xff in the original data, + this can be used to find by brute force all the candidates for swap_key1, + xor_key, and for the low 8 bits of addr_key. This is a serious weakness + which dramatically reduces the security of the encryption. +- A 0x00 is always encrypted as a byte with as many 1s as xor_key; a 0xff is + always encrypted as a byte with as many 0s as xor_key has 1s. So you just + need to know one 0x00 or 0xff in the unencrypted data to know how many 1s + there are in xor_key. +- Once you have restricted the range for swap_key1 and you know the number of + 1s in the xor_key, you can easily use known plaintext attacks and brute + force to find the remaining keys. Long strings like THIS GAME IS FOR USE IN + and ABCDEFGHIJKLMNOPQRSTUVWXYZ can be found by comparing the number of 1s + in the clear and encrypted data, taking xor_key into account. When you have + found where the string is, use brute force to reduce the key space. + + +Known games: + swap_key1 swap_key2 addr_key xor_key +Mahjong Gakuen 2 Gakuen-chou no Fukushuu 76543210 01234567 aa55 a5 +Poker Ladies " " " " "" "" +Dokaben " " " " "" "" +Dokaben 2 unknown +Pang / Buster Bros / Pomping World 01234567 76543210 6548 24 +Capcom Baseball " " " " "" "" +Capcom World 04152637 40516273 5751 43 +Adventure Quiz 2 Hatena ? no Dai-Bouken 45670123 45670123 5751 43 +Super Pang 45670123 45670123 5852 43 +Super Buster Bros 45670123 45670123 2130 12 +Super Marukin-Ban 54321076 54321076 4854 4f +Quiz Tonosama no Yabou 12345670 12345670 1111 11 +Ashita Tenki ni Naare unknown +Quiz Sangokushi 23456701 23456701 1828 18 +Block Block 02461357 64207531 0002 01 + +Warriors of Fate 01234567 54163072 5151 51 +Cadillacs and Dinosaurs 76543210 24601357 4343 43 +Punisher 67452103 75316024 2222 22 +Slam Masters 54321076 65432107 3131 19 + +***************************************************************************/ + +#include "cpuintrf.h" + +static int bitswap1(int src,int key,int sel) +{ + if (sel & (1 << ((key >> 0) & 7))) + src = (src & 0xfc) | ((src & 0x01) << 1) | ((src & 0x02) >> 1); + if (sel & (1 << ((key >> 4) & 7))) + src = (src & 0xf3) | ((src & 0x04) << 1) | ((src & 0x08) >> 1); + if (sel & (1 << ((key >> 8) & 7))) + src = (src & 0xcf) | ((src & 0x10) << 1) | ((src & 0x20) >> 1); + if (sel & (1 << ((key >>12) & 7))) + src = (src & 0x3f) | ((src & 0x40) << 1) | ((src & 0x80) >> 1); + + return src; +} + +static int bitswap2(int src,int key,int sel) +{ + if (sel & (1 << ((key >>12) & 7))) + src = (src & 0xfc) | ((src & 0x01) << 1) | ((src & 0x02) >> 1); + if (sel & (1 << ((key >> 8) & 7))) + src = (src & 0xf3) | ((src & 0x04) << 1) | ((src & 0x08) >> 1); + if (sel & (1 << ((key >> 4) & 7))) + src = (src & 0xcf) | ((src & 0x10) << 1) | ((src & 0x20) >> 1); + if (sel & (1 << ((key >> 0) & 7))) + src = (src & 0x3f) | ((src & 0x40) << 1) | ((src & 0x80) >> 1); + + return src; +} + +static int bytedecode(int src,int swap_key1,int swap_key2,int xor_key,int sel) +{ + src = bitswap1(src,swap_key1 & 0xffff,sel & 0xff); + src = ((src & 0x7f) << 1) | ((src & 0x80) >> 7); + src = bitswap2(src,swap_key1 >> 16,sel & 0xff); + src ^= xor_key; + src = ((src & 0x7f) << 1) | ((src & 0x80) >> 7); + src = bitswap2(src,swap_key2 & 0xffff,sel >> 8); + src = ((src & 0x7f) << 1) | ((src & 0x80) >> 7); + src = bitswap1(src,swap_key2 >> 16,sel >> 8); + return src; +} + +static void kabuki_decode(unsigned char *src,unsigned char *dest_op,unsigned char *dest_data, + int base_addr,int length,int swap_key1,int swap_key2,int addr_key,int xor_key) +{ + int A; + int sel; + + for (A = 0; A < length; A++) + { + /* decode opcodes */ + sel = (A + base_addr) + addr_key; + dest_op[A] = bytedecode(src[A],swap_key1,swap_key2,xor_key,sel); + + /* decode data */ + sel = ((A + base_addr) ^ 0x1fc0) + addr_key + 1; + dest_data[A] = bytedecode(src[A],swap_key1,swap_key2,xor_key,sel); + } +} + +void cps1_decode(unsigned char *rom, int swap_key1,int swap_key2,int addr_key,int xor_key) +{ + int diff = (512*1024)/2; + + kabuki_decode(rom, rom+diff, rom, 0x0000, 0x8000, swap_key1, swap_key2, addr_key, xor_key); +} diff --git a/plugins/ao/eng_qsf/qsound.c b/plugins/ao/eng_qsf/qsound.c new file mode 100644 index 00000000..b11829d4 --- /dev/null +++ b/plugins/ao/eng_qsf/qsound.c @@ -0,0 +1,442 @@ +/*************************************************************************** + + Capcom System QSound(tm) + ======================== + + Driver by Paul Leaman (paul@vortexcomputing.demon.co.uk) + and Miguel Angel Horna (mahorna@teleline.es) + + A 16 channel stereo sample player. + + QSpace position is simulated by panning the sound in the stereo space. + + Register + 0 xxbb xx = unknown bb = start high address + 1 ssss ssss = sample start address + 2 pitch + 3 unknown (always 0x8000) + 4 loop offset from end address + 5 end + 6 master channel volume + 7 not used + 8 Balance (left=0x0110 centre=0x0120 right=0x0130) + 9 unknown (most fixed samples use 0 for this register) + + Many thanks to CAB (the author of Amuse), without whom this probably would + never have been finished. + + If anybody has some information about this hardware, please send it to me + to mahorna@teleline.es or 432937@cepsz.unizar.es. + http://teleline.terra.es/personal/mahorna + +***************************************************************************/ + +#include <math.h> +#include "cpuintrf.h" +#include "qsound.h" + +#if 0 +#if QSOUND_DRIVER2 +void setchannel(int channel,signed short *buffer,int length,int vol,int pan); +void setchloop(int channel,int loops,int loope); +void stopchan(int channel); +void calcula_mix(int channel); +#endif +#endif + +qsound_state_t *qsound_sh_start( struct QSound_interface *qsintf ) +{ + qsound_state_t *qs = malloc (sizeof (qsound_state_t)); + memset (qs, 0, sizeof (qsound_state_t)); + memcpy (&qs->intf, qsintf, sizeof (struct QSound_interface)); + + int i; + + qs->qsound_sample_rom = (QSOUND_SRC_SAMPLE *)qs->intf.sample_rom; + + memset(qs->qsound_channel, 0, sizeof(qs->qsound_channel)); + +#if QSOUND_DRIVER1 + qs->qsound_frq_ratio = ((float)qs->intf.clock / (float)QSOUND_CLOCKDIV) / + (float) 44100; + qs->qsound_frq_ratio *= 16.0; + + /* Create pan table */ + for (i=0; i<33; i++) + { + qs->qsound_pan_table[i]=(int)((256/sqrt(32)) * sqrt(i)); + } +#else + i=0; +#endif + +#if LOG_QSOUND + logerror("Pan table\n"); + for (i=0; i<33; i++) + logerror("%02x ", qs->qsound_pan_table[i]); +#endif +#if 0 + { + /* Allocate stream */ +#define CHANNELS ( 2 ) + char buf[CHANNELS][40]; + const char *name[CHANNELS]; + int vol[2]; + name[0] = buf[0]; + name[1] = buf[1]; + sprintf( buf[0], "%s L", sound_name(msound) ); + sprintf( buf[1], "%s R", sound_name(msound) ); + vol[0]=MIXER(intf->mixing_level[0], MIXER_PAN_LEFT); + vol[1]=MIXER(intf->mixing_level[1], MIXER_PAN_RIGHT); + qsound_stream = stream_init_multi( + CHANNELS, + name, + vol, + Machine->sample_rate, + 0, + qsound_update ); + } +#endif +#if LOG_WAVE + qs->fpRawDataR=fopen("qsoundr.raw", "w+b"); + qs->fpRawDataL=fopen("qsoundl.raw", "w+b"); + if (!qs->fpRawDataR || !qs->fpRawDataL) + { + return NULL; + } +#endif + + return qs; +} + +void qsound_sh_stop (qsound_state_t *qs) +{ + if (qs) { +#if LOG_WAVE + if (qs->fpRawDataR) + { + fclose(qs->fpRawDataR); + } + if (qs->fpRawDataL) + { + fclose(qs->fpRawDataL); + } +#endif + free (qs); + } +} + +void qsound_data_h_w(qsound_state_t *qs, int data) +{ + qs->qsound_data=(qs->qsound_data&0xff)|(data<<8); +} + +void qsound_data_l_w(qsound_state_t *qs, int data) +{ + qs->qsound_data=(qs->qsound_data&0xff00)|data; +} + +void qsound_cmd_w(qsound_state_t *qs, int data) +{ +// printf("QS: cmd %x, data %x\n", data, qs->qsound_data); + qsound_set_command(qs, data, qs->qsound_data); +} + +int qsound_status_r(qsound_state_t *qs) +{ + /* Port ready bit (0x80 if ready) */ + return 0x80; +} + +void qsound_set_command(qsound_state_t *qs, int data, int value) +{ + int ch=0,reg=0; + if (data < 0x80) + { + ch=data>>3; + reg=data & 0x07; + } + else + { + if (data < 0x90) + { + ch=data-0x80; + reg=8; + } + else + { + if (data >= 0xba && data < 0xca) + { + ch=data-0xba; + reg=9; + } + else + { + /* Unknown registers */ + ch=99; + reg=99; + } + } + } + + switch (reg) + { + case 0: /* Bank */ + ch=(ch+1)&0x0f; /* strange ... */ + qs->qsound_channel[ch].bank=(value&0x7f)<<16; + qs->qsound_channel[ch].bank /= LENGTH_DIV; +#ifdef MAME_DEBUG + if (!value & 0x8000) + { + char baf[40]; + sprintf(baf,"Register3=%04x",value); + usrintf_showmessage(baf); + } +#endif + + break; + case 1: /* start */ +// printf("QS: key on ch %02d\n", ch); + qs->qsound_channel[ch].address=value; + qs->qsound_channel[ch].address/=LENGTH_DIV; + break; + case 2: /* pitch */ +#if QSOUND_DRIVER1 + qs->qsound_channel[ch].pitch=(long) + ((float)value * qs->qsound_frq_ratio ); + qs->qsound_channel[ch].pitch/=LENGTH_DIV; +#else + qs->qsound_channel[ch].factor=((float) (value*(6/LENGTH_DIV)) / + (float) Machine->sample_rate)*256.0; + +#endif + if (!value) + { + /* Key off */ +// printf("QS: key off ch %02d\n", ch); + qs->qsound_channel[ch].key=0; + } + break; + case 3: /* unknown */ + qs->qsound_channel[ch].reg3=value; +#ifdef MAME_DEBUG + if (value != 0x8000) + { + char baf[40]; + sprintf(baf,"Register3=%04x",value); + usrintf_showmessage(baf); + } +#endif + break; + case 4: /* loop offset */ + qs->qsound_channel[ch].loop=value/LENGTH_DIV; + break; + case 5: /* end */ + qs->qsound_channel[ch].end=value/LENGTH_DIV; + break; + case 6: /* master volume */ + if (value==0) + { + /* Key off */ + qs->qsound_channel[ch].key=0; + } + else if (qs->qsound_channel[ch].key==0) + { + /* Key on */ + qs->qsound_channel[ch].key=1; +#if QSOUND_DRIVER1 + qs->qsound_channel[ch].offset=0; + qs->qsound_channel[ch].lastdt=0; +#else + qs->qsound_channel[ch].cursor=qs->qsound_channel[ch].address <<8 ; + qs->qsound_channel[ch].buffer=qsound_sample_rom+ + qs->qsound_channel[ch].bank; +#endif + } + qs->qsound_channel[ch].vol=value; +#if QSOUND_DRIVER2 + calcula_mix(ch); +#endif + break; + + case 7: /* unused */ +#ifdef MAME_DEBUG + { + char baf[40]; + sprintf(baf,"UNUSED QSOUND REG 7=%04x",value); + usrintf_showmessage(baf); + } +#endif + + break; + case 8: + { +#if QSOUND_DRIVER1 + int pandata=(value-0x10)&0x3f; + if (pandata > 32) + { + pandata=32; + } + qs->qsound_channel[ch].rvol=qs->qsound_pan_table[pandata]; + qs->qsound_channel[ch].lvol=qs->qsound_pan_table[32-pandata]; +#endif + qs->qsound_channel[ch].pan = value; +#if QSOUND_DRIVER2 + calcula_mix(ch); +#endif + } + break; + case 9: + qs->qsound_channel[ch].reg9=value; +/* +#ifdef MAME_DEBUG + { + char baf[40]; + sprintf(baf,"QSOUND REG 9=%04x",value); + usrintf_showmessage(baf); + } +#endif +*/ + break; + } +#if LOG_QSOUND + logerror("QSOUND WRITE %02x CH%02d-R%02d =%04x\n", data, ch, reg, value); +#endif +} + +#if QSOUND_DRIVER1 + +/* Driver 1 - based on the Amuse source */ + +void qsound_update(qsound_state_t *qs, int num, INT16 **buffer, int length ) +{ + int i,j; + int rvol, lvol, count; + struct QSOUND_CHANNEL *pC=&qs->qsound_channel[0]; + QSOUND_SRC_SAMPLE * pST; + QSOUND_SAMPLE *datap[2]; + + datap[0] = buffer[0]; + datap[1] = buffer[1]; + memset( datap[0], 0x00, length * sizeof(QSOUND_SAMPLE) ); + memset( datap[1], 0x00, length * sizeof(QSOUND_SAMPLE) ); + + + for (i=0; i<QSOUND_CHANNELS; i++) + { + if (pC->key) + { + QSOUND_SAMPLE *pOutL=datap[0]; + QSOUND_SAMPLE *pOutR=datap[1]; + pST=qs->qsound_sample_rom+pC->bank; + + rvol=(pC->rvol*pC->vol)>>(8*LENGTH_DIV); + lvol=(pC->lvol*pC->vol)>>(8*LENGTH_DIV); + + for (j=length-1; j>=0; j--) + { + count=(pC->offset)>>16; + pC->offset &= 0xffff; + if (count) + { + pC->address += count; + if (pC->address >= pC->end) + { + if (!pC->loop) + { + /* Reached the end of a non-looped sample */ + pC->key=0; + break; + } + /* Reached the end, restart the loop */ + pC->address = (pC->end - pC->loop) & 0xffff; + } + pC->lastdt = pST[pC->address]; + } + + (*pOutL) += ((pC->lastdt * lvol) >> 6); + (*pOutR) += ((pC->lastdt * rvol) >> 6); + pOutL++; + pOutR++; + pC->offset += pC->pitch; + } + } + pC++; + } + +#if LOG_WAVE + fwrite(datap[0], length*sizeof(QSOUND_SAMPLE), 1, fpRawDataL); + fwrite(datap[1], length*sizeof(QSOUND_SAMPLE), 1, fpRawDataR); +#endif +} + +#else + +/* ---------------------------------------------------------------- + QSound Sample Mixer (Slow) + Miguel Angel Horna mahorna@teleline.es + + ------------------------------------------------------------------ */ + + +void calcula_mix(int channel) +{ + int factl,factr; + struct qs->qsound_channel *pC=&qs->qsound_channel[channel]; + int vol=pC->vol>>5; + int pan=((pC->pan&0xFF)-0x10)<<3; + pC->mixl=vol; + pC->mixr=vol; + factr=pan; + factl=255-factr; + pC->mixl=(pC->mixl * factl)>>8; + pC->mixr=(pC->mixr * factr)>>8; +#if QSOUND_8BIT_SAMPLES + pC->mixl<<=8; + pC->mixr<<=8; +#endif +} + +void qsound_update(int num,void **buffer,int length) +{ + int i,j; + QSOUND_SAMPLE *bufL,*bufR, sample; + struct qs->qsound_channel *pC=qs->qsound_channel; + + memset( buffer[0], 0x00, length * sizeof(QSOUND_SAMPLE) ); + memset( buffer[1], 0x00, length * sizeof(QSOUND_SAMPLE) ); + + for(j=0;j<qs->qsound_channelS;++j) + { + bufL=(QSOUND_SAMPLE *) buffer[0]; + bufR=(QSOUND_SAMPLE *) buffer[1]; + if(pC->key) + { + for(i=0;i<length;++i) + { + int pos=pC->cursor>>8; + if(pos!=pC->lpos) /*next sample*/ + { + sample=pC->buffer[pos]; + pC->lastsaml=(sample*pC->mixl)>>8; + pC->lastsamr=(sample*pC->mixr)>>8; + pC->lpos=pos; + } + (*bufL++)+=pC->lastsaml; + (*bufR++)+=pC->lastsamr; + pC->cursor+=pC->factor; + if(pC->loop && (pC->cursor>>8) > pC->end) + { + pC->cursor=(pC->end-pC->loop)<<8; + } + else if((pC->cursor>>8) > pC->end) + pC->key=0; + } + } + pC++; + } +} +#endif + + +/**************** end of file ****************/ diff --git a/plugins/ao/eng_qsf/qsound.h b/plugins/ao/eng_qsf/qsound.h new file mode 100644 index 00000000..3d4538a6 --- /dev/null +++ b/plugins/ao/eng_qsf/qsound.h @@ -0,0 +1,117 @@ +/********************************************************* + + Capcom Q-Sound system + +*********************************************************/ + +#ifndef __QSOUND_H__ +#define __QSOUND_H__ + +#define QSOUND_CLOCK 4000000 /* default 4MHz clock */ + +struct QSound_interface +{ + int clock; /* clock */ + char *sample_rom; /* sample data */ +}; + + +/* +Two Q sound drivers: +DRIVER1 Based on the Amuse source +DRIVER2 Miguel Angel Horna (mahorna@teleline.es) +*/ +#define QSOUND_DRIVER1 1 +/* +I don't know whether this system uses 8 bit or 16 bit samples. +If it uses 16 bit samples then the sample ROM loading macros need +to be modified to work with non-intel machines. +*/ +#define QSOUND_8BIT_SAMPLES 1 + +/* +Debug defines +*/ +#define LOG_WAVE 0 +#define LOG_QSOUND 0 + +/* Typedefs & defines */ + +#define QSOUND_DRIVER2 !QSOUND_DRIVER1 + +#if QSOUND_8BIT_SAMPLES +/* 8 bit source ROM samples */ +typedef signed char QSOUND_SRC_SAMPLE; +#define LENGTH_DIV 1 +#else +/* 8 bit source ROM samples */ +typedef signed short QSOUND_SRC_SAMPLE; +#define LENGTH_DIV 2 +#endif + +#define QSOUND_CLOCKDIV 166 /* Clock divider */ +#define QSOUND_CHANNELS 16 +typedef INT16 QSOUND_SAMPLE; + +struct QSOUND_CHANNEL +{ + int bank; /* bank (x16) */ + int address; /* start address */ + int pitch; /* pitch */ + int reg3; /* unknown (always 0x8000) */ + int loop; /* loop address */ + int end; /* end address */ + int vol; /* master volume */ + int pan; /* Pan value */ + int reg9; /* unknown */ + + /* Work variables */ + int key; /* Key on / key off */ + +#if QSOUND_DRIVER1 + int lvol; /* left volume */ + int rvol; /* right volume */ + int lastdt; /* last sample value */ + int offset; /* current offset counter */ +#else + QSOUND_SRC_SAMPLE *buffer; + int factor; /*step factor (fixed point 8-bit)*/ + int mixl,mixr; /*mixing factor (fixed point)*/ + int cursor; /*current sample position (fixed point)*/ + int lpos; /*last cursor pos*/ + int lastsaml; /*last left sample (to avoid any calculation)*/ + int lastsamr; /*last right sample*/ +#endif +}; + + +typedef struct { + /* Private variables */ + struct QSound_interface intf; /* Interface */ + int qsound_stream; /* Audio stream */ + struct QSOUND_CHANNEL qsound_channel[QSOUND_CHANNELS]; + int qsound_data; /* register latch data */ + QSOUND_SRC_SAMPLE *qsound_sample_rom; /* Q sound sample ROM */ + +#if QSOUND_DRIVER1 + int qsound_pan_table[33]; /* Pan volume table */ + float qsound_frq_ratio; /* Frequency ratio */ +#endif + +#if LOG_WAVE + FILE *fpRawDataL; + FILE *fpRawDataR; +#endif +} qsound_state_t; + +qsound_state_t *qsound_sh_start(struct QSound_interface *qsintf); +void qsound_sh_stop(qsound_state_t *qs); + +void qsound_data_h_w(qsound_state_t *qs, int data); +void qsound_data_l_w(qsound_state_t *qs, int data); +void qsound_cmd_w(qsound_state_t *qs, int data); +int qsound_status_r(qsound_state_t *qs); +void qsound_update(qsound_state_t *qs, int num, INT16 **buffer, int length); +void qsound_set_command(qsound_state_t *qs, int data, int value); + +#endif /* __QSOUND_H__ */ diff --git a/plugins/ao/eng_qsf/z80.c b/plugins/ao/eng_qsf/z80.c new file mode 100644 index 00000000..ddcd57ce --- /dev/null +++ b/plugins/ao/eng_qsf/z80.c @@ -0,0 +1,4425 @@ +/***************************************************************************** + * + * z80.c + * Portable Z80 emulator V3.5 + * + * Copyright (C) 1998,1999,2000 Juergen Buchmueller, all rights reserved. + * + * - This source code is released as freeware for non-commercial purposes. + * - You are free to use and redistribute this code in modified or + * unmodified form, provided you list me in the credits. + * - If you modify this source code, you must add a notice to each modified + * source file that it has been changed. If you're a nice person, you + * will clearly mark each change too. :) + * - If you wish to use this for commercial purposes, please contact me at + * pullmoll@t-online.de + * - The author of this copywritten work reserves the right to change the + * terms of its usage and license at any time, including retroactively + * - This entire notice must remain in the source code. + * + * Changes in 3.5 + * - Implemented OTIR, INIR, etc. without look-up table for PF flag. + * [Ramsoft, Sean Young] + * Changes in 3.4 + * - Removed Z80-MSX specific code as it's not needed any more. + * - Implemented DAA without look-up table [Ramsoft, Sean Young] + * Changes in 3.3 + * - Fixed undocumented flags XF & YF in the non-asm versions of CP, + * and all the 16 bit arithmetic instructions. [Sean Young] + * Changes in 3.2 + * - Fixed undocumented flags XF & YF of RRCA, and CF and HF of + * INI/IND/OUTI/OUTD/INIR/INDR/OTIR/OTDR [Sean Young] + * Changes in 3.1 + * - removed the REPEAT_AT_ONCE execution of LDIR/CPIR etc. opcodes + * for readabilities sake and because the implementation was buggy + * (and I was not able to find the difference) + * Changes in 3.0 + * - 'finished' switch to dynamically overrideable cycle count tables + * Changes in 2.9: + * - added methods to access and override the cycle count tables + * - fixed handling and timing of multiple DD/FD prefixed opcodes + * Changes in 2.8: + * - OUTI/OUTD/OTIR/OTDR also pre-decrement the B register now. + * This was wrong because of a bug fix on the wrong side + * (astrocade sound driver). + * Changes in 2.7: + * - removed z80_vm specific code, it's not needed (and never was). + * Changes in 2.6: + * - BUSY_LOOP_HACKS needed to call change_pc16() earlier, before + * checking the opcodes at the new address, because otherwise they + * might access the old (wrong or even NULL) banked memory region. + * Thanks to Sean Young for finding this nasty bug. + * Changes in 2.5: + * - Burning cycles always adjusts the ICount by a multiple of 4. + * - In REPEAT_AT_ONCE cases the R register wasn't incremented twice + * per repetition as it should have been. Those repeated opcodes + * could also underflow the ICount. + * - Simplified TIME_LOOP_HACKS for BC and added two more for DE + HL + * timing loops. I think those hacks weren't endian safe before too. + * Changes in 2.4: + * - z80_reset zaps the entire context, sets IX and IY to 0xffff(!) and + * sets the Z flag. With these changes the Tehkan World Cup driver + * _seems_ to work again. + * Changes in 2.3: + * - External termination of the execution loop calls z80_burn() and + * z80_vm_burn() to burn an amount of cycles (R adjustment) + * - Shortcuts which burn CPU cycles (BUSY_LOOP_HACKS and TIME_LOOP_HACKS) + * now also adjust the R register depending on the skipped opcodes. + * Changes in 2.2: + * - Fixed bugs in CPL, SCF and CCF instructions flag handling. + * - Changed variable EA and ARG16() function to UINT32; this + * produces slightly more efficient code. + * - The DD/FD XY CB opcodes where XY is 40-7F and Y is not 6/E + * are changed to calls to the X6/XE opcodes to reduce object size. + * They're hardly ever used so this should not yield a speed penalty. + * New in 2.0: + * - Optional more exact Z80 emulation (#define Z80_EXACT 1) according + * to a detailed description by Sean Young which can be found at: + * http://www.msxnet.org/tech/z80-documented.pdf + *****************************************************************************/ + +#include "ao.h" + +#include "cpuintrf.h" +#include "z80.h" + +#include "mem.h" + +static UINT8 z80_reg_layout[] = { + Z80_PC, Z80_SP, Z80_AF, Z80_BC, Z80_DE, Z80_HL, -1, + Z80_IX, Z80_IY, Z80_AF2,Z80_BC2,Z80_DE2,Z80_HL2,-1, + Z80_R, Z80_I, Z80_IM, Z80_IFF1,Z80_IFF2, -1, + Z80_NMI_STATE,Z80_IRQ_STATE,Z80_DC0,Z80_DC1,Z80_DC2,Z80_DC3, 0 +}; + +static UINT8 z80_win_layout[] = { + 27, 0,53, 4, /* register window (top rows) */ + 0, 0,26,22, /* disassembler window (left colums) */ + 27, 5,53, 8, /* memory #1 window (right, upper middle) */ + 27,14,53, 8, /* memory #2 window (right, lower middle) */ + 0,23,80, 1, /* command line window (bottom rows) */ +}; + +#define CF 0x01 +#define NF 0x02 +#define PF 0x04 +#define VF PF +#define XF 0x08 +#define HF 0x10 +#define YF 0x20 +#define ZF 0x40 +#define SF 0x80 + +#define INT_IRQ 0x01 +#define NMI_IRQ 0x02 + +#define _PPC z80->Z80.PREPC.d /* previous program counter */ + +#define _PCD z80->Z80.PC.d +#define _PC z80->Z80.PC.w.l + +#define _SPD z80->Z80.SP.d +#define _SP z80->Z80.SP.w.l + +#define _AFD z80->Z80.AF.d +#define _AF z80->Z80.AF.w.l +#define _Z80_A z80->Z80.AF.b.h +#define _F z80->Z80.AF.b.l + +#define _BCD z80->Z80.BC.d +#define _BC z80->Z80.BC.w.l +#define _Z80_B z80->Z80.BC.b.h +#define _Z80_C z80->Z80.BC.b.l + +#define _DED z80->Z80.DE.d +#define _DE z80->Z80.DE.w.l +#define _Z80_D z80->Z80.DE.b.h +#define _Z80_E z80->Z80.DE.b.l + +#define _HLD z80->Z80.HL.d +#define _HL z80->Z80.HL.w.l +#define _Z80_H z80->Z80.HL.b.h +#define _Z80_L z80->Z80.HL.b.l + +#define _IXD z80->Z80.IX.d +#define _IX z80->Z80.IX.w.l +#define _HX z80->Z80.IX.b.h +#define _LX z80->Z80.IX.b.l + +#define _IYD z80->Z80.IY.d +#define _IY z80->Z80.IY.w.l +#define _HY z80->Z80.IY.b.h +#define _LY z80->Z80.IY.b.l + +#define _Z80_I z80->Z80.I +#define _Z80_R z80->Z80.R +#define _R2 z80->Z80.R2 +#define _IM z80->Z80.IM +#define _IFF1 z80->Z80.IFF1 +#define _IFF2 z80->Z80.IFF2 +#define _HALT z80->Z80.HALT + +static const UINT8 cc_op[0x100] = { + 4,10, 7, 6, 4, 4, 7, 4, 4,11, 7, 6, 4, 4, 7, 4, + 8,10, 7, 6, 4, 4, 7, 4,12,11, 7, 6, 4, 4, 7, 4, + 7,10,16, 6, 4, 4, 7, 4, 7,11,16, 6, 4, 4, 7, 4, + 7,10,13, 6,11,11,10, 4, 7,11,13, 6, 4, 4, 7, 4, + 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, + 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, + 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, + 7, 7, 7, 7, 7, 7, 4, 7, 4, 4, 4, 4, 4, 4, 7, 4, + 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, + 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, + 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, + 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, + 5,10,10,10,10,11, 7,11, 5,10,10, 0,10,17, 7,11, + 5,10,10,11,10,11, 7,11, 5, 4,10,11,10, 0, 7,11, + 5,10,10,19,10,11, 7,11, 5, 4,10, 4,10, 0, 7,11, + 5,10,10, 4,10,11, 7,11, 5, 6,10, 4,10, 0, 7,11}; + +static const UINT8 cc_cb[0x100] = { + 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, + 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, + 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, + 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, + 8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8, + 8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8, + 8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8, + 8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8, + 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, + 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, + 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, + 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, + 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, + 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, + 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, + 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8}; + +static const UINT8 cc_ed[0x100] = { + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, +12,12,15,20, 8, 8, 8, 9,12,12,15,20, 8, 8, 8, 9, +12,12,15,20, 8, 8, 8, 9,12,12,15,20, 8, 8, 8, 9, +12,12,15,20, 8, 8, 8,18,12,12,15,20, 8, 8, 8,18, +12,12,15,20, 8, 8, 8, 8,12,12,15,20, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, +16,16,16,16, 8, 8, 8, 8,16,16,16,16, 8, 8, 8, 8, +16,16,16,16, 8, 8, 8, 8,16,16,16,16, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}; + +static const UINT8 cc_xy[0x100] = { + 4, 4, 4, 4, 4, 4, 4, 4, 4,15, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4,15, 4, 4, 4, 4, 4, 4, + 4,14,20,10, 9, 9, 9, 4, 4,15,20,10, 9, 9, 9, 4, + 4, 4, 4, 4,23,23,19, 4, 4,15, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 9, 9,19, 4, 4, 4, 4, 4, 9, 9,19, 4, + 4, 4, 4, 4, 9, 9,19, 4, 4, 4, 4, 4, 9, 9,19, 4, + 9, 9, 9, 9, 9, 9,19, 9, 9, 9, 9, 9, 9, 9,19, 9, +19,19,19,19,19,19, 4,19, 4, 4, 4, 4, 9, 9,19, 4, + 4, 4, 4, 4, 9, 9,19, 4, 4, 4, 4, 4, 9, 9,19, 4, + 4, 4, 4, 4, 9, 9,19, 4, 4, 4, 4, 4, 9, 9,19, 4, + 4, 4, 4, 4, 9, 9,19, 4, 4, 4, 4, 4, 9, 9,19, 4, + 4, 4, 4, 4, 9, 9,19, 4, 4, 4, 4, 4, 9, 9,19, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4,14, 4,23, 4,15, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4,10, 4, 4, 4, 4, 4, 4}; + +static const UINT8 cc_xycb[0x100] = { +23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, +23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, +23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, +23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, +23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, +23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, +23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, +23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, +23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, +23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, +23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, +23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23}; + +/* extra cycles if jr/jp/call taken and 'interrupt latency' on rst 0-7 */ +static const UINT8 cc_ex[0x100] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* DJNZ */ + 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, /* JR NZ/JR Z */ + 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, /* JR NC/JR C */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 0, 0, 0, 0, 5, 5, 5, 5, 0, 0, 0, 0, /* LDIR/CPIR/INIR/OTIR LDDR/CPDR/INDR/OTDR */ + 6, 0, 0, 0, 7, 0, 0, 2, 6, 0, 0, 0, 7, 0, 0, 2, + 6, 0, 0, 0, 7, 0, 0, 2, 6, 0, 0, 0, 7, 0, 0, 2, + 6, 0, 0, 0, 7, 0, 0, 2, 6, 0, 0, 0, 7, 0, 0, 2, + 6, 0, 0, 0, 7, 0, 0, 2, 6, 0, 0, 0, 7, 0, 0, 2}; + +static const UINT8 *cc[6] = { cc_op, cc_cb, cc_ed, cc_xy, cc_xycb, cc_ex }; +#define Z80_TABLE_dd Z80_TABLE_xy +#define Z80_TABLE_fd Z80_TABLE_xy + +static void take_interrupt(z80_state_t *z80); + +typedef void (*funcptr)(z80_state_t *z80); + +#define PROTOTYPES(tablename,prefix) \ + INLINE void prefix##_00(z80_state_t *z80); INLINE void prefix##_01(z80_state_t *z80); INLINE void prefix##_02(z80_state_t *z80); INLINE void prefix##_03(z80_state_t *z80); \ + INLINE void prefix##_04(z80_state_t *z80); INLINE void prefix##_05(z80_state_t *z80); INLINE void prefix##_06(z80_state_t *z80); INLINE void prefix##_07(z80_state_t *z80); \ + INLINE void prefix##_08(z80_state_t *z80); INLINE void prefix##_09(z80_state_t *z80); INLINE void prefix##_0a(z80_state_t *z80); INLINE void prefix##_0b(z80_state_t *z80); \ + INLINE void prefix##_0c(z80_state_t *z80); INLINE void prefix##_0d(z80_state_t *z80); INLINE void prefix##_0e(z80_state_t *z80); INLINE void prefix##_0f(z80_state_t *z80); \ + INLINE void prefix##_10(z80_state_t *z80); INLINE void prefix##_11(z80_state_t *z80); INLINE void prefix##_12(z80_state_t *z80); INLINE void prefix##_13(z80_state_t *z80); \ + INLINE void prefix##_14(z80_state_t *z80); INLINE void prefix##_15(z80_state_t *z80); INLINE void prefix##_16(z80_state_t *z80); INLINE void prefix##_17(z80_state_t *z80); \ + INLINE void prefix##_18(z80_state_t *z80); INLINE void prefix##_19(z80_state_t *z80); INLINE void prefix##_1a(z80_state_t *z80); INLINE void prefix##_1b(z80_state_t *z80); \ + INLINE void prefix##_1c(z80_state_t *z80); INLINE void prefix##_1d(z80_state_t *z80); INLINE void prefix##_1e(z80_state_t *z80); INLINE void prefix##_1f(z80_state_t *z80); \ + INLINE void prefix##_20(z80_state_t *z80); INLINE void prefix##_21(z80_state_t *z80); INLINE void prefix##_22(z80_state_t *z80); INLINE void prefix##_23(z80_state_t *z80); \ + INLINE void prefix##_24(z80_state_t *z80); INLINE void prefix##_25(z80_state_t *z80); INLINE void prefix##_26(z80_state_t *z80); INLINE void prefix##_27(z80_state_t *z80); \ + INLINE void prefix##_28(z80_state_t *z80); INLINE void prefix##_29(z80_state_t *z80); INLINE void prefix##_2a(z80_state_t *z80); INLINE void prefix##_2b(z80_state_t *z80); \ + INLINE void prefix##_2c(z80_state_t *z80); INLINE void prefix##_2d(z80_state_t *z80); INLINE void prefix##_2e(z80_state_t *z80); INLINE void prefix##_2f(z80_state_t *z80); \ + INLINE void prefix##_30(z80_state_t *z80); INLINE void prefix##_31(z80_state_t *z80); INLINE void prefix##_32(z80_state_t *z80); INLINE void prefix##_33(z80_state_t *z80); \ + INLINE void prefix##_34(z80_state_t *z80); INLINE void prefix##_35(z80_state_t *z80); INLINE void prefix##_36(z80_state_t *z80); INLINE void prefix##_37(z80_state_t *z80); \ + INLINE void prefix##_38(z80_state_t *z80); INLINE void prefix##_39(z80_state_t *z80); INLINE void prefix##_3a(z80_state_t *z80); INLINE void prefix##_3b(z80_state_t *z80); \ + INLINE void prefix##_3c(z80_state_t *z80); INLINE void prefix##_3d(z80_state_t *z80); INLINE void prefix##_3e(z80_state_t *z80); INLINE void prefix##_3f(z80_state_t *z80); \ + INLINE void prefix##_40(z80_state_t *z80); INLINE void prefix##_41(z80_state_t *z80); INLINE void prefix##_42(z80_state_t *z80); INLINE void prefix##_43(z80_state_t *z80); \ + INLINE void prefix##_44(z80_state_t *z80); INLINE void prefix##_45(z80_state_t *z80); INLINE void prefix##_46(z80_state_t *z80); INLINE void prefix##_47(z80_state_t *z80); \ + INLINE void prefix##_48(z80_state_t *z80); INLINE void prefix##_49(z80_state_t *z80); INLINE void prefix##_4a(z80_state_t *z80); INLINE void prefix##_4b(z80_state_t *z80); \ + INLINE void prefix##_4c(z80_state_t *z80); INLINE void prefix##_4d(z80_state_t *z80); INLINE void prefix##_4e(z80_state_t *z80); INLINE void prefix##_4f(z80_state_t *z80); \ + INLINE void prefix##_50(z80_state_t *z80); INLINE void prefix##_51(z80_state_t *z80); INLINE void prefix##_52(z80_state_t *z80); INLINE void prefix##_53(z80_state_t *z80); \ + INLINE void prefix##_54(z80_state_t *z80); INLINE void prefix##_55(z80_state_t *z80); INLINE void prefix##_56(z80_state_t *z80); INLINE void prefix##_57(z80_state_t *z80); \ + INLINE void prefix##_58(z80_state_t *z80); INLINE void prefix##_59(z80_state_t *z80); INLINE void prefix##_5a(z80_state_t *z80); INLINE void prefix##_5b(z80_state_t *z80); \ + INLINE void prefix##_5c(z80_state_t *z80); INLINE void prefix##_5d(z80_state_t *z80); INLINE void prefix##_5e(z80_state_t *z80); INLINE void prefix##_5f(z80_state_t *z80); \ + INLINE void prefix##_60(z80_state_t *z80); INLINE void prefix##_61(z80_state_t *z80); INLINE void prefix##_62(z80_state_t *z80); INLINE void prefix##_63(z80_state_t *z80); \ + INLINE void prefix##_64(z80_state_t *z80); INLINE void prefix##_65(z80_state_t *z80); INLINE void prefix##_66(z80_state_t *z80); INLINE void prefix##_67(z80_state_t *z80); \ + INLINE void prefix##_68(z80_state_t *z80); INLINE void prefix##_69(z80_state_t *z80); INLINE void prefix##_6a(z80_state_t *z80); INLINE void prefix##_6b(z80_state_t *z80); \ + INLINE void prefix##_6c(z80_state_t *z80); INLINE void prefix##_6d(z80_state_t *z80); INLINE void prefix##_6e(z80_state_t *z80); INLINE void prefix##_6f(z80_state_t *z80); \ + INLINE void prefix##_70(z80_state_t *z80); INLINE void prefix##_71(z80_state_t *z80); INLINE void prefix##_72(z80_state_t *z80); INLINE void prefix##_73(z80_state_t *z80); \ + INLINE void prefix##_74(z80_state_t *z80); INLINE void prefix##_75(z80_state_t *z80); INLINE void prefix##_76(z80_state_t *z80); INLINE void prefix##_77(z80_state_t *z80); \ + INLINE void prefix##_78(z80_state_t *z80); INLINE void prefix##_79(z80_state_t *z80); INLINE void prefix##_7a(z80_state_t *z80); INLINE void prefix##_7b(z80_state_t *z80); \ + INLINE void prefix##_7c(z80_state_t *z80); INLINE void prefix##_7d(z80_state_t *z80); INLINE void prefix##_7e(z80_state_t *z80); INLINE void prefix##_7f(z80_state_t *z80); \ + INLINE void prefix##_80(z80_state_t *z80); INLINE void prefix##_81(z80_state_t *z80); INLINE void prefix##_82(z80_state_t *z80); INLINE void prefix##_83(z80_state_t *z80); \ + INLINE void prefix##_84(z80_state_t *z80); INLINE void prefix##_85(z80_state_t *z80); INLINE void prefix##_86(z80_state_t *z80); INLINE void prefix##_87(z80_state_t *z80); \ + INLINE void prefix##_88(z80_state_t *z80); INLINE void prefix##_89(z80_state_t *z80); INLINE void prefix##_8a(z80_state_t *z80); INLINE void prefix##_8b(z80_state_t *z80); \ + INLINE void prefix##_8c(z80_state_t *z80); INLINE void prefix##_8d(z80_state_t *z80); INLINE void prefix##_8e(z80_state_t *z80); INLINE void prefix##_8f(z80_state_t *z80); \ + INLINE void prefix##_90(z80_state_t *z80); INLINE void prefix##_91(z80_state_t *z80); INLINE void prefix##_92(z80_state_t *z80); INLINE void prefix##_93(z80_state_t *z80); \ + INLINE void prefix##_94(z80_state_t *z80); INLINE void prefix##_95(z80_state_t *z80); INLINE void prefix##_96(z80_state_t *z80); INLINE void prefix##_97(z80_state_t *z80); \ + INLINE void prefix##_98(z80_state_t *z80); INLINE void prefix##_99(z80_state_t *z80); INLINE void prefix##_9a(z80_state_t *z80); INLINE void prefix##_9b(z80_state_t *z80); \ + INLINE void prefix##_9c(z80_state_t *z80); INLINE void prefix##_9d(z80_state_t *z80); INLINE void prefix##_9e(z80_state_t *z80); INLINE void prefix##_9f(z80_state_t *z80); \ + INLINE void prefix##_a0(z80_state_t *z80); INLINE void prefix##_a1(z80_state_t *z80); INLINE void prefix##_a2(z80_state_t *z80); INLINE void prefix##_a3(z80_state_t *z80); \ + INLINE void prefix##_a4(z80_state_t *z80); INLINE void prefix##_a5(z80_state_t *z80); INLINE void prefix##_a6(z80_state_t *z80); INLINE void prefix##_a7(z80_state_t *z80); \ + INLINE void prefix##_a8(z80_state_t *z80); INLINE void prefix##_a9(z80_state_t *z80); INLINE void prefix##_aa(z80_state_t *z80); INLINE void prefix##_ab(z80_state_t *z80); \ + INLINE void prefix##_ac(z80_state_t *z80); INLINE void prefix##_ad(z80_state_t *z80); INLINE void prefix##_ae(z80_state_t *z80); INLINE void prefix##_af(z80_state_t *z80); \ + INLINE void prefix##_b0(z80_state_t *z80); INLINE void prefix##_b1(z80_state_t *z80); INLINE void prefix##_b2(z80_state_t *z80); INLINE void prefix##_b3(z80_state_t *z80); \ + INLINE void prefix##_b4(z80_state_t *z80); INLINE void prefix##_b5(z80_state_t *z80); INLINE void prefix##_b6(z80_state_t *z80); INLINE void prefix##_b7(z80_state_t *z80); \ + INLINE void prefix##_b8(z80_state_t *z80); INLINE void prefix##_b9(z80_state_t *z80); INLINE void prefix##_ba(z80_state_t *z80); INLINE void prefix##_bb(z80_state_t *z80); \ + INLINE void prefix##_bc(z80_state_t *z80); INLINE void prefix##_bd(z80_state_t *z80); INLINE void prefix##_be(z80_state_t *z80); INLINE void prefix##_bf(z80_state_t *z80); \ + INLINE void prefix##_c0(z80_state_t *z80); INLINE void prefix##_c1(z80_state_t *z80); INLINE void prefix##_c2(z80_state_t *z80); INLINE void prefix##_c3(z80_state_t *z80); \ + INLINE void prefix##_c4(z80_state_t *z80); INLINE void prefix##_c5(z80_state_t *z80); INLINE void prefix##_c6(z80_state_t *z80); INLINE void prefix##_c7(z80_state_t *z80); \ + INLINE void prefix##_c8(z80_state_t *z80); INLINE void prefix##_c9(z80_state_t *z80); INLINE void prefix##_ca(z80_state_t *z80); INLINE void prefix##_cb(z80_state_t *z80); \ + INLINE void prefix##_cc(z80_state_t *z80); INLINE void prefix##_cd(z80_state_t *z80); INLINE void prefix##_ce(z80_state_t *z80); INLINE void prefix##_cf(z80_state_t *z80); \ + INLINE void prefix##_d0(z80_state_t *z80); INLINE void prefix##_d1(z80_state_t *z80); INLINE void prefix##_d2(z80_state_t *z80); INLINE void prefix##_d3(z80_state_t *z80); \ + INLINE void prefix##_d4(z80_state_t *z80); INLINE void prefix##_d5(z80_state_t *z80); INLINE void prefix##_d6(z80_state_t *z80); INLINE void prefix##_d7(z80_state_t *z80); \ + INLINE void prefix##_d8(z80_state_t *z80); INLINE void prefix##_d9(z80_state_t *z80); INLINE void prefix##_da(z80_state_t *z80); INLINE void prefix##_db(z80_state_t *z80); \ + INLINE void prefix##_dc(z80_state_t *z80); INLINE void prefix##_dd(z80_state_t *z80); INLINE void prefix##_de(z80_state_t *z80); INLINE void prefix##_df(z80_state_t *z80); \ + INLINE void prefix##_e0(z80_state_t *z80); INLINE void prefix##_e1(z80_state_t *z80); INLINE void prefix##_e2(z80_state_t *z80); INLINE void prefix##_e3(z80_state_t *z80); \ + INLINE void prefix##_e4(z80_state_t *z80); INLINE void prefix##_e5(z80_state_t *z80); INLINE void prefix##_e6(z80_state_t *z80); INLINE void prefix##_e7(z80_state_t *z80); \ + INLINE void prefix##_e8(z80_state_t *z80); INLINE void prefix##_e9(z80_state_t *z80); INLINE void prefix##_ea(z80_state_t *z80); INLINE void prefix##_eb(z80_state_t *z80); \ + INLINE void prefix##_ec(z80_state_t *z80); INLINE void prefix##_ed(z80_state_t *z80); INLINE void prefix##_ee(z80_state_t *z80); INLINE void prefix##_ef(z80_state_t *z80); \ + INLINE void prefix##_f0(z80_state_t *z80); INLINE void prefix##_f1(z80_state_t *z80); INLINE void prefix##_f2(z80_state_t *z80); INLINE void prefix##_f3(z80_state_t *z80); \ + INLINE void prefix##_f4(z80_state_t *z80); INLINE void prefix##_f5(z80_state_t *z80); INLINE void prefix##_f6(z80_state_t *z80); INLINE void prefix##_f7(z80_state_t *z80); \ + INLINE void prefix##_f8(z80_state_t *z80); INLINE void prefix##_f9(z80_state_t *z80); INLINE void prefix##_fa(z80_state_t *z80); INLINE void prefix##_fb(z80_state_t *z80); \ + INLINE void prefix##_fc(z80_state_t *z80); INLINE void prefix##_fd(z80_state_t *z80); INLINE void prefix##_fe(z80_state_t *z80); INLINE void prefix##_ff(z80_state_t *z80); \ +static const funcptr tablename[0x100] = { \ + prefix##_00,prefix##_01,prefix##_02,prefix##_03,prefix##_04,prefix##_05,prefix##_06,prefix##_07, \ + prefix##_08,prefix##_09,prefix##_0a,prefix##_0b,prefix##_0c,prefix##_0d,prefix##_0e,prefix##_0f, \ + prefix##_10,prefix##_11,prefix##_12,prefix##_13,prefix##_14,prefix##_15,prefix##_16,prefix##_17, \ + prefix##_18,prefix##_19,prefix##_1a,prefix##_1b,prefix##_1c,prefix##_1d,prefix##_1e,prefix##_1f, \ + prefix##_20,prefix##_21,prefix##_22,prefix##_23,prefix##_24,prefix##_25,prefix##_26,prefix##_27, \ + prefix##_28,prefix##_29,prefix##_2a,prefix##_2b,prefix##_2c,prefix##_2d,prefix##_2e,prefix##_2f, \ + prefix##_30,prefix##_31,prefix##_32,prefix##_33,prefix##_34,prefix##_35,prefix##_36,prefix##_37, \ + prefix##_38,prefix##_39,prefix##_3a,prefix##_3b,prefix##_3c,prefix##_3d,prefix##_3e,prefix##_3f, \ + prefix##_40,prefix##_41,prefix##_42,prefix##_43,prefix##_44,prefix##_45,prefix##_46,prefix##_47, \ + prefix##_48,prefix##_49,prefix##_4a,prefix##_4b,prefix##_4c,prefix##_4d,prefix##_4e,prefix##_4f, \ + prefix##_50,prefix##_51,prefix##_52,prefix##_53,prefix##_54,prefix##_55,prefix##_56,prefix##_57, \ + prefix##_58,prefix##_59,prefix##_5a,prefix##_5b,prefix##_5c,prefix##_5d,prefix##_5e,prefix##_5f, \ + prefix##_60,prefix##_61,prefix##_62,prefix##_63,prefix##_64,prefix##_65,prefix##_66,prefix##_67, \ + prefix##_68,prefix##_69,prefix##_6a,prefix##_6b,prefix##_6c,prefix##_6d,prefix##_6e,prefix##_6f, \ + prefix##_70,prefix##_71,prefix##_72,prefix##_73,prefix##_74,prefix##_75,prefix##_76,prefix##_77, \ + prefix##_78,prefix##_79,prefix##_7a,prefix##_7b,prefix##_7c,prefix##_7d,prefix##_7e,prefix##_7f, \ + prefix##_80,prefix##_81,prefix##_82,prefix##_83,prefix##_84,prefix##_85,prefix##_86,prefix##_87, \ + prefix##_88,prefix##_89,prefix##_8a,prefix##_8b,prefix##_8c,prefix##_8d,prefix##_8e,prefix##_8f, \ + prefix##_90,prefix##_91,prefix##_92,prefix##_93,prefix##_94,prefix##_95,prefix##_96,prefix##_97, \ + prefix##_98,prefix##_99,prefix##_9a,prefix##_9b,prefix##_9c,prefix##_9d,prefix##_9e,prefix##_9f, \ + prefix##_a0,prefix##_a1,prefix##_a2,prefix##_a3,prefix##_a4,prefix##_a5,prefix##_a6,prefix##_a7, \ + prefix##_a8,prefix##_a9,prefix##_aa,prefix##_ab,prefix##_ac,prefix##_ad,prefix##_ae,prefix##_af, \ + prefix##_b0,prefix##_b1,prefix##_b2,prefix##_b3,prefix##_b4,prefix##_b5,prefix##_b6,prefix##_b7, \ + prefix##_b8,prefix##_b9,prefix##_ba,prefix##_bb,prefix##_bc,prefix##_bd,prefix##_be,prefix##_bf, \ + prefix##_c0,prefix##_c1,prefix##_c2,prefix##_c3,prefix##_c4,prefix##_c5,prefix##_c6,prefix##_c7, \ + prefix##_c8,prefix##_c9,prefix##_ca,prefix##_cb,prefix##_cc,prefix##_cd,prefix##_ce,prefix##_cf, \ + prefix##_d0,prefix##_d1,prefix##_d2,prefix##_d3,prefix##_d4,prefix##_d5,prefix##_d6,prefix##_d7, \ + prefix##_d8,prefix##_d9,prefix##_da,prefix##_db,prefix##_dc,prefix##_dd,prefix##_de,prefix##_df, \ + prefix##_e0,prefix##_e1,prefix##_e2,prefix##_e3,prefix##_e4,prefix##_e5,prefix##_e6,prefix##_e7, \ + prefix##_e8,prefix##_e9,prefix##_ea,prefix##_eb,prefix##_ec,prefix##_ed,prefix##_ee,prefix##_ef, \ + prefix##_f0,prefix##_f1,prefix##_f2,prefix##_f3,prefix##_f4,prefix##_f5,prefix##_f6,prefix##_f7, \ + prefix##_f8,prefix##_f9,prefix##_fa,prefix##_fb,prefix##_fc,prefix##_fd,prefix##_fe,prefix##_ff \ +} + +PROTOTYPES(Z80op,op); +PROTOTYPES(Z80cb,cb); +PROTOTYPES(Z80dd,dd); +PROTOTYPES(Z80ed,ed); +PROTOTYPES(Z80fd,fd); +PROTOTYPES(Z80xycb,xycb); + +/****************************************************************************/ +/* Burn an odd amount of cycles, that is instructions taking something */ +/* different from 4 T-states per opcode (and R increment) */ +/****************************************************************************/ +INLINE void BURNODD(z80_state_t *z80, int cycles, int opcodes, int cyclesum) +{ + if( cycles > 0 ) + { + _Z80_R += (cycles / cyclesum) * opcodes; + z80->z80_ICount -= (cycles / cyclesum) * cyclesum; + } +} + +/*************************************************************** + * define an opcode function + ***************************************************************/ +#define OP(prefix,opcode) INLINE void prefix##_##opcode(z80_state_t *z80) + +/*************************************************************** + * adjust cycle count by n T-states + ***************************************************************/ +#define CC(prefix,opcode) z80->z80_ICount -= cc[Z80_TABLE_##prefix][opcode] + +/*************************************************************** + * execute an opcode + ***************************************************************/ +#define EXEC(prefix,opcode) \ +{ \ + unsigned op = opcode; \ + CC(prefix,op); \ + (*Z80##prefix[op])(z80); \ +} + +#if BIG_SWITCH +#define EXEC_INLINE(prefix,opcode) \ +{ \ + unsigned op = opcode; \ + CC(prefix,op); \ + switch(op) \ + { \ + case 0x00:prefix##_##00(z80);break; case 0x01:prefix##_##01(z80);break; case 0x02:prefix##_##02(z80);break; case 0x03:prefix##_##03(z80);break; \ + case 0x04:prefix##_##04(z80);break; case 0x05:prefix##_##05(z80);break; case 0x06:prefix##_##06(z80);break; case 0x07:prefix##_##07(z80);break; \ + case 0x08:prefix##_##08(z80);break; case 0x09:prefix##_##09(z80);break; case 0x0a:prefix##_##0a(z80);break; case 0x0b:prefix##_##0b(z80);break; \ + case 0x0c:prefix##_##0c(z80);break; case 0x0d:prefix##_##0d(z80);break; case 0x0e:prefix##_##0e(z80);break; case 0x0f:prefix##_##0f(z80);break; \ + case 0x10:prefix##_##10(z80);break; case 0x11:prefix##_##11(z80);break; case 0x12:prefix##_##12(z80);break; case 0x13:prefix##_##13(z80);break; \ + case 0x14:prefix##_##14(z80);break; case 0x15:prefix##_##15(z80);break; case 0x16:prefix##_##16(z80);break; case 0x17:prefix##_##17(z80);break; \ + case 0x18:prefix##_##18(z80);break; case 0x19:prefix##_##19(z80);break; case 0x1a:prefix##_##1a(z80);break; case 0x1b:prefix##_##1b(z80);break; \ + case 0x1c:prefix##_##1c(z80);break; case 0x1d:prefix##_##1d(z80);break; case 0x1e:prefix##_##1e(z80);break; case 0x1f:prefix##_##1f(z80);break; \ + case 0x20:prefix##_##20(z80);break; case 0x21:prefix##_##21(z80);break; case 0x22:prefix##_##22(z80);break; case 0x23:prefix##_##23(z80);break; \ + case 0x24:prefix##_##24(z80);break; case 0x25:prefix##_##25(z80);break; case 0x26:prefix##_##26(z80);break; case 0x27:prefix##_##27(z80);break; \ + case 0x28:prefix##_##28(z80);break; case 0x29:prefix##_##29(z80);break; case 0x2a:prefix##_##2a(z80);break; case 0x2b:prefix##_##2b(z80);break; \ + case 0x2c:prefix##_##2c(z80);break; case 0x2d:prefix##_##2d(z80);break; case 0x2e:prefix##_##2e(z80);break; case 0x2f:prefix##_##2f(z80);break; \ + case 0x30:prefix##_##30(z80);break; case 0x31:prefix##_##31(z80);break; case 0x32:prefix##_##32(z80);break; case 0x33:prefix##_##33(z80);break; \ + case 0x34:prefix##_##34(z80);break; case 0x35:prefix##_##35(z80);break; case 0x36:prefix##_##36(z80);break; case 0x37:prefix##_##37(z80);break; \ + case 0x38:prefix##_##38(z80);break; case 0x39:prefix##_##39(z80);break; case 0x3a:prefix##_##3a(z80);break; case 0x3b:prefix##_##3b(z80);break; \ + case 0x3c:prefix##_##3c(z80);break; case 0x3d:prefix##_##3d(z80);break; case 0x3e:prefix##_##3e(z80);break; case 0x3f:prefix##_##3f(z80);break; \ + case 0x40:prefix##_##40(z80);break; case 0x41:prefix##_##41(z80);break; case 0x42:prefix##_##42(z80);break; case 0x43:prefix##_##43(z80);break; \ + case 0x44:prefix##_##44(z80);break; case 0x45:prefix##_##45(z80);break; case 0x46:prefix##_##46(z80);break; case 0x47:prefix##_##47(z80);break; \ + case 0x48:prefix##_##48(z80);break; case 0x49:prefix##_##49(z80);break; case 0x4a:prefix##_##4a(z80);break; case 0x4b:prefix##_##4b(z80);break; \ + case 0x4c:prefix##_##4c(z80);break; case 0x4d:prefix##_##4d(z80);break; case 0x4e:prefix##_##4e(z80);break; case 0x4f:prefix##_##4f(z80);break; \ + case 0x50:prefix##_##50(z80);break; case 0x51:prefix##_##51(z80);break; case 0x52:prefix##_##52(z80);break; case 0x53:prefix##_##53(z80);break; \ + case 0x54:prefix##_##54(z80);break; case 0x55:prefix##_##55(z80);break; case 0x56:prefix##_##56(z80);break; case 0x57:prefix##_##57(z80);break; \ + case 0x58:prefix##_##58(z80);break; case 0x59:prefix##_##59(z80);break; case 0x5a:prefix##_##5a(z80);break; case 0x5b:prefix##_##5b(z80);break; \ + case 0x5c:prefix##_##5c(z80);break; case 0x5d:prefix##_##5d(z80);break; case 0x5e:prefix##_##5e(z80);break; case 0x5f:prefix##_##5f(z80);break; \ + case 0x60:prefix##_##60(z80);break; case 0x61:prefix##_##61(z80);break; case 0x62:prefix##_##62(z80);break; case 0x63:prefix##_##63(z80);break; \ + case 0x64:prefix##_##64(z80);break; case 0x65:prefix##_##65(z80);break; case 0x66:prefix##_##66(z80);break; case 0x67:prefix##_##67(z80);break; \ + case 0x68:prefix##_##68(z80);break; case 0x69:prefix##_##69(z80);break; case 0x6a:prefix##_##6a(z80);break; case 0x6b:prefix##_##6b(z80);break; \ + case 0x6c:prefix##_##6c(z80);break; case 0x6d:prefix##_##6d(z80);break; case 0x6e:prefix##_##6e(z80);break; case 0x6f:prefix##_##6f(z80);break; \ + case 0x70:prefix##_##70(z80);break; case 0x71:prefix##_##71(z80);break; case 0x72:prefix##_##72(z80);break; case 0x73:prefix##_##73(z80);break; \ + case 0x74:prefix##_##74(z80);break; case 0x75:prefix##_##75(z80);break; case 0x76:prefix##_##76(z80);break; case 0x77:prefix##_##77(z80);break; \ + case 0x78:prefix##_##78(z80);break; case 0x79:prefix##_##79(z80);break; case 0x7a:prefix##_##7a(z80);break; case 0x7b:prefix##_##7b(z80);break; \ + case 0x7c:prefix##_##7c(z80);break; case 0x7d:prefix##_##7d(z80);break; case 0x7e:prefix##_##7e(z80);break; case 0x7f:prefix##_##7f(z80);break; \ + case 0x80:prefix##_##80(z80);break; case 0x81:prefix##_##81(z80);break; case 0x82:prefix##_##82(z80);break; case 0x83:prefix##_##83(z80);break; \ + case 0x84:prefix##_##84(z80);break; case 0x85:prefix##_##85(z80);break; case 0x86:prefix##_##86(z80);break; case 0x87:prefix##_##87(z80);break; \ + case 0x88:prefix##_##88(z80);break; case 0x89:prefix##_##89(z80);break; case 0x8a:prefix##_##8a(z80);break; case 0x8b:prefix##_##8b(z80);break; \ + case 0x8c:prefix##_##8c(z80);break; case 0x8d:prefix##_##8d(z80);break; case 0x8e:prefix##_##8e(z80);break; case 0x8f:prefix##_##8f(z80);break; \ + case 0x90:prefix##_##90(z80);break; case 0x91:prefix##_##91(z80);break; case 0x92:prefix##_##92(z80);break; case 0x93:prefix##_##93(z80);break; \ + case 0x94:prefix##_##94(z80);break; case 0x95:prefix##_##95(z80);break; case 0x96:prefix##_##96(z80);break; case 0x97:prefix##_##97(z80);break; \ + case 0x98:prefix##_##98(z80);break; case 0x99:prefix##_##99(z80);break; case 0x9a:prefix##_##9a(z80);break; case 0x9b:prefix##_##9b(z80);break; \ + case 0x9c:prefix##_##9c(z80);break; case 0x9d:prefix##_##9d(z80);break; case 0x9e:prefix##_##9e(z80);break; case 0x9f:prefix##_##9f(z80);break; \ + case 0xa0:prefix##_##a0(z80);break; case 0xa1:prefix##_##a1(z80);break; case 0xa2:prefix##_##a2(z80);break; case 0xa3:prefix##_##a3(z80);break; \ + case 0xa4:prefix##_##a4(z80);break; case 0xa5:prefix##_##a5(z80);break; case 0xa6:prefix##_##a6(z80);break; case 0xa7:prefix##_##a7(z80);break; \ + case 0xa8:prefix##_##a8(z80);break; case 0xa9:prefix##_##a9(z80);break; case 0xaa:prefix##_##aa(z80);break; case 0xab:prefix##_##ab(z80);break; \ + case 0xac:prefix##_##ac(z80);break; case 0xad:prefix##_##ad(z80);break; case 0xae:prefix##_##ae(z80);break; case 0xaf:prefix##_##af(z80);break; \ + case 0xb0:prefix##_##b0(z80);break; case 0xb1:prefix##_##b1(z80);break; case 0xb2:prefix##_##b2(z80);break; case 0xb3:prefix##_##b3(z80);break; \ + case 0xb4:prefix##_##b4(z80);break; case 0xb5:prefix##_##b5(z80);break; case 0xb6:prefix##_##b6(z80);break; case 0xb7:prefix##_##b7(z80);break; \ + case 0xb8:prefix##_##b8(z80);break; case 0xb9:prefix##_##b9(z80);break; case 0xba:prefix##_##ba(z80);break; case 0xbb:prefix##_##bb(z80);break; \ + case 0xbc:prefix##_##bc(z80);break; case 0xbd:prefix##_##bd(z80);break; case 0xbe:prefix##_##be(z80);break; case 0xbf:prefix##_##bf(z80);break; \ + case 0xc0:prefix##_##c0(z80);break; case 0xc1:prefix##_##c1(z80);break; case 0xc2:prefix##_##c2(z80);break; case 0xc3:prefix##_##c3(z80);break; \ + case 0xc4:prefix##_##c4(z80);break; case 0xc5:prefix##_##c5(z80);break; case 0xc6:prefix##_##c6(z80);break; case 0xc7:prefix##_##c7(z80);break; \ + case 0xc8:prefix##_##c8(z80);break; case 0xc9:prefix##_##c9(z80);break; case 0xca:prefix##_##ca(z80);break; case 0xcb:prefix##_##cb(z80);break; \ + case 0xcc:prefix##_##cc(z80);break; case 0xcd:prefix##_##cd(z80);break; case 0xce:prefix##_##ce(z80);break; case 0xcf:prefix##_##cf(z80);break; \ + case 0xd0:prefix##_##d0(z80);break; case 0xd1:prefix##_##d1(z80);break; case 0xd2:prefix##_##d2(z80);break; case 0xd3:prefix##_##d3(z80);break; \ + case 0xd4:prefix##_##d4(z80);break; case 0xd5:prefix##_##d5(z80);break; case 0xd6:prefix##_##d6(z80);break; case 0xd7:prefix##_##d7(z80);break; \ + case 0xd8:prefix##_##d8(z80);break; case 0xd9:prefix##_##d9(z80);break; case 0xda:prefix##_##da(z80);break; case 0xdb:prefix##_##db(z80);break; \ + case 0xdc:prefix##_##dc(z80);break; case 0xdd:prefix##_##dd(z80);break; case 0xde:prefix##_##de(z80);break; case 0xdf:prefix##_##df(z80);break; \ + case 0xe0:prefix##_##e0(z80);break; case 0xe1:prefix##_##e1(z80);break; case 0xe2:prefix##_##e2(z80);break; case 0xe3:prefix##_##e3(z80);break; \ + case 0xe4:prefix##_##e4(z80);break; case 0xe5:prefix##_##e5(z80);break; case 0xe6:prefix##_##e6(z80);break; case 0xe7:prefix##_##e7(z80);break; \ + case 0xe8:prefix##_##e8(z80);break; case 0xe9:prefix##_##e9(z80);break; case 0xea:prefix##_##ea(z80);break; case 0xeb:prefix##_##eb(z80);break; \ + case 0xec:prefix##_##ec(z80);break; case 0xed:prefix##_##ed(z80);break; case 0xee:prefix##_##ee(z80);break; case 0xef:prefix##_##ef(z80);break; \ + case 0xf0:prefix##_##f0(z80);break; case 0xf1:prefix##_##f1(z80);break; case 0xf2:prefix##_##f2(z80);break; case 0xf3:prefix##_##f3(z80);break; \ + case 0xf4:prefix##_##f4(z80);break; case 0xf5:prefix##_##f5(z80);break; case 0xf6:prefix##_##f6(z80);break; case 0xf7:prefix##_##f7(z80);break; \ + case 0xf8:prefix##_##f8(z80);break; case 0xf9:prefix##_##f9(z80);break; case 0xfa:prefix##_##fa(z80);break; case 0xfb:prefix##_##fb(z80);break; \ + case 0xfc:prefix##_##fc(z80);break; case 0xfd:prefix##_##fd(z80);break; case 0xfe:prefix##_##fe(z80);break; case 0xff:prefix##_##ff(z80);break; \ + } \ +} +#else +#define EXEC_INLINE EXEC +#endif + + +/*************************************************************** + * Enter HALT state; write 1 to fake port on first execution + ***************************************************************/ +#define ENTER_HALT { \ + _PC--; \ + _HALT = 1; \ + if( !z80->after_EI ) \ + z80_burn( z80, z80->z80_ICount ); \ +} + +/*************************************************************** + * Leave HALT state; write 0 to fake port + ***************************************************************/ +#define LEAVE_HALT { \ + if( _HALT ) \ + { \ + _HALT = 0; \ + _PC++; \ + } \ +} + +/*************************************************************** + * Input a byte from given I/O port + ***************************************************************/ +#define IN(port) ((UINT8)cpu_readport16(z80->userdata,port)) + +/*************************************************************** + * Output a byte to given I/O port + ***************************************************************/ +#define OUT(port,value) cpu_writeport16(z80->userdata,port,value) + +/*************************************************************** + * Read a byte from given memory location + ***************************************************************/ +#define RM(addr) (UINT8)cpu_readmem16(z80->userdata,addr) + +/*************************************************************** + * Read a word from given memory location + ***************************************************************/ +INLINE void RM16( z80_state_t *z80, UINT32 addr, PAIR *r ) +{ + r->b.l = RM(addr); + r->b.h = RM((addr+1)&0xffff); +} + +/*************************************************************** + * Write a byte to given memory location + ***************************************************************/ +#define WM(addr,value) cpu_writemem16(z80->userdata,addr,value) + +/*************************************************************** + * Write a word to given memory location + ***************************************************************/ +INLINE void WM16( z80_state_t *z80, UINT32 addr, PAIR *r ) +{ + WM(addr,r->b.l); + WM((addr+1)&0xffff,r->b.h); +} + +/*************************************************************** + * ROP() is identical to RM() except it is used for + * reading opcodes. In case of system with memory mapped I/O, + * this function can be used to greatly speed up emulation + ***************************************************************/ +INLINE UINT8 ROP(z80_state_t *z80) +{ + unsigned pc = _PCD; + _PC++; + return cpu_readop(z80->userdata,pc); +} + +/**************************************************************** + * ARG() is identical to ROP() except it is used + * for reading opcode arguments. This difference can be used to + * support systems that use different encoding mechanisms for + * opcodes and opcode arguments + ***************************************************************/ +INLINE UINT8 ARG(z80_state_t *z80) +{ + unsigned pc = _PCD; + _PC++; + return cpu_readop_arg(z80->userdata, pc); +} + +INLINE UINT32 ARG16(z80_state_t *z80) +{ + unsigned pc = _PCD; + _PC += 2; + return cpu_readop_arg(z80->userdata,pc) | (cpu_readop_arg(z80->userdata,(pc+1)&0xffff) << 8); +} + +/*************************************************************** + * Calculate the effective address EA of an opcode using + * IX+offset resp. IY+offset addressing. + ***************************************************************/ +#define EAX z80->EA = (UINT32)(UINT16)(_IX+(INT8)ARG(z80)) +#define EAY z80->EA = (UINT32)(UINT16)(_IY+(INT8)ARG(z80)) + +/*************************************************************** + * POP + ***************************************************************/ +#define POP(DR) { RM16(z80, _SPD, &z80->Z80.DR ); _SP += 2; } + +/*************************************************************** + * PUSH + ***************************************************************/ +#define PUSH(SR) { _SP -= 2; WM16( z80, _SPD, &z80->Z80.SR ); } + +/*************************************************************** + * JP + ***************************************************************/ +#if BUSY_LOOP_HACKS +#define JP { \ + unsigned oldpc = _PCD-1; \ + _PCD = ARG16(z80); \ + change_pc16(_PCD); \ + /* speed up busy loop */ \ + if( _PCD == oldpc ) \ + { \ + if( !z80->after_EI ) \ + BURNODD( z80, z80->z80_ICount, 1, cc[Z80_TABLE_op][0xc3] ); \ + } \ + else \ + { \ + UINT8 op = cpu_readop(z80->userdata,_PCD); \ + if( _PCD == oldpc-1 ) \ + { \ + /* NOP - JP $-1 or EI - JP $-1 */ \ + if ( op == 0x00 || op == 0xfb ) \ + { \ + if( !z80->after_EI ) \ + BURNODD( z80, z80->z80_ICount-cc[Z80_TABLE_op][0x00], \ + 2, cc[Z80_TABLE_op][0x00]+cc[Z80_TABLE_op][0xc3]); \ + } \ + } \ + else \ + /* LD SP,#xxxx - JP $-3 (Galaga) */ \ + if( _PCD == oldpc-3 && op == 0x31 ) \ + { \ + if( !z80->after_EI ) \ + BURNODD( z80, z80->z80_ICount-cc[Z80_TABLE_op][0x31], \ + 2, cc[Z80_TABLE_op][0x31]+cc[Z80_TABLE_op][0xc3]); \ + } \ + } \ +} +#else +#define JP { \ + _PCD = ARG16(z80); \ + change_pc16(_PCD); \ +} +#endif + +/*************************************************************** + * JP_COND + ***************************************************************/ + +#define JP_COND(cond) \ + if( cond ) \ + { \ + _PCD = ARG16(z80); \ + change_pc16(_PCD); \ + } \ + else \ + { \ + _PC += 2; \ + } + +/*************************************************************** + * JR + ***************************************************************/ +#define JR() \ +{ \ + unsigned oldpc = _PCD-1; \ + INT8 arg = (INT8)ARG(z80); /* ARG() also increments _PC */ \ + _PC += arg; /* so don't do _PC += ARG() */ \ + change_pc16(_PCD); \ + /* speed up busy loop */ \ + if( _PCD == oldpc ) \ + { \ + if( !z80->after_EI ) \ + BURNODD( z80, z80->z80_ICount, 1, cc[Z80_TABLE_op][0x18] ); \ + } \ + else \ + { \ + UINT8 op = cpu_readop(z80->userdata,_PCD); \ + if( _PCD == oldpc-1 ) \ + { \ + /* NOP - JR $-1 or EI - JR $-1 */ \ + if ( op == 0x00 || op == 0xfb ) \ + { \ + if( !z80->after_EI ) \ + BURNODD( z80, z80->z80_ICount-cc[Z80_TABLE_op][0x00], \ + 2, cc[Z80_TABLE_op][0x00]+cc[Z80_TABLE_op][0x18]); \ + } \ + } \ + else \ + /* LD SP,#xxxx - JR $-3 */ \ + if( _PCD == oldpc-3 && op == 0x31 ) \ + { \ + if( !z80->after_EI ) \ + BURNODD( z80, z80->z80_ICount-cc[Z80_TABLE_op][0x31], \ + 2, cc[Z80_TABLE_op][0x31]+cc[Z80_TABLE_op][0x18]); \ + } \ + } \ +} + +/*************************************************************** + * JR_COND + ***************************************************************/ +#define JR_COND(cond,opcode) \ + if( cond ) \ + { \ + INT8 arg = (INT8)ARG(z80); /* ARG() also increments _PC */ \ + _PC += arg; /* so don't do _PC += ARG() */ \ + CC(ex,opcode); \ + change_pc16(_PCD); \ + } \ + else _PC++; \ + +/*************************************************************** + * CALL + ***************************************************************/ +#define CALL() \ + z80->EA = ARG16(z80); \ + PUSH( PC ); \ + _PCD = z80->EA; \ + change_pc16(_PCD) + +/*************************************************************** + * CALL_COND + ***************************************************************/ +#define CALL_COND(cond,opcode) \ + if( cond ) \ + { \ + z80->EA = ARG16(z80); \ + PUSH( PC ); \ + _PCD = z80->EA; \ + CC(ex,opcode); \ + change_pc16(_PCD); \ + } \ + else \ + { \ + _PC+=2; \ + } + +/*************************************************************** + * RET_COND + ***************************************************************/ +#define RET_COND(cond,opcode) \ + if( cond ) \ + { \ + POP(PC); \ + change_pc16(_PCD); \ + CC(ex,opcode); \ + } + +/*************************************************************** + * RETN + ***************************************************************/ +#define RETN { \ + POP(PC); \ + change_pc16(_PCD); \ + if( _IFF1 == 0 && _IFF2 == 1 ) \ + { \ + _IFF1 = 1; \ + if( z80->Z80.irq_state != CLEAR_LINE || \ + z80->Z80.request_irq >= 0 ) \ + { \ + take_interrupt(z80); \ + } \ + } \ + else _IFF1 = _IFF2; \ +} + +/*************************************************************** + * RETI + ***************************************************************/ +#define RETI { \ + int device = z80->Z80.service_irq; \ + POP(PC); \ + change_pc16(_PCD); \ +/* according to http://www.msxnet.org/tech/z80-documented.pdf */\ +/* _IFF1 = _IFF2; */ \ + if( device >= 0 ) \ + { \ + z80->Z80.irq[device].interrupt_reti(z80->Z80.irq[device].irq_param); \ + } \ +} + +/*************************************************************** + * LD R,A + ***************************************************************/ +#define LD_R_A { \ + _Z80_R = _Z80_A; \ + _R2 = _Z80_A & 0x80; /* keep bit 7 of R */ \ +} + +/*************************************************************** + * LD A,R + ***************************************************************/ +#define LD_A_R { \ + _Z80_A = (_Z80_R & 0x7f) | _R2; \ + _F = (_F & CF) | z80->SZ[_Z80_A] | ( _IFF2 << 2 ); \ +} + +/*************************************************************** + * LD I,A + ***************************************************************/ +#define LD_I_A { \ + _Z80_I = _Z80_A; \ +} + +/*************************************************************** + * LD A,I + ***************************************************************/ +#define LD_A_I { \ + _Z80_A = _Z80_I; \ + _F = (_F & CF) | z80->SZ[_Z80_A] | ( _IFF2 << 2 ); \ +} + +/*************************************************************** + * RST + ***************************************************************/ +#define RST(addr) \ + PUSH( PC ); \ + _PCD = addr; \ + change_pc16(_PCD) + +/*************************************************************** + * INC r8 + ***************************************************************/ +INLINE UINT8 INC(z80_state_t *z80, UINT8 value) +{ + UINT8 res = value + 1; + _F = (_F & CF) | z80->SZHV_inc[res]; + return (UINT8)res; +} + +/*************************************************************** + * DEC r8 + ***************************************************************/ +INLINE UINT8 DEC(z80_state_t *z80, UINT8 value) +{ + UINT8 res = value - 1; + _F = (_F & CF) | z80->SZHV_dec[res]; + return res; +} + +/*************************************************************** + * RLCA + ***************************************************************/ +#if Z80_EXACT +#define RLCA \ + _Z80_A = (_Z80_A << 1) | (_Z80_A >> 7); \ + _F = (_F & (SF | ZF | PF)) | (_Z80_A & (YF | XF | CF)) +#else +#define RLCA \ + _Z80_A = (_Z80_A << 1) | (_Z80_A >> 7); \ + _F = (_F & (SF | ZF | YF | XF | PF)) | (_Z80_A & CF) +#endif + +/*************************************************************** + * RRCA + ***************************************************************/ +#if Z80_EXACT +#define RRCA \ + _F = (_F & (SF | ZF | PF)) | (_Z80_A & CF); \ + _Z80_A = (_Z80_A >> 1) | (_Z80_A << 7); \ + _F |= (_Z80_A & (YF | XF) ) +#else +#define RRCA \ + _F = (_F & (SF | ZF | YF | XF | PF)) | (_Z80_A & CF); \ + _Z80_A = (_Z80_A >> 1) | (_Z80_A << 7) +#endif + +/*************************************************************** + * RLA + ***************************************************************/ +#if Z80_EXACT +#define RLA { \ + UINT8 res = (_Z80_A << 1) | (_F & CF); \ + UINT8 c = (_Z80_A & 0x80) ? CF : 0; \ + _F = (_F & (SF | ZF | PF)) | c | (res & (YF | XF)); \ + _Z80_A = res; \ +} +#else +#define RLA { \ + UINT8 res = (_Z80_A << 1) | (_F & CF); \ + UINT8 c = (_Z80_A & 0x80) ? CF : 0; \ + _F = (_F & (SF | ZF | YF | XF | PF)) | c; \ + _Z80_A = res; \ +} +#endif + +/*************************************************************** + * RRA + ***************************************************************/ +#if Z80_EXACT +#define RRA { \ + UINT8 res = (_Z80_A >> 1) | (_F << 7); \ + UINT8 c = (_Z80_A & 0x01) ? CF : 0; \ + _F = (_F & (SF | ZF | PF)) | c | (res & (YF | XF)); \ + _Z80_A = res; \ +} +#else +#define RRA { \ + UINT8 res = (_Z80_A >> 1) | (_F << 7); \ + UINT8 c = (_Z80_A & 0x01) ? CF : 0; \ + _F = (_F & (SF | ZF | YF | XF | PF)) | c; \ + _Z80_A = res; \ +} +#endif + +/*************************************************************** + * RRD + ***************************************************************/ +#define RRD { \ + UINT8 n = RM(_HL); \ + WM( _HL, (n >> 4) | (_Z80_A << 4) ); \ + _Z80_A = (_Z80_A & 0xf0) | (n & 0x0f); \ + _F = (_F & CF) | z80->SZP[_Z80_A]; \ +} + +/*************************************************************** + * RLD + ***************************************************************/ +#define RLD { \ + UINT8 n = RM(_HL); \ + WM( _HL, (n << 4) | (_Z80_A & 0x0f) ); \ + _Z80_A = (_Z80_A & 0xf0) | (n >> 4); \ + _F = (_F & CF) | z80->SZP[_Z80_A]; \ +} + +/*************************************************************** + * ADD A,n + ***************************************************************/ +#ifdef X86_ASM +#if Z80_EXACT +#define ADD(value) \ + asm ( \ + " addb %2,%0 \n" \ + " lahf \n" \ + " setob %1 \n" /* al = 1 if overflow */ \ + " addb %1,%1 \n" \ + " addb %1,%1 \n" /* shift to P/V bit position */ \ + " andb $0xd1,%%ah \n" /* sign, zero, half carry, carry */ \ + " orb %%ah,%1 \n" \ + " movb %0,%%ah \n" /* get result */ \ + " andb $0x28,%%ah \n" /* maks flags 5+3 */ \ + " orb %%ah,%1 \n" /* put them into flags */ \ + :"=q" (_Z80_A), "=q" (_F) \ + :"q" (value), "1" (_F), "0" (_Z80_A) \ + ) +#else +#define ADD(value) \ + asm ( \ + " addb %2,%0 \n" \ + " lahf \n" \ + " setob %1 \n" /* al = 1 if overflow */ \ + " addb %1,%1 \n" \ + " addb %1,%1 \n" /* shift to P/V bit position */ \ + " andb $0xd1,%%ah \n" /* sign, zero, half carry, carry */ \ + " orb %%ah,%1 \n" \ + :"=q" (_Z80_A), "=q" (_F) \ + :"q" (value), "1" (_F), "0" (_Z80_A) \ + ) +#endif +#else +#if BIG_FLAGS_ARRAY +#define ADD(z80,value) \ +{ \ + UINT32 ah = _AFD & 0xff00; \ + UINT32 res = (UINT8)((ah >> 8) + value); \ + _F = z80->SZHVC_add[ah | res]; \ + _Z80_A = res; \ +} +#else +#define ADD(value) \ +{ \ + unsigned val = value; \ + unsigned res = _Z80_A + val; \ + _F = SZ[(UINT8)res] | ((res >> 8) & CF) | \ + ((_Z80_A ^ res ^ val) & HF) | \ + (((val ^ _Z80_A ^ 0x80) & (val ^ res) & 0x80) >> 5); \ + _Z80_A = (UINT8)res; \ +} +#endif +#endif + +/*************************************************************** + * ADC A,n + ***************************************************************/ +#ifdef X86_ASM +#if Z80_EXACT +#define ADC(value) \ + asm ( \ + " shrb $1,%1 \n" \ + " adcb %2,%0 \n" \ + " lahf \n" \ + " setob %1 \n" /* al = 1 if overflow */ \ + " addb %1,%1 \n" /* shift to P/V bit position */ \ + " addb %1,%1 \n" \ + " andb $0xd1,%%ah \n" /* sign, zero, half carry, carry */ \ + " orb %%ah,%1 \n" /* combine with P/V */ \ + " movb %0,%%ah \n" /* get result */ \ + " andb $0x28,%%ah \n" /* maks flags 5+3 */ \ + " orb %%ah,%1 \n" /* put them into flags */ \ + :"=q" (_Z80_A), "=q" (_F) \ + :"q" (value), "1" (_F), "0" (_Z80_A) \ + ) +#else +#define ADC(value) \ + asm ( \ + " shrb $1,%1 \n" \ + " adcb %2,%0 \n" \ + " lahf \n" \ + " setob %1 \n" /* al = 1 if overflow */ \ + " addb %1,%1 \n" /* shift to P/V bit position */ \ + " addb %1,%1 \n" \ + " andb $0xd1,%%ah \n" /* sign, zero, half carry, carry */ \ + " orb %%ah,%1 \n" /* combine with P/V */ \ + :"=q" (_Z80_A), "=q" (_F) \ + :"q" (value), "1" (_F), "0" (_Z80_A) \ + ) +#endif +#else +#if BIG_FLAGS_ARRAY +#define ADC(value) \ +{ \ + UINT32 ah = _AFD & 0xff00, c = _AFD & 1; \ + UINT32 res = (UINT8)((ah >> 8) + value + c); \ + _F = z80->SZHVC_add[(c << 16) | ah | res]; \ + _Z80_A = res; \ +} +#else +#define ADC(value) \ +{ \ + unsigned val = value; \ + unsigned res = _Z80_A + val + (_F & CF); \ + _F = SZ[res & 0xff] | ((res >> 8) & CF) | \ + ((_Z80_A ^ res ^ val) & HF) | \ + (((val ^ _Z80_A ^ 0x80) & (val ^ res) & 0x80) >> 5); \ + _Z80_A = res; \ +} +#endif +#endif + +/*************************************************************** + * SUB n + ***************************************************************/ +#ifdef X86_ASM +#if Z80_EXACT +#define SUB(value) \ + asm ( \ + " subb %2,%0 \n" \ + " lahf \n" \ + " setob %1 \n" /* al = 1 if overflow */ \ + " stc \n" /* prepare to set N flag */ \ + " adcb %1,%1 \n" /* shift to P/V bit position */ \ + " addb %1,%1 \n" \ + " andb $0xd1,%%ah \n" /* sign, zero, half carry, carry */ \ + " orb %%ah,%1 \n" /* combine with P/V */ \ + " movb %0,%%ah \n" /* get result */ \ + " andb $0x28,%%ah \n" /* maks flags 5+3 */ \ + " orb %%ah,%1 \n" /* put them into flags */ \ + :"=q" (_Z80_A), "=q" (_F) \ + :"q" (value), "1" (_F), "0" (_Z80_A) \ + ) +#else +#define SUB(value) \ + asm ( \ + " subb %2,%0 \n" \ + " lahf \n" \ + " setob %1 \n" /* al = 1 if overflow */ \ + " stc \n" /* prepare to set N flag */ \ + " adcb %1,%1 \n" /* shift to P/V bit position */ \ + " addb %1,%1 \n" \ + " andb $0xd1,%%ah \n" /* sign, zero, half carry, carry */ \ + " orb %%ah,%1 \n" /* combine with P/V */ \ + :"=q" (_Z80_A), "=q" (_F) \ + :"q" (value), "1" (_F), "0" (_Z80_A) \ + ) +#endif +#else +#if BIG_FLAGS_ARRAY +#define SUB(value) \ +{ \ + UINT32 ah = _AFD & 0xff00; \ + UINT32 res = (UINT8)((ah >> 8) - value); \ + _F = z80->SZHVC_sub[ah | res]; \ + _Z80_A = res; \ +} +#else +#define SUB(value) \ +{ \ + unsigned val = value; \ + unsigned res = _Z80_A - val; \ + _F = SZ[res & 0xff] | ((res >> 8) & CF) | NF | \ + ((_Z80_A ^ res ^ val) & HF) | \ + (((val ^ _Z80_A) & (_Z80_A ^ res) & 0x80) >> 5); \ + _Z80_A = res; \ +} +#endif +#endif + +/*************************************************************** + * SBC A,n + ***************************************************************/ +#ifdef X86_ASM +#if Z80_EXACT +#define SBC(value) \ + asm ( \ + " shrb $1,%1 \n" \ + " sbbb %2,%0 \n" \ + " lahf \n" \ + " setob %1 \n" /* al = 1 if overflow */ \ + " stc \n" /* prepare to set N flag */ \ + " adcb %1,%1 \n" /* shift to P/V bit position */ \ + " addb %1,%1 \n" \ + " andb $0xd1,%%ah \n" /* sign, zero, half carry, carry */ \ + " orb %%ah,%1 \n" /* combine with P/V */ \ + " movb %0,%%ah \n" /* get result */ \ + " andb $0x28,%%ah \n" /* maks flags 5+3 */ \ + " orb %%ah,%1 \n" /* put them into flags */ \ + :"=q" (_Z80_A), "=q" (_F) \ + :"q" (value), "1" (_F), "0" (_Z80_A) \ + ) +#else +#define SBC(value) \ + asm ( \ + " shrb $1,%1 \n" \ + " sbbb %2,%0 \n" \ + " lahf \n" \ + " setob %1 \n" /* al = 1 if overflow */ \ + " stc \n" /* prepare to set N flag */ \ + " adcb %1,%1 \n" /* shift to P/V bit position */ \ + " addb %1,%1 \n" \ + " andb $0xd1,%%ah \n" /* sign, zero, half carry, carry */ \ + " orb %%ah,%1 \n" /* combine with P/V */ \ + :"=q" (_Z80_A), "=q" (_F) \ + :"q" (value), "1" (_F), "0" (_Z80_A) \ + ) +#endif +#else +#if BIG_FLAGS_ARRAY +#define SBC(value) \ +{ \ + UINT32 ah = _AFD & 0xff00, c = _AFD & 1; \ + UINT32 res = (UINT8)((ah >> 8) - value - c); \ + _F = z80->SZHVC_sub[(c<<16) | ah | res]; \ + _Z80_A = res; \ +} +#else +#define SBC(value) \ +{ \ + unsigned val = value; \ + unsigned res = _Z80_A - val - (_F & CF); \ + _F = SZ[res & 0xff] | ((res >> 8) & CF) | NF | \ + ((_Z80_A ^ res ^ val) & HF) | \ + (((val ^ _Z80_A) & (_Z80_A ^ res) & 0x80) >> 5); \ + _Z80_A = res; \ +} +#endif +#endif + +/*************************************************************** + * NEG + ***************************************************************/ +#define NEG { \ + UINT8 value = _Z80_A; \ + _Z80_A = 0; \ + SUB(value); \ +} + +/*************************************************************** + * DAA + ***************************************************************/ +#define DAA { \ + UINT8 cf, nf, hf, lo, hi, diff; \ + cf = _F & CF; \ + nf = _F & NF; \ + hf = _F & HF; \ + lo = _Z80_A & 15; \ + hi = _Z80_A / 16; \ + \ + if (cf) \ + { \ + diff = (lo <= 9 && !hf) ? 0x60 : 0x66; \ + } \ + else \ + { \ + if (lo >= 10) \ + { \ + diff = hi <= 8 ? 0x06 : 0x66; \ + } \ + else \ + { \ + if (hi >= 10) \ + { \ + diff = hf ? 0x66 : 0x60; \ + } \ + else \ + { \ + diff = hf ? 0x06 : 0x00; \ + } \ + } \ + } \ + if (nf) _Z80_A -= diff; \ + else _Z80_A += diff; \ + \ + _F = z80->SZP[_Z80_A] | (_F & NF); \ + if (cf || (lo <= 9 ? hi >= 10 : hi >= 9)) _F |= CF; \ + if (nf ? hf && lo <= 5 : lo >= 10) _F |= HF; \ +} + +/*************************************************************** + * AND n + ***************************************************************/ +#define AND(value) \ + _Z80_A &= value; \ + _F = z80->SZP[_Z80_A] | HF + +/*************************************************************** + * OR n + ***************************************************************/ +#define OR(value) \ + _Z80_A |= value; \ + _F = z80->SZP[_Z80_A] + +/*************************************************************** + * XOR n + ***************************************************************/ +#define XOR(value) \ + _Z80_A ^= value; \ + _F = z80->SZP[_Z80_A] + +/*************************************************************** + * CP n + ***************************************************************/ +#ifdef X86_ASM +#if Z80_EXACT +#define CP(value) \ + asm ( \ + " cmpb %2,%0 \n" \ + " lahf \n" \ + " setob %1 \n" /* al = 1 if overflow */ \ + " stc \n" /* prepare to set N flag */ \ + " adcb %1,%1 \n" /* shift to P/V bit position */ \ + " addb %1,%1 \n" \ + " andb $0xd1,%%ah \n" /* sign, zero, half carry, carry */ \ + " orb %%ah,%1 \n" /* combine with P/V */ \ + " movb %2,%%ah \n" /* get result */ \ + " andb $0x28,%%ah \n" /* maks flags 5+3 */ \ + " orb %%ah,%1 \n" /* put them into flags */ \ + :"=q" (_Z80_A), "=q" (_F) \ + :"q" (value), "1" (_F), "0" (_Z80_A) \ + ) +#else +#define CP(value) \ + asm ( \ + " cmpb %2,%0 \n" \ + " lahf \n" \ + " setob %1 \n" /* al = 1 if overflow */ \ + " stc \n" /* prepare to set N flag */ \ + " adcb %1,%1 \n" /* shift to P/V bit position */ \ + " addb %1,%1 \n" \ + " andb $0xd1,%%ah \n" /* sign, zero, half carry, carry */ \ + " orb %%ah,%1 \n" /* combine with P/V */ \ + :"=q" (_Z80_A), "=q" (_F) \ + :"q" (value), "1" (_F), "0" (_Z80_A) \ + ) +#endif +#else +#if BIG_FLAGS_ARRAY +#define CP(value) \ +{ \ + unsigned val = value; \ + UINT32 ah = _AFD & 0xff00; \ + UINT32 res = (UINT8)((ah >> 8) - val); \ + _F = (z80->SZHVC_sub[ah | res] & ~(YF | XF)) | \ + (val & (YF | XF)); \ +} +#else +#define CP(value) \ +{ \ + unsigned val = value; \ + unsigned res = _Z80_A - val; \ + _F = (SZ[res & 0xff] & (SF | ZF)) | \ + (val & (YF | XF)) | ((res >> 8) & CF) | NF | \ + ((_Z80_A ^ res ^ val) & HF) | \ + ((((val ^ _Z80_A) & (_Z80_A ^ res)) >> 5) & VF); \ +} +#endif +#endif + +/*************************************************************** + * EX AF,AF' + ***************************************************************/ +#define EX_AF { \ + PAIR tmp; \ + tmp = z80->Z80.AF; z80->Z80.AF = z80->Z80.AF2; z80->Z80.AF2 = tmp; \ +} + +/*************************************************************** + * EX DE,HL + ***************************************************************/ +#define EX_DE_HL { \ + PAIR tmp; \ + tmp = z80->Z80.DE; z80->Z80.DE = z80->Z80.HL; z80->Z80.HL = tmp; \ +} + +/*************************************************************** + * EXX + ***************************************************************/ +#define EXX { \ + PAIR tmp; \ + tmp = z80->Z80.BC; z80->Z80.BC = z80->Z80.BC2; z80->Z80.BC2 = tmp; \ + tmp = z80->Z80.DE; z80->Z80.DE = z80->Z80.DE2; z80->Z80.DE2 = tmp; \ + tmp = z80->Z80.HL; z80->Z80.HL = z80->Z80.HL2; z80->Z80.HL2 = tmp; \ +} + +/*************************************************************** + * EX (SP),r16 + ***************************************************************/ +#define EXSP(DR) \ +{ \ + PAIR tmp = { { 0, 0, 0, 0 } }; \ + RM16(z80, _SPD, &tmp ); \ + WM16( z80, _SPD, &z80->Z80.DR ); \ + z80->Z80.DR = tmp; \ +} + + +/*************************************************************** + * ADD16 + ***************************************************************/ +#ifdef X86_ASM +#if Z80_EXACT +#define ADD16(z80,DR,SR) \ + asm ( \ + " andb $0xc4,%1 \n" \ + " addb %%dl,%%cl \n" \ + " adcb %%dh,%%ch \n" \ + " lahf \n" \ + " andb $0x11,%%ah \n" \ + " orb %%ah,%1 \n" \ + " movb %%ch,%%ah \n" /* get result MSB */ \ + " andb $0x28,%%ah \n" /* maks flags 5+3 */ \ + " orb %%ah,%1 \n" /* put them into flags */ \ + :"=c" (z80->Z80.DR.d), "=q" (_F) \ + :"0" (z80->Z80.DR.d), "1" (_F), "d" (Z80.SR.d) \ + ) +#else +#define ADD16(z80,DR,SR) \ + asm ( \ + " andb $0xc4,%1 \n" \ + " addb %%dl,%%cl \n" \ + " adcb %%dh,%%ch \n" \ + " lahf \n" \ + " andb $0x11,%%ah \n" \ + " orb %%ah,%1 \n" \ + :"=c" (z80->Z80.DR.d), "=q" (_F) \ + :"0" (z80->Z80.DR.d), "1" (_F), "d" (Z80.SR.d) \ + ) +#endif +#else +#define ADD16(z80,DR,SR) \ +{ \ + UINT32 res = z80->Z80.DR.d + z80->Z80.SR.d; \ + _F = (_F & (SF | ZF | VF)) | \ + (((z80->Z80.DR.d ^ res ^ z80->Z80.SR.d) >> 8) & HF) | \ + ((res >> 16) & CF) | ((res >> 8) & (YF | XF)); \ + z80->Z80.DR.w.l = (UINT16)res; \ +} +#endif + +/*************************************************************** + * ADC r16,r16 + ***************************************************************/ +#ifdef X86_ASM +#if Z80_EXACT +#define ADC16(Reg) \ + asm ( \ + " shrb $1,%1 \n" \ + " adcb %%dl,%%cl \n" \ + " lahf \n" \ + " movb %%ah,%%dl \n" \ + " adcb %%dh,%%ch \n" \ + " lahf \n" \ + " setob %1 \n" \ + " orb $0xbf,%%dl \n" /* set all but zero */ \ + " addb %1,%1 \n" \ + " andb $0xd1,%%ah \n" /* sign,zero,half carry and carry */\ + " addb %1,%1 \n" \ + " orb %%ah,%1 \n" /* overflow into P/V */ \ + " andb %%dl,%1 \n" /* mask zero */ \ + " movb %%ch,%%ah \n" /* get result MSB */ \ + " andb $0x28,%%ah \n" /* maks flags 5+3 */ \ + " orb %%ah,%1 \n" /* put them into flags */ \ + :"=c" (_HLD), "=q" (_F) \ + :"0" (_HLD), "1" (_F), "d" (Z80.Reg.d) \ + ) +#else +#define ADC16(Reg) \ + asm ( \ + " shrb $1,%1 \n" \ + " adcb %%dl,%%cl \n" \ + " lahf \n" \ + " movb %%ah,%%dl \n" \ + " adcb %%dh,%%ch \n" \ + " lahf \n" \ + " setob %1 \n" \ + " orb $0xbf,%%dl \n" /* set all but zero */ \ + " addb %1,%1 \n" \ + " andb $0xd1,%%ah \n" /* sign,zero,half carry and carry */\ + " addb %1,%1 \n" \ + " orb %%ah,%1 \n" /* overflow into P/V */ \ + " andb %%dl,%1 \n" /* mask zero */ \ + :"=c" (_HLD), "=q" (_F) \ + :"0" (_HLD), "1" (_F), "d" (Z80.Reg.d) \ + ) +#endif +#else +#define ADC16(Reg) \ +{ \ + UINT32 res = _HLD + z80->Z80.Reg.d + (_F & CF); \ + _F = (((_HLD ^ res ^ z80->Z80.Reg.d) >> 8) & HF) | \ + ((res >> 16) & CF) | \ + ((res >> 8) & (SF | YF | XF)) | \ + ((res & 0xffff) ? 0 : ZF) | \ + (((z80->Z80.Reg.d ^ _HLD ^ 0x8000) & (z80->Z80.Reg.d ^ res) & 0x8000) >> 13); \ + _HL = (UINT16)res; \ +} +#endif + +/*************************************************************** + * SBC r16,r16 + ***************************************************************/ +#ifdef X86_ASM +#if Z80_EXACT +#define SBC16(Reg) \ +asm ( \ + " shrb $1,%1 \n" \ + " sbbb %%dl,%%cl \n" \ + " lahf \n" \ + " movb %%ah,%%dl \n" \ + " sbbb %%dh,%%ch \n" \ + " lahf \n" \ + " setob %1 \n" \ + " orb $0xbf,%%dl \n" /* set all but zero */ \ + " stc \n" \ + " adcb %1,%1 \n" \ + " andb $0xd1,%%ah \n" /* sign,zero,half carry and carry */\ + " addb %1,%1 \n" \ + " orb %%ah,%1 \n" /* overflow into P/V */ \ + " andb %%dl,%1 \n" /* mask zero */ \ + " movb %%ch,%%ah \n" /* get result MSB */ \ + " andb $0x28,%%ah \n" /* maks flags 5+3 */ \ + " orb %%ah,%1 \n" /* put them into flags */ \ + :"=c" (_HLD), "=q" (_F) \ + :"0" (_HLD), "1" (_F), "d" (Z80.Reg.d) \ + ) +#else +#define SBC16(Reg) \ +asm ( \ + " shrb $1,%1 \n" \ + " sbbb %%dl,%%cl \n" \ + " lahf \n" \ + " movb %%ah,%%dl \n" \ + " sbbb %%dh,%%ch \n" \ + " lahf \n" \ + " setob %1 \n" \ + " orb $0xbf,%%dl \n" /* set all but zero */ \ + " stc \n" \ + " adcb %1,%1 \n" \ + " andb $0xd1,%%ah \n" /* sign,zero,half carry and carry */\ + " addb %1,%1 \n" \ + " orb %%ah,%1 \n" /* overflow into P/V */ \ + " andb %%dl,%1 \n" /* mask zero */ \ + :"=c" (_HLD), "=q" (_F) \ + :"0" (_HLD), "1" (_F), "d" (Z80.Reg.d) \ + ) +#endif +#else +#define SBC16(Reg) \ +{ \ + UINT32 res = _HLD - z80->Z80.Reg.d - (_F & CF); \ + _F = (((_HLD ^ res ^ z80->Z80.Reg.d) >> 8) & HF) | NF | \ + ((res >> 16) & CF) | \ + ((res >> 8) & (SF | YF | XF)) | \ + ((res & 0xffff) ? 0 : ZF) | \ + (((z80->Z80.Reg.d ^ _HLD) & (_HLD ^ res) &0x8000) >> 13); \ + _HL = (UINT16)res; \ +} +#endif + +/*************************************************************** + * RLC r8 + ***************************************************************/ +INLINE UINT8 RLC(z80_state_t *z80, UINT8 value) +{ + unsigned res = value; + unsigned c = (res & 0x80) ? CF : 0; + res = ((res << 1) | (res >> 7)) & 0xff; + _F = z80->SZP[res] | c; + return res; +} + +/*************************************************************** + * RRC r8 + ***************************************************************/ +INLINE UINT8 RRC(z80_state_t *z80, UINT8 value) +{ + unsigned res = value; + unsigned c = (res & 0x01) ? CF : 0; + res = ((res >> 1) | (res << 7)) & 0xff; + _F = z80->SZP[res] | c; + return res; +} + +/*************************************************************** + * RL r8 + ***************************************************************/ +INLINE UINT8 RL(z80_state_t *z80, UINT8 value) +{ + unsigned res = value; + unsigned c = (res & 0x80) ? CF : 0; + res = ((res << 1) | (_F & CF)) & 0xff; + _F = z80->SZP[res] | c; + return res; +} + +/*************************************************************** + * RR r8 + ***************************************************************/ +INLINE UINT8 RR(z80_state_t *z80, UINT8 value) +{ + unsigned res = value; + unsigned c = (res & 0x01) ? CF : 0; + res = ((res >> 1) | (_F << 7)) & 0xff; + _F = z80->SZP[res] | c; + return res; +} + +/*************************************************************** + * SLA r8 + ***************************************************************/ +INLINE UINT8 SLA(z80_state_t *z80, UINT8 value) +{ + unsigned res = value; + unsigned c = (res & 0x80) ? CF : 0; + res = (res << 1) & 0xff; + _F = z80->SZP[res] | c; + return res; +} + +/*************************************************************** + * SRA r8 + ***************************************************************/ +INLINE UINT8 SRA(z80_state_t *z80, UINT8 value) +{ + unsigned res = value; + unsigned c = (res & 0x01) ? CF : 0; + res = ((res >> 1) | (res & 0x80)) & 0xff; + _F = z80->SZP[res] | c; + return res; +} + +/*************************************************************** + * SLL r8 + ***************************************************************/ +INLINE UINT8 SLL(z80_state_t *z80, UINT8 value) +{ + unsigned res = value; + unsigned c = (res & 0x80) ? CF : 0; + res = ((res << 1) | 0x01) & 0xff; + _F = z80->SZP[res] | c; + return res; +} + +/*************************************************************** + * SRL r8 + ***************************************************************/ +INLINE UINT8 SRL(z80_state_t *z80, UINT8 value) +{ + unsigned res = value; + unsigned c = (res & 0x01) ? CF : 0; + res = (res >> 1) & 0xff; + _F = z80->SZP[res] | c; + return res; +} + +/*************************************************************** + * BIT bit,r8 + ***************************************************************/ +#undef BIT +#define BIT(z80,bit,reg) \ + _F = (_F & CF) | HF | z80->SZ_BIT[reg & (1<<bit)] + +/*************************************************************** + * BIT bit,(IX/Y+o) + ***************************************************************/ +#if Z80_EXACT +#define BIT_XY(z80,bit,reg) \ + _F = (_F & CF) | HF | (z80->SZ_BIT[reg & (1<<bit)] & ~(YF|XF)) | ((z80->EA>>8) & (YF|XF)) +#else +#define BIT_XY BIT +#endif + +/*************************************************************** + * RES bit,r8 + ***************************************************************/ +INLINE UINT8 RES(z80_state_t *z80, UINT8 bit, UINT8 value) +{ + return value & ~(1<<bit); +} + +/*************************************************************** + * SET bit,r8 + ***************************************************************/ +INLINE UINT8 SET(z80_state_t *z80, UINT8 bit, UINT8 value) +{ + return value | (1<<bit); +} + +/*************************************************************** + * LDI + ***************************************************************/ +#if Z80_EXACT +#define LDI { \ + UINT8 io = RM(_HL); \ + WM( _DE, io ); \ + _F &= SF | ZF | CF; \ + if( (_Z80_A + io) & 0x02 ) _F |= YF; /* bit 1 -> flag 5 */ \ + if( (_Z80_A + io) & 0x08 ) _F |= XF; /* bit 3 -> flag 3 */ \ + _HL++; _DE++; _BC--; \ + if( _BC ) _F |= VF; \ +} +#else +#define LDI { \ + WM( _DE, RM(_HL) ); \ + _F &= SF | ZF | YF | XF | CF; \ + _HL++; _DE++; _BC--; \ + if( _BC ) _F |= VF; \ +} +#endif + +/*************************************************************** + * CPI + ***************************************************************/ +#if Z80_EXACT +#define CPI { \ + UINT8 val = RM(_HL); \ + UINT8 res = _Z80_A - val; \ + _HL++; _BC--; \ + _F = (_F & CF) | (z80->SZ[res] & ~(YF|XF)) | ((_Z80_A ^ val ^ res) & HF) | NF; \ + if( _F & HF ) res -= 1; \ + if( res & 0x02 ) _F |= YF; /* bit 1 -> flag 5 */ \ + if( res & 0x08 ) _F |= XF; /* bit 3 -> flag 3 */ \ + if( _BC ) _F |= VF; \ +} +#else +#define CPI { \ + UINT8 val = RM(_HL); \ + UINT8 res = _Z80_A - val; \ + _HL++; _BC--; \ + _F = (_F & CF) | z80->SZ[res] | ((_Z80_A ^ val ^ res) & HF) | NF; \ + if( _BC ) _F |= VF; \ +} +#endif + +/*************************************************************** + * INI + ***************************************************************/ +#if Z80_EXACT +#define INI { \ + unsigned t; \ + UINT8 io = IN(_BC); \ + _Z80_B--; \ + WM( _HL, io ); \ + _HL++; \ + _F = z80->SZ[_Z80_B]; \ + t = (unsigned)((_Z80_C + 1) & 0xff) + (unsigned)io; \ + if( io & SF ) _F |= NF; \ + if( t & 0x100 ) _F |= HF | CF; \ + _F |= z80->SZP[(UINT8)(t & 0x07) ^ _Z80_B] & PF; \ +} +#else +#define INI { \ + _Z80_B--; \ + WM( _HL, IN(_BC) ); \ + _HL++; \ + _F = (_Z80_B) ? NF : NF | ZF; \ +} +#endif + +/*************************************************************** + * OUTI + ***************************************************************/ +#if Z80_EXACT +#define OUTI { \ + unsigned t; \ + UINT8 io = RM(_HL); \ + _Z80_B--; \ + OUT( _BC, io ); \ + _HL++; \ + _F = z80->SZ[_Z80_B]; \ + t = (unsigned)_Z80_L + (unsigned)io; \ + if( io & SF ) _F |= NF; \ + if( t & 0x100 ) _F |= HF | CF; \ + _F |= z80->SZP[(UINT8)(t & 0x07) ^ _Z80_B] & PF; \ +} +#else +#define OUTI { \ + _Z80_B--; \ + OUT( _BC, RM(_HL) ); \ + _HL++; \ + _F = (_Z80_B) ? NF : NF | ZF; \ +} +#endif + +/*************************************************************** + * LDD + ***************************************************************/ +#if Z80_EXACT +#define LDD { \ + UINT8 io = RM(_HL); \ + WM( _DE, io ); \ + _F &= SF | ZF | CF; \ + if( (_Z80_A + io) & 0x02 ) _F |= YF; /* bit 1 -> flag 5 */ \ + if( (_Z80_A + io) & 0x08 ) _F |= XF; /* bit 3 -> flag 3 */ \ + _HL--; _DE--; _BC--; \ + if( _BC ) _F |= VF; \ +} +#else +#define LDD { \ + WM( _DE, RM(_HL) ); \ + _F &= SF | ZF | YF | XF | CF; \ + _HL--; _DE--; _BC--; \ + if( _BC ) _F |= VF; \ +} +#endif + +/*************************************************************** + * CPD + ***************************************************************/ +#if Z80_EXACT +#define CPD { \ + UINT8 val = RM(_HL); \ + UINT8 res = _Z80_A - val; \ + _HL--; _BC--; \ + _F = (_F & CF) | (z80->SZ[res] & ~(YF|XF)) | ((_Z80_A ^ val ^ res) & HF) | NF; \ + if( _F & HF ) res -= 1; \ + if( res & 0x02 ) _F |= YF; /* bit 1 -> flag 5 */ \ + if( res & 0x08 ) _F |= XF; /* bit 3 -> flag 3 */ \ + if( _BC ) _F |= VF; \ +} +#else +#define CPD { \ + UINT8 val = RM(_HL); \ + UINT8 res = _Z80_A - val; \ + _HL--; _BC--; \ + _F = (_F & CF) | z80->SZ[res] | ((_Z80_A ^ val ^ res) & HF) | NF; \ + if( _BC ) _F |= VF; \ +} +#endif + +/*************************************************************** + * IND + ***************************************************************/ +#if Z80_EXACT +#define IND { \ + unsigned t; \ + UINT8 io = IN(_BC); \ + _Z80_B--; \ + WM( _HL, io ); \ + _HL--; \ + _F = z80->SZ[_Z80_B]; \ + t = ((unsigned)(_Z80_C - 1) & 0xff) + (unsigned)io; \ + if( io & SF ) _F |= NF; \ + if( t & 0x100 ) _F |= HF | CF; \ + _F |= z80->SZP[(UINT8)(t & 0x07) ^ _Z80_B] & PF; \ +} +#else +#define IND { \ + _Z80_B--; \ + WM( _HL, IN(_BC) ); \ + _HL--; \ + _F = (_Z80_B) ? NF : NF | ZF; \ +} +#endif + +/*************************************************************** + * OUTD + ***************************************************************/ +#if Z80_EXACT +#define OUTD { \ + unsigned t; \ + UINT8 io = RM(_HL); \ + _Z80_B--; \ + OUT( _BC, io ); \ + _HL--; \ + _F = z80->SZ[_Z80_B]; \ + t = (unsigned)_Z80_L + (unsigned)io; \ + if( io & SF ) _F |= NF; \ + if( t & 0x100 ) _F |= HF | CF; \ + _F |= z80->SZP[(UINT8)(t & 0x07) ^ _Z80_B] & PF; \ +} +#else +#define OUTD { \ + _Z80_B--; \ + OUT( _BC, RM(_HL) ); \ + _HL--; \ + _F = (_Z80_B) ? NF : NF | ZF; \ +} +#endif + +/*************************************************************** + * LDIR + ***************************************************************/ +#define LDIR \ + LDI; \ + if( _BC ) \ + { \ + _PC -= 2; \ + CC(ex,0xb0); \ + } + +/*************************************************************** + * CPIR + ***************************************************************/ +#define CPIR \ + CPI; \ + if( _BC && !(_F & ZF) ) \ + { \ + _PC -= 2; \ + CC(ex,0xb1); \ + } + +/*************************************************************** + * INIR + ***************************************************************/ +#define INIR \ + INI; \ + if( _Z80_B ) \ + { \ + _PC -= 2; \ + CC(ex,0xb2); \ + } + +/*************************************************************** + * OTIR + ***************************************************************/ +#define OTIR \ + OUTI; \ + if( _Z80_B ) \ + { \ + _PC -= 2; \ + CC(ex,0xb3); \ + } + +/*************************************************************** + * LDDR + ***************************************************************/ +#define LDDR \ + LDD; \ + if( _BC ) \ + { \ + _PC -= 2; \ + CC(ex,0xb8); \ + } + +/*************************************************************** + * CPDR + ***************************************************************/ +#define CPDR \ + CPD; \ + if( _BC && !(_F & ZF) ) \ + { \ + _PC -= 2; \ + CC(ex,0xb9); \ + } + +/*************************************************************** + * INDR + ***************************************************************/ +#define INDR \ + IND; \ + if( _Z80_B ) \ + { \ + _PC -= 2; \ + CC(ex,0xba); \ + } + +/*************************************************************** + * OTDR + ***************************************************************/ +#define OTDR \ + OUTD; \ + if( _Z80_B ) \ + { \ + _PC -= 2; \ + CC(ex,0xbb); \ + } + +/*************************************************************** + * EI + ***************************************************************/ +#define EI { \ + /* If interrupts were disabled, execute one more \ + * instruction and check the IRQ line. \ + * If not, simply set interrupt flip-flop 2 \ + */ \ + if( _IFF1 == 0 ) \ + { \ + _IFF1 = _IFF2 = 1; \ + _PPC = _PCD; \ + CALL_MAME_DEBUG; \ + _Z80_R++; \ + while( cpu_readop(z80->userdata,_PCD) == 0xfb ) /* more EIs? */ \ + { \ + CC(op,0xfb); \ + _PPC =_PCD; \ + CALL_MAME_DEBUG; \ + _PC++; \ + _Z80_R++; \ + } \ + if( z80->Z80.irq_state != CLEAR_LINE || \ + z80->Z80.request_irq >= 0 ) \ + { \ + z80->after_EI = 1; /* avoid cycle skip hacks */ \ + EXEC(op,ROP(z80)); \ + z80->after_EI = 0; \ + take_interrupt(z80); \ + } else EXEC(op,ROP(z80)); \ + } else _IFF2 = 1; \ +} + +/********************************************************** + * opcodes with CB prefix + * rotate, shift and bit operations + **********************************************************/ +OP(cb,00) { _Z80_B = RLC(z80, _Z80_B); } /* RLC B */ +OP(cb,01) { _Z80_C = RLC(z80, _Z80_C); } /* RLC C */ +OP(cb,02) { _Z80_D = RLC(z80, _Z80_D); } /* RLC D */ +OP(cb,03) { _Z80_E = RLC(z80, _Z80_E); } /* RLC E */ +OP(cb,04) { _Z80_H = RLC(z80, _Z80_H); } /* RLC H */ +OP(cb,05) { _Z80_L = RLC(z80, _Z80_L); } /* RLC L */ +OP(cb,06) { WM( _HL, RLC(z80, RM(_HL)) ); } /* RLC (HL) */ +OP(cb,07) { _Z80_A = RLC(z80, _Z80_A); } /* RLC A */ + +OP(cb,08) { _Z80_B = RRC(z80, _Z80_B); } /* RRC B */ +OP(cb,09) { _Z80_C = RRC(z80, _Z80_C); } /* RRC C */ +OP(cb,0a) { _Z80_D = RRC(z80, _Z80_D); } /* RRC D */ +OP(cb,0b) { _Z80_E = RRC(z80, _Z80_E); } /* RRC E */ +OP(cb,0c) { _Z80_H = RRC(z80, _Z80_H); } /* RRC H */ +OP(cb,0d) { _Z80_L = RRC(z80, _Z80_L); } /* RRC L */ +OP(cb,0e) { WM( _HL, RRC(z80, RM(_HL)) ); } /* RRC (HL) */ +OP(cb,0f) { _Z80_A = RRC(z80, _Z80_A); } /* RRC A */ + +OP(cb,10) { _Z80_B = RL(z80, _Z80_B); } /* RL B */ +OP(cb,11) { _Z80_C = RL(z80, _Z80_C); } /* RL C */ +OP(cb,12) { _Z80_D = RL(z80, _Z80_D); } /* RL D */ +OP(cb,13) { _Z80_E = RL(z80, _Z80_E); } /* RL E */ +OP(cb,14) { _Z80_H = RL(z80, _Z80_H); } /* RL H */ +OP(cb,15) { _Z80_L = RL(z80, _Z80_L); } /* RL L */ +OP(cb,16) { WM( _HL, RL(z80, RM(_HL)) ); } /* RL (HL) */ +OP(cb,17) { _Z80_A = RL(z80, _Z80_A); } /* RL A */ + +OP(cb,18) { _Z80_B = RR(z80, _Z80_B); } /* RR B */ +OP(cb,19) { _Z80_C = RR(z80, _Z80_C); } /* RR C */ +OP(cb,1a) { _Z80_D = RR(z80, _Z80_D); } /* RR D */ +OP(cb,1b) { _Z80_E = RR(z80, _Z80_E); } /* RR E */ +OP(cb,1c) { _Z80_H = RR(z80, _Z80_H); } /* RR H */ +OP(cb,1d) { _Z80_L = RR(z80, _Z80_L); } /* RR L */ +OP(cb,1e) { WM( _HL, RR(z80, RM(_HL)) ); } /* RR (HL) */ +OP(cb,1f) { _Z80_A = RR(z80, _Z80_A); } /* RR A */ + +OP(cb,20) { _Z80_B = SLA(z80, _Z80_B); } /* SLA B */ +OP(cb,21) { _Z80_C = SLA(z80, _Z80_C); } /* SLA C */ +OP(cb,22) { _Z80_D = SLA(z80, _Z80_D); } /* SLA D */ +OP(cb,23) { _Z80_E = SLA(z80, _Z80_E); } /* SLA E */ +OP(cb,24) { _Z80_H = SLA(z80, _Z80_H); } /* SLA H */ +OP(cb,25) { _Z80_L = SLA(z80, _Z80_L); } /* SLA L */ +OP(cb,26) { WM( _HL, SLA(z80, RM(_HL)) ); } /* SLA (HL) */ +OP(cb,27) { _Z80_A = SLA(z80, _Z80_A); } /* SLA A */ + +OP(cb,28) { _Z80_B = SRA(z80, _Z80_B); } /* SRA B */ +OP(cb,29) { _Z80_C = SRA(z80, _Z80_C); } /* SRA C */ +OP(cb,2a) { _Z80_D = SRA(z80, _Z80_D); } /* SRA D */ +OP(cb,2b) { _Z80_E = SRA(z80, _Z80_E); } /* SRA E */ +OP(cb,2c) { _Z80_H = SRA(z80, _Z80_H); } /* SRA H */ +OP(cb,2d) { _Z80_L = SRA(z80, _Z80_L); } /* SRA L */ +OP(cb,2e) { WM( _HL, SRA(z80, RM(_HL)) ); } /* SRA (HL) */ +OP(cb,2f) { _Z80_A = SRA(z80, _Z80_A); } /* SRA A */ + +OP(cb,30) { _Z80_B = SLL(z80, _Z80_B); } /* SLL B */ +OP(cb,31) { _Z80_C = SLL(z80, _Z80_C); } /* SLL C */ +OP(cb,32) { _Z80_D = SLL(z80, _Z80_D); } /* SLL D */ +OP(cb,33) { _Z80_E = SLL(z80, _Z80_E); } /* SLL E */ +OP(cb,34) { _Z80_H = SLL(z80, _Z80_H); } /* SLL H */ +OP(cb,35) { _Z80_L = SLL(z80, _Z80_L); } /* SLL L */ +OP(cb,36) { WM( _HL, SLL(z80, RM(_HL)) ); } /* SLL (HL) */ +OP(cb,37) { _Z80_A = SLL(z80, _Z80_A); } /* SLL A */ + +OP(cb,38) { _Z80_B = SRL(z80, _Z80_B); } /* SRL B */ +OP(cb,39) { _Z80_C = SRL(z80, _Z80_C); } /* SRL C */ +OP(cb,3a) { _Z80_D = SRL(z80, _Z80_D); } /* SRL D */ +OP(cb,3b) { _Z80_E = SRL(z80, _Z80_E); } /* SRL E */ +OP(cb,3c) { _Z80_H = SRL(z80, _Z80_H); } /* SRL H */ +OP(cb,3d) { _Z80_L = SRL(z80, _Z80_L); } /* SRL L */ +OP(cb,3e) { WM( _HL, SRL(z80, RM(_HL)) ); } /* SRL (HL) */ +OP(cb,3f) { _Z80_A = SRL(z80, _Z80_A); } /* SRL A */ + +OP(cb,40) { BIT(z80, 0,_Z80_B); } /* BIT 0,B */ +OP(cb,41) { BIT(z80, 0,_Z80_C); } /* BIT 0,C */ +OP(cb,42) { BIT(z80, 0,_Z80_D); } /* BIT 0,D */ +OP(cb,43) { BIT(z80, 0,_Z80_E); } /* BIT 0,E */ +OP(cb,44) { BIT(z80, 0,_Z80_H); } /* BIT 0,H */ +OP(cb,45) { BIT(z80, 0,_Z80_L); } /* BIT 0,L */ +OP(cb,46) { BIT(z80, 0,RM(_HL)); } /* BIT 0,(HL) */ +OP(cb,47) { BIT(z80, 0,_Z80_A); } /* BIT 0,A */ + +OP(cb,48) { BIT(z80, 1,_Z80_B); } /* BIT 1,B */ +OP(cb,49) { BIT(z80, 1,_Z80_C); } /* BIT 1,C */ +OP(cb,4a) { BIT(z80, 1,_Z80_D); } /* BIT 1,D */ +OP(cb,4b) { BIT(z80, 1,_Z80_E); } /* BIT 1,E */ +OP(cb,4c) { BIT(z80, 1,_Z80_H); } /* BIT 1,H */ +OP(cb,4d) { BIT(z80, 1,_Z80_L); } /* BIT 1,L */ +OP(cb,4e) { BIT(z80, 1,RM(_HL)); } /* BIT 1,(HL) */ +OP(cb,4f) { BIT(z80, 1,_Z80_A); } /* BIT 1,A */ + +OP(cb,50) { BIT(z80, 2,_Z80_B); } /* BIT 2,B */ +OP(cb,51) { BIT(z80, 2,_Z80_C); } /* BIT 2,C */ +OP(cb,52) { BIT(z80, 2,_Z80_D); } /* BIT 2,D */ +OP(cb,53) { BIT(z80, 2,_Z80_E); } /* BIT 2,E */ +OP(cb,54) { BIT(z80, 2,_Z80_H); } /* BIT 2,H */ +OP(cb,55) { BIT(z80, 2,_Z80_L); } /* BIT 2,L */ +OP(cb,56) { BIT(z80, 2,RM(_HL)); } /* BIT 2,(HL) */ +OP(cb,57) { BIT(z80, 2,_Z80_A); } /* BIT 2,A */ + +OP(cb,58) { BIT(z80, 3,_Z80_B); } /* BIT 3,B */ +OP(cb,59) { BIT(z80, 3,_Z80_C); } /* BIT 3,C */ +OP(cb,5a) { BIT(z80, 3,_Z80_D); } /* BIT 3,D */ +OP(cb,5b) { BIT(z80, 3,_Z80_E); } /* BIT 3,E */ +OP(cb,5c) { BIT(z80, 3,_Z80_H); } /* BIT 3,H */ +OP(cb,5d) { BIT(z80, 3,_Z80_L); } /* BIT 3,L */ +OP(cb,5e) { BIT(z80, 3,RM(_HL)); } /* BIT 3,(HL) */ +OP(cb,5f) { BIT(z80, 3,_Z80_A); } /* BIT 3,A */ + +OP(cb,60) { BIT(z80, 4,_Z80_B); } /* BIT 4,B */ +OP(cb,61) { BIT(z80, 4,_Z80_C); } /* BIT 4,C */ +OP(cb,62) { BIT(z80, 4,_Z80_D); } /* BIT 4,D */ +OP(cb,63) { BIT(z80, 4,_Z80_E); } /* BIT 4,E */ +OP(cb,64) { BIT(z80, 4,_Z80_H); } /* BIT 4,H */ +OP(cb,65) { BIT(z80, 4,_Z80_L); } /* BIT 4,L */ +OP(cb,66) { BIT(z80, 4,RM(_HL)); } /* BIT 4,(HL) */ +OP(cb,67) { BIT(z80, 4,_Z80_A); } /* BIT 4,A */ + +OP(cb,68) { BIT(z80, 5,_Z80_B); } /* BIT 5,B */ +OP(cb,69) { BIT(z80, 5,_Z80_C); } /* BIT 5,C */ +OP(cb,6a) { BIT(z80, 5,_Z80_D); } /* BIT 5,D */ +OP(cb,6b) { BIT(z80, 5,_Z80_E); } /* BIT 5,E */ +OP(cb,6c) { BIT(z80, 5,_Z80_H); } /* BIT 5,H */ +OP(cb,6d) { BIT(z80, 5,_Z80_L); } /* BIT 5,L */ +OP(cb,6e) { BIT(z80, 5,RM(_HL)); } /* BIT 5,(HL) */ +OP(cb,6f) { BIT(z80, 5,_Z80_A); } /* BIT 5,A */ + +OP(cb,70) { BIT(z80, 6,_Z80_B); } /* BIT 6,B */ +OP(cb,71) { BIT(z80, 6,_Z80_C); } /* BIT 6,C */ +OP(cb,72) { BIT(z80, 6,_Z80_D); } /* BIT 6,D */ +OP(cb,73) { BIT(z80, 6,_Z80_E); } /* BIT 6,E */ +OP(cb,74) { BIT(z80, 6,_Z80_H); } /* BIT 6,H */ +OP(cb,75) { BIT(z80, 6,_Z80_L); } /* BIT 6,L */ +OP(cb,76) { BIT(z80, 6,RM(_HL)); } /* BIT 6,(HL) */ +OP(cb,77) { BIT(z80, 6,_Z80_A); } /* BIT 6,A */ + +OP(cb,78) { BIT(z80, 7,_Z80_B); } /* BIT 7,B */ +OP(cb,79) { BIT(z80, 7,_Z80_C); } /* BIT 7,C */ +OP(cb,7a) { BIT(z80, 7,_Z80_D); } /* BIT 7,D */ +OP(cb,7b) { BIT(z80, 7,_Z80_E); } /* BIT 7,E */ +OP(cb,7c) { BIT(z80, 7,_Z80_H); } /* BIT 7,H */ +OP(cb,7d) { BIT(z80, 7,_Z80_L); } /* BIT 7,L */ +OP(cb,7e) { BIT(z80, 7,RM(_HL)); } /* BIT 7,(HL) */ +OP(cb,7f) { BIT(z80, 7,_Z80_A); } /* BIT 7,A */ + +OP(cb,80) { _Z80_B = RES(z80, 0,_Z80_B); } /* RES 0,B */ +OP(cb,81) { _Z80_C = RES(z80, 0,_Z80_C); } /* RES 0,C */ +OP(cb,82) { _Z80_D = RES(z80, 0,_Z80_D); } /* RES 0,D */ +OP(cb,83) { _Z80_E = RES(z80, 0,_Z80_E); } /* RES 0,E */ +OP(cb,84) { _Z80_H = RES(z80, 0,_Z80_H); } /* RES 0,H */ +OP(cb,85) { _Z80_L = RES(z80, 0,_Z80_L); } /* RES 0,L */ +OP(cb,86) { WM( _HL, RES(z80, 0,RM(_HL)) ); } /* RES 0,(HL) */ +OP(cb,87) { _Z80_A = RES(z80, 0,_Z80_A); } /* RES 0,A */ + +OP(cb,88) { _Z80_B = RES(z80, 1,_Z80_B); } /* RES 1,B */ +OP(cb,89) { _Z80_C = RES(z80, 1,_Z80_C); } /* RES 1,C */ +OP(cb,8a) { _Z80_D = RES(z80, 1,_Z80_D); } /* RES 1,D */ +OP(cb,8b) { _Z80_E = RES(z80, 1,_Z80_E); } /* RES 1,E */ +OP(cb,8c) { _Z80_H = RES(z80, 1,_Z80_H); } /* RES 1,H */ +OP(cb,8d) { _Z80_L = RES(z80, 1,_Z80_L); } /* RES 1,L */ +OP(cb,8e) { WM( _HL, RES(z80, 1,RM(_HL)) ); } /* RES 1,(HL) */ +OP(cb,8f) { _Z80_A = RES(z80, 1,_Z80_A); } /* RES 1,A */ + +OP(cb,90) { _Z80_B = RES(z80, 2,_Z80_B); } /* RES 2,B */ +OP(cb,91) { _Z80_C = RES(z80, 2,_Z80_C); } /* RES 2,C */ +OP(cb,92) { _Z80_D = RES(z80, 2,_Z80_D); } /* RES 2,D */ +OP(cb,93) { _Z80_E = RES(z80, 2,_Z80_E); } /* RES 2,E */ +OP(cb,94) { _Z80_H = RES(z80, 2,_Z80_H); } /* RES 2,H */ +OP(cb,95) { _Z80_L = RES(z80, 2,_Z80_L); } /* RES 2,L */ +OP(cb,96) { WM( _HL, RES(z80, 2,RM(_HL)) ); } /* RES 2,(HL) */ +OP(cb,97) { _Z80_A = RES(z80, 2,_Z80_A); } /* RES 2,A */ + +OP(cb,98) { _Z80_B = RES(z80, 3,_Z80_B); } /* RES 3,B */ +OP(cb,99) { _Z80_C = RES(z80, 3,_Z80_C); } /* RES 3,C */ +OP(cb,9a) { _Z80_D = RES(z80, 3,_Z80_D); } /* RES 3,D */ +OP(cb,9b) { _Z80_E = RES(z80, 3,_Z80_E); } /* RES 3,E */ +OP(cb,9c) { _Z80_H = RES(z80, 3,_Z80_H); } /* RES 3,H */ +OP(cb,9d) { _Z80_L = RES(z80, 3,_Z80_L); } /* RES 3,L */ +OP(cb,9e) { WM( _HL, RES(z80, 3,RM(_HL)) ); } /* RES 3,(HL) */ +OP(cb,9f) { _Z80_A = RES(z80, 3,_Z80_A); } /* RES 3,A */ + +OP(cb,a0) { _Z80_B = RES(z80, 4,_Z80_B); } /* RES 4,B */ +OP(cb,a1) { _Z80_C = RES(z80, 4,_Z80_C); } /* RES 4,C */ +OP(cb,a2) { _Z80_D = RES(z80, 4,_Z80_D); } /* RES 4,D */ +OP(cb,a3) { _Z80_E = RES(z80, 4,_Z80_E); } /* RES 4,E */ +OP(cb,a4) { _Z80_H = RES(z80, 4,_Z80_H); } /* RES 4,H */ +OP(cb,a5) { _Z80_L = RES(z80, 4,_Z80_L); } /* RES 4,L */ +OP(cb,a6) { WM( _HL, RES(z80, 4,RM(_HL)) ); } /* RES 4,(HL) */ +OP(cb,a7) { _Z80_A = RES(z80, 4,_Z80_A); } /* RES 4,A */ + +OP(cb,a8) { _Z80_B = RES(z80, 5,_Z80_B); } /* RES 5,B */ +OP(cb,a9) { _Z80_C = RES(z80, 5,_Z80_C); } /* RES 5,C */ +OP(cb,aa) { _Z80_D = RES(z80, 5,_Z80_D); } /* RES 5,D */ +OP(cb,ab) { _Z80_E = RES(z80, 5,_Z80_E); } /* RES 5,E */ +OP(cb,ac) { _Z80_H = RES(z80, 5,_Z80_H); } /* RES 5,H */ +OP(cb,ad) { _Z80_L = RES(z80, 5,_Z80_L); } /* RES 5,L */ +OP(cb,ae) { WM( _HL, RES(z80, 5,RM(_HL)) ); } /* RES 5,(HL) */ +OP(cb,af) { _Z80_A = RES(z80, 5,_Z80_A); } /* RES 5,A */ + +OP(cb,b0) { _Z80_B = RES(z80, 6,_Z80_B); } /* RES 6,B */ +OP(cb,b1) { _Z80_C = RES(z80, 6,_Z80_C); } /* RES 6,C */ +OP(cb,b2) { _Z80_D = RES(z80, 6,_Z80_D); } /* RES 6,D */ +OP(cb,b3) { _Z80_E = RES(z80, 6,_Z80_E); } /* RES 6,E */ +OP(cb,b4) { _Z80_H = RES(z80, 6,_Z80_H); } /* RES 6,H */ +OP(cb,b5) { _Z80_L = RES(z80, 6,_Z80_L); } /* RES 6,L */ +OP(cb,b6) { WM( _HL, RES(z80, 6,RM(_HL)) ); } /* RES 6,(HL) */ +OP(cb,b7) { _Z80_A = RES(z80, 6,_Z80_A); } /* RES 6,A */ + +OP(cb,b8) { _Z80_B = RES(z80, 7,_Z80_B); } /* RES 7,B */ +OP(cb,b9) { _Z80_C = RES(z80, 7,_Z80_C); } /* RES 7,C */ +OP(cb,ba) { _Z80_D = RES(z80, 7,_Z80_D); } /* RES 7,D */ +OP(cb,bb) { _Z80_E = RES(z80, 7,_Z80_E); } /* RES 7,E */ +OP(cb,bc) { _Z80_H = RES(z80, 7,_Z80_H); } /* RES 7,H */ +OP(cb,bd) { _Z80_L = RES(z80, 7,_Z80_L); } /* RES 7,L */ +OP(cb,be) { WM( _HL, RES(z80, 7,RM(_HL)) ); } /* RES 7,(HL) */ +OP(cb,bf) { _Z80_A = RES(z80, 7,_Z80_A); } /* RES 7,A */ + +OP(cb,c0) { _Z80_B = SET(z80, 0,_Z80_B); } /* SET 0,B */ +OP(cb,c1) { _Z80_C = SET(z80, 0,_Z80_C); } /* SET 0,C */ +OP(cb,c2) { _Z80_D = SET(z80, 0,_Z80_D); } /* SET 0,D */ +OP(cb,c3) { _Z80_E = SET(z80, 0,_Z80_E); } /* SET 0,E */ +OP(cb,c4) { _Z80_H = SET(z80, 0,_Z80_H); } /* SET 0,H */ +OP(cb,c5) { _Z80_L = SET(z80, 0,_Z80_L); } /* SET 0,L */ +OP(cb,c6) { WM( _HL, SET(z80, 0,RM(_HL)) ); } /* SET 0,(HL) */ +OP(cb,c7) { _Z80_A = SET(z80, 0,_Z80_A); } /* SET 0,A */ + +OP(cb,c8) { _Z80_B = SET(z80, 1,_Z80_B); } /* SET 1,B */ +OP(cb,c9) { _Z80_C = SET(z80, 1,_Z80_C); } /* SET 1,C */ +OP(cb,ca) { _Z80_D = SET(z80, 1,_Z80_D); } /* SET 1,D */ +OP(cb,cb) { _Z80_E = SET(z80, 1,_Z80_E); } /* SET 1,E */ +OP(cb,cc) { _Z80_H = SET(z80, 1,_Z80_H); } /* SET 1,H */ +OP(cb,cd) { _Z80_L = SET(z80, 1,_Z80_L); } /* SET 1,L */ +OP(cb,ce) { WM( _HL, SET(z80, 1,RM(_HL)) ); } /* SET 1,(HL) */ +OP(cb,cf) { _Z80_A = SET(z80, 1,_Z80_A); } /* SET 1,A */ + +OP(cb,d0) { _Z80_B = SET(z80, 2,_Z80_B); } /* SET 2,B */ +OP(cb,d1) { _Z80_C = SET(z80, 2,_Z80_C); } /* SET 2,C */ +OP(cb,d2) { _Z80_D = SET(z80, 2,_Z80_D); } /* SET 2,D */ +OP(cb,d3) { _Z80_E = SET(z80, 2,_Z80_E); } /* SET 2,E */ +OP(cb,d4) { _Z80_H = SET(z80, 2,_Z80_H); } /* SET 2,H */ +OP(cb,d5) { _Z80_L = SET(z80, 2,_Z80_L); } /* SET 2,L */ +OP(cb,d6) { WM( _HL, SET(z80, 2,RM(_HL)) ); }/* SET 2,(HL) */ +OP(cb,d7) { _Z80_A = SET(z80, 2,_Z80_A); } /* SET 2,A */ + +OP(cb,d8) { _Z80_B = SET(z80, 3,_Z80_B); } /* SET 3,B */ +OP(cb,d9) { _Z80_C = SET(z80, 3,_Z80_C); } /* SET 3,C */ +OP(cb,da) { _Z80_D = SET(z80, 3,_Z80_D); } /* SET 3,D */ +OP(cb,db) { _Z80_E = SET(z80, 3,_Z80_E); } /* SET 3,E */ +OP(cb,dc) { _Z80_H = SET(z80, 3,_Z80_H); } /* SET 3,H */ +OP(cb,dd) { _Z80_L = SET(z80, 3,_Z80_L); } /* SET 3,L */ +OP(cb,de) { WM( _HL, SET(z80, 3,RM(_HL)) ); } /* SET 3,(HL) */ +OP(cb,df) { _Z80_A = SET(z80, 3,_Z80_A); } /* SET 3,A */ + +OP(cb,e0) { _Z80_B = SET(z80, 4,_Z80_B); } /* SET 4,B */ +OP(cb,e1) { _Z80_C = SET(z80, 4,_Z80_C); } /* SET 4,C */ +OP(cb,e2) { _Z80_D = SET(z80, 4,_Z80_D); } /* SET 4,D */ +OP(cb,e3) { _Z80_E = SET(z80, 4,_Z80_E); } /* SET 4,E */ +OP(cb,e4) { _Z80_H = SET(z80, 4,_Z80_H); } /* SET 4,H */ +OP(cb,e5) { _Z80_L = SET(z80, 4,_Z80_L); } /* SET 4,L */ +OP(cb,e6) { WM( _HL, SET(z80, 4,RM(_HL)) ); } /* SET 4,(HL) */ +OP(cb,e7) { _Z80_A = SET(z80, 4,_Z80_A); } /* SET 4,A */ + +OP(cb,e8) { _Z80_B = SET(z80, 5,_Z80_B); } /* SET 5,B */ +OP(cb,e9) { _Z80_C = SET(z80, 5,_Z80_C); } /* SET 5,C */ +OP(cb,ea) { _Z80_D = SET(z80, 5,_Z80_D); } /* SET 5,D */ +OP(cb,eb) { _Z80_E = SET(z80, 5,_Z80_E); } /* SET 5,E */ +OP(cb,ec) { _Z80_H = SET(z80, 5,_Z80_H); } /* SET 5,H */ +OP(cb,ed) { _Z80_L = SET(z80, 5,_Z80_L); } /* SET 5,L */ +OP(cb,ee) { WM( _HL, SET(z80, 5,RM(_HL)) ); } /* SET 5,(HL) */ +OP(cb,ef) { _Z80_A = SET(z80, 5,_Z80_A); } /* SET 5,A */ + +OP(cb,f0) { _Z80_B = SET(z80, 6,_Z80_B); } /* SET 6,B */ +OP(cb,f1) { _Z80_C = SET(z80, 6,_Z80_C); } /* SET 6,C */ +OP(cb,f2) { _Z80_D = SET(z80, 6,_Z80_D); } /* SET 6,D */ +OP(cb,f3) { _Z80_E = SET(z80, 6,_Z80_E); } /* SET 6,E */ +OP(cb,f4) { _Z80_H = SET(z80, 6,_Z80_H); } /* SET 6,H */ +OP(cb,f5) { _Z80_L = SET(z80, 6,_Z80_L); } /* SET 6,L */ +OP(cb,f6) { WM( _HL, SET(z80, 6,RM(_HL)) ); } /* SET 6,(HL) */ +OP(cb,f7) { _Z80_A = SET(z80, 6,_Z80_A); } /* SET 6,A */ + +OP(cb,f8) { _Z80_B = SET(z80, 7,_Z80_B); } /* SET 7,B */ +OP(cb,f9) { _Z80_C = SET(z80, 7,_Z80_C); } /* SET 7,C */ +OP(cb,fa) { _Z80_D = SET(z80, 7,_Z80_D); } /* SET 7,D */ +OP(cb,fb) { _Z80_E = SET(z80, 7,_Z80_E); } /* SET 7,E */ +OP(cb,fc) { _Z80_H = SET(z80, 7,_Z80_H); } /* SET 7,H */ +OP(cb,fd) { _Z80_L = SET(z80, 7,_Z80_L); } /* SET 7,L */ +OP(cb,fe) { WM( _HL, SET(z80, 7,RM(_HL)) ); } /* SET 7,(HL) */ +OP(cb,ff) { _Z80_A = SET(z80, 7,_Z80_A); } /* SET 7,A */ + + +/********************************************************** +* opcodes with DD/FD CB prefix +* rotate, shift and bit operations with (IX+o) +**********************************************************/ +OP(xycb,00) { _Z80_B = RLC(z80, RM(z80->EA) ); WM( z80->EA,_Z80_B ); } /* RLC B=(XY+o) */ +OP(xycb,01) { _Z80_C = RLC(z80, RM(z80->EA) ); WM( z80->EA,_Z80_C ); } /* RLC C=(XY+o) */ +OP(xycb,02) { _Z80_D = RLC(z80, RM(z80->EA) ); WM( z80->EA,_Z80_D ); } /* RLC D=(XY+o) */ +OP(xycb,03) { _Z80_E = RLC(z80, RM(z80->EA) ); WM( z80->EA,_Z80_E ); } /* RLC E=(XY+o) */ +OP(xycb,04) { _Z80_H = RLC(z80, RM(z80->EA) ); WM( z80->EA,_Z80_H ); } /* RLC H=(XY+o) */ +OP(xycb,05) { _Z80_L = RLC(z80, RM(z80->EA) ); WM( z80->EA,_Z80_L ); } /* RLC L=(XY+o) */ +OP(xycb,06) { WM( z80->EA, RLC(z80, RM(z80->EA) ) ); } /* RLC (XY+o) */ +OP(xycb,07) { _Z80_A = RLC(z80, RM(z80->EA) ); WM( z80->EA,_Z80_A ); } /* RLC A=(XY+o) */ + +OP(xycb,08) { _Z80_B = RRC(z80, RM(z80->EA) ); WM( z80->EA,_Z80_B ); } /* RRC B=(XY+o) */ +OP(xycb,09) { _Z80_C = RRC(z80, RM(z80->EA) ); WM( z80->EA,_Z80_C ); } /* RRC C=(XY+o) */ +OP(xycb,0a) { _Z80_D = RRC(z80, RM(z80->EA) ); WM( z80->EA,_Z80_D ); } /* RRC D=(XY+o) */ +OP(xycb,0b) { _Z80_E = RRC(z80, RM(z80->EA) ); WM( z80->EA,_Z80_E ); } /* RRC E=(XY+o) */ +OP(xycb,0c) { _Z80_H = RRC(z80, RM(z80->EA) ); WM( z80->EA,_Z80_H ); } /* RRC H=(XY+o) */ +OP(xycb,0d) { _Z80_L = RRC(z80, RM(z80->EA) ); WM( z80->EA,_Z80_L ); } /* RRC L=(XY+o) */ +OP(xycb,0e) { WM( z80->EA,RRC(z80, RM(z80->EA) ) ); } /* RRC (XY+o) */ +OP(xycb,0f) { _Z80_A = RRC(z80, RM(z80->EA) ); WM( z80->EA,_Z80_A ); } /* RRC A=(XY+o) */ + +OP(xycb,10) { _Z80_B = RL(z80, RM(z80->EA) ); WM( z80->EA,_Z80_B ); } /* RL B=(XY+o) */ +OP(xycb,11) { _Z80_C = RL(z80, RM(z80->EA) ); WM( z80->EA,_Z80_C ); } /* RL C=(XY+o) */ +OP(xycb,12) { _Z80_D = RL(z80, RM(z80->EA) ); WM( z80->EA,_Z80_D ); } /* RL D=(XY+o) */ +OP(xycb,13) { _Z80_E = RL(z80, RM(z80->EA) ); WM( z80->EA,_Z80_E ); } /* RL E=(XY+o) */ +OP(xycb,14) { _Z80_H = RL(z80, RM(z80->EA) ); WM( z80->EA,_Z80_H ); } /* RL H=(XY+o) */ +OP(xycb,15) { _Z80_L = RL(z80, RM(z80->EA) ); WM( z80->EA,_Z80_L ); } /* RL L=(XY+o) */ +OP(xycb,16) { WM( z80->EA,RL(z80, RM(z80->EA) ) ); } /* RL (XY+o) */ +OP(xycb,17) { _Z80_A = RL(z80, RM(z80->EA) ); WM( z80->EA,_Z80_A ); } /* RL A=(XY+o) */ + +OP(xycb,18) { _Z80_B = RR(z80, RM(z80->EA) ); WM( z80->EA,_Z80_B ); } /* RR B=(XY+o) */ +OP(xycb,19) { _Z80_C = RR(z80, RM(z80->EA) ); WM( z80->EA,_Z80_C ); } /* RR C=(XY+o) */ +OP(xycb,1a) { _Z80_D = RR(z80, RM(z80->EA) ); WM( z80->EA,_Z80_D ); } /* RR D=(XY+o) */ +OP(xycb,1b) { _Z80_E = RR(z80, RM(z80->EA) ); WM( z80->EA,_Z80_E ); } /* RR E=(XY+o) */ +OP(xycb,1c) { _Z80_H = RR(z80, RM(z80->EA) ); WM( z80->EA,_Z80_H ); } /* RR H=(XY+o) */ +OP(xycb,1d) { _Z80_L = RR(z80, RM(z80->EA) ); WM( z80->EA,_Z80_L ); } /* RR L=(XY+o) */ +OP(xycb,1e) { WM( z80->EA,RR(z80, RM(z80->EA) ) ); } /* RR (XY+o) */ +OP(xycb,1f) { _Z80_A = RR(z80, RM(z80->EA) ); WM( z80->EA,_Z80_A ); } /* RR A=(XY+o) */ + +OP(xycb,20) { _Z80_B = SLA(z80, RM(z80->EA) ); WM( z80->EA,_Z80_B ); } /* SLA B=(XY+o) */ +OP(xycb,21) { _Z80_C = SLA(z80, RM(z80->EA) ); WM( z80->EA,_Z80_C ); } /* SLA C=(XY+o) */ +OP(xycb,22) { _Z80_D = SLA(z80, RM(z80->EA) ); WM( z80->EA,_Z80_D ); } /* SLA D=(XY+o) */ +OP(xycb,23) { _Z80_E = SLA(z80, RM(z80->EA) ); WM( z80->EA,_Z80_E ); } /* SLA E=(XY+o) */ +OP(xycb,24) { _Z80_H = SLA(z80, RM(z80->EA) ); WM( z80->EA,_Z80_H ); } /* SLA H=(XY+o) */ +OP(xycb,25) { _Z80_L = SLA(z80, RM(z80->EA) ); WM( z80->EA,_Z80_L ); } /* SLA L=(XY+o) */ +OP(xycb,26) { WM( z80->EA,SLA(z80, RM(z80->EA) ) ); } /* SLA (XY+o) */ +OP(xycb,27) { _Z80_A = SLA(z80, RM(z80->EA) ); WM( z80->EA,_Z80_A ); } /* SLA A=(XY+o) */ + +OP(xycb,28) { _Z80_B = SRA(z80, RM(z80->EA) ); WM( z80->EA,_Z80_B ); } /* SRA B=(XY+o) */ +OP(xycb,29) { _Z80_C = SRA(z80, RM(z80->EA) ); WM( z80->EA,_Z80_C ); } /* SRA C=(XY+o) */ +OP(xycb,2a) { _Z80_D = SRA(z80, RM(z80->EA) ); WM( z80->EA,_Z80_D ); } /* SRA D=(XY+o) */ +OP(xycb,2b) { _Z80_E = SRA(z80, RM(z80->EA) ); WM( z80->EA,_Z80_E ); } /* SRA E=(XY+o) */ +OP(xycb,2c) { _Z80_H = SRA(z80, RM(z80->EA) ); WM( z80->EA,_Z80_H ); } /* SRA H=(XY+o) */ +OP(xycb,2d) { _Z80_L = SRA(z80, RM(z80->EA) ); WM( z80->EA,_Z80_L ); } /* SRA L=(XY+o) */ +OP(xycb,2e) { WM( z80->EA,SRA(z80, RM(z80->EA) ) ); } /* SRA (XY+o) */ +OP(xycb,2f) { _Z80_A = SRA(z80, RM(z80->EA) ); WM( z80->EA,_Z80_A ); } /* SRA A=(XY+o) */ + +OP(xycb,30) { _Z80_B = SLL(z80, RM(z80->EA) ); WM( z80->EA,_Z80_B ); } /* SLL B=(XY+o) */ +OP(xycb,31) { _Z80_C = SLL(z80, RM(z80->EA) ); WM( z80->EA,_Z80_C ); } /* SLL C=(XY+o) */ +OP(xycb,32) { _Z80_D = SLL(z80, RM(z80->EA) ); WM( z80->EA,_Z80_D ); } /* SLL D=(XY+o) */ +OP(xycb,33) { _Z80_E = SLL(z80, RM(z80->EA) ); WM( z80->EA,_Z80_E ); } /* SLL E=(XY+o) */ +OP(xycb,34) { _Z80_H = SLL(z80, RM(z80->EA) ); WM( z80->EA,_Z80_H ); } /* SLL H=(XY+o) */ +OP(xycb,35) { _Z80_L = SLL(z80, RM(z80->EA) ); WM( z80->EA,_Z80_L ); } /* SLL L=(XY+o) */ +OP(xycb,36) { WM( z80->EA,SLL(z80, RM(z80->EA) ) ); } /* SLL (XY+o) */ +OP(xycb,37) { _Z80_A = SLL(z80, RM(z80->EA) ); WM( z80->EA,_Z80_A ); } /* SLL A=(XY+o) */ + +OP(xycb,38) { _Z80_B = SRL(z80, RM(z80->EA) ); WM( z80->EA,_Z80_B ); } /* SRL B=(XY+o) */ +OP(xycb,39) { _Z80_C = SRL(z80, RM(z80->EA) ); WM( z80->EA,_Z80_C ); } /* SRL C=(XY+o) */ +OP(xycb,3a) { _Z80_D = SRL(z80, RM(z80->EA) ); WM( z80->EA,_Z80_D ); } /* SRL D=(XY+o) */ +OP(xycb,3b) { _Z80_E = SRL(z80, RM(z80->EA) ); WM( z80->EA,_Z80_E ); } /* SRL E=(XY+o) */ +OP(xycb,3c) { _Z80_H = SRL(z80, RM(z80->EA) ); WM( z80->EA,_Z80_H ); } /* SRL H=(XY+o) */ +OP(xycb,3d) { _Z80_L = SRL(z80, RM(z80->EA) ); WM( z80->EA,_Z80_L ); } /* SRL L=(XY+o) */ +OP(xycb,3e) { WM( z80->EA,SRL(z80, RM(z80->EA) ) ); } /* SRL (XY+o) */ +OP(xycb,3f) { _Z80_A = SRL(z80, RM(z80->EA) ); WM( z80->EA,_Z80_A ); } /* SRL A=(XY+o) */ + +OP(xycb,40) { xycb_46(z80); } /* BIT 0,B=(XY+o) */ +OP(xycb,41) { xycb_46(z80); } /* BIT 0,C=(XY+o) */ +OP(xycb,42) { xycb_46(z80); } /* BIT 0,D=(XY+o) */ +OP(xycb,43) { xycb_46(z80); } /* BIT 0,E=(XY+o) */ +OP(xycb,44) { xycb_46(z80); } /* BIT 0,H=(XY+o) */ +OP(xycb,45) { xycb_46(z80); } /* BIT 0,L=(XY+o) */ +OP(xycb,46) { BIT_XY(z80,0,RM(z80->EA)); } /* BIT 0,(XY+o) */ +OP(xycb,47) { xycb_46(z80); } /* BIT 0,A=(XY+o) */ + +OP(xycb,48) { xycb_4e(z80); } /* BIT 1,B=(XY+o) */ +OP(xycb,49) { xycb_4e(z80); } /* BIT 1,C=(XY+o) */ +OP(xycb,4a) { xycb_4e(z80); } /* BIT 1,D=(XY+o) */ +OP(xycb,4b) { xycb_4e(z80); } /* BIT 1,E=(XY+o) */ +OP(xycb,4c) { xycb_4e(z80); } /* BIT 1,H=(XY+o) */ +OP(xycb,4d) { xycb_4e(z80); } /* BIT 1,L=(XY+o) */ +OP(xycb,4e) { BIT_XY(z80,1,RM(z80->EA)); } /* BIT 1,(XY+o) */ +OP(xycb,4f) { xycb_4e(z80); } /* BIT 1,A=(XY+o) */ + +OP(xycb,50) { xycb_56(z80); } /* BIT 2,B=(XY+o) */ +OP(xycb,51) { xycb_56(z80); } /* BIT 2,C=(XY+o) */ +OP(xycb,52) { xycb_56(z80); } /* BIT 2,D=(XY+o) */ +OP(xycb,53) { xycb_56(z80); } /* BIT 2,E=(XY+o) */ +OP(xycb,54) { xycb_56(z80); } /* BIT 2,H=(XY+o) */ +OP(xycb,55) { xycb_56(z80); } /* BIT 2,L=(XY+o) */ +OP(xycb,56) { BIT_XY(z80,2,RM(z80->EA)); } /* BIT 2,(XY+o) */ +OP(xycb,57) { xycb_56(z80); } /* BIT 2,A=(XY+o) */ + +OP(xycb,58) { xycb_5e(z80); } /* BIT 3,B=(XY+o) */ +OP(xycb,59) { xycb_5e(z80); } /* BIT 3,C=(XY+o) */ +OP(xycb,5a) { xycb_5e(z80); } /* BIT 3,D=(XY+o) */ +OP(xycb,5b) { xycb_5e(z80); } /* BIT 3,E=(XY+o) */ +OP(xycb,5c) { xycb_5e(z80); } /* BIT 3,H=(XY+o) */ +OP(xycb,5d) { xycb_5e(z80); } /* BIT 3,L=(XY+o) */ +OP(xycb,5e) { BIT_XY(z80,3,RM(z80->EA)); } /* BIT 3,(XY+o) */ +OP(xycb,5f) { xycb_5e(z80); } /* BIT 3,A=(XY+o) */ + +OP(xycb,60) { xycb_66(z80); } /* BIT 4,B=(XY+o) */ +OP(xycb,61) { xycb_66(z80); } /* BIT 4,C=(XY+o) */ +OP(xycb,62) { xycb_66(z80); } /* BIT 4,D=(XY+o) */ +OP(xycb,63) { xycb_66(z80); } /* BIT 4,E=(XY+o) */ +OP(xycb,64) { xycb_66(z80); } /* BIT 4,H=(XY+o) */ +OP(xycb,65) { xycb_66(z80); } /* BIT 4,L=(XY+o) */ +OP(xycb,66) { BIT_XY(z80,4,RM(z80->EA)); } /* BIT 4,(XY+o) */ +OP(xycb,67) { xycb_66(z80); } /* BIT 4,A=(XY+o) */ + +OP(xycb,68) { xycb_6e(z80); } /* BIT 5,B=(XY+o) */ +OP(xycb,69) { xycb_6e(z80); } /* BIT 5,C=(XY+o) */ +OP(xycb,6a) { xycb_6e(z80); } /* BIT 5,D=(XY+o) */ +OP(xycb,6b) { xycb_6e(z80); } /* BIT 5,E=(XY+o) */ +OP(xycb,6c) { xycb_6e(z80); } /* BIT 5,H=(XY+o) */ +OP(xycb,6d) { xycb_6e(z80); } /* BIT 5,L=(XY+o) */ +OP(xycb,6e) { BIT_XY(z80,5,RM(z80->EA)); } /* BIT 5,(XY+o) */ +OP(xycb,6f) { xycb_6e(z80); } /* BIT 5,A=(XY+o) */ + +OP(xycb,70) { xycb_76(z80); } /* BIT 6,B=(XY+o) */ +OP(xycb,71) { xycb_76(z80); } /* BIT 6,C=(XY+o) */ +OP(xycb,72) { xycb_76(z80); } /* BIT 6,D=(XY+o) */ +OP(xycb,73) { xycb_76(z80); } /* BIT 6,E=(XY+o) */ +OP(xycb,74) { xycb_76(z80); } /* BIT 6,H=(XY+o) */ +OP(xycb,75) { xycb_76(z80); } /* BIT 6,L=(XY+o) */ +OP(xycb,76) { BIT_XY(z80,6,RM(z80->EA)); } /* BIT 6,(XY+o) */ +OP(xycb,77) { xycb_76(z80); } /* BIT 6,A=(XY+o) */ + +OP(xycb,78) { xycb_7e(z80); } /* BIT 7,B=(XY+o) */ +OP(xycb,79) { xycb_7e(z80); } /* BIT 7,C=(XY+o) */ +OP(xycb,7a) { xycb_7e(z80); } /* BIT 7,D=(XY+o) */ +OP(xycb,7b) { xycb_7e(z80); } /* BIT 7,E=(XY+o) */ +OP(xycb,7c) { xycb_7e(z80); } /* BIT 7,H=(XY+o) */ +OP(xycb,7d) { xycb_7e(z80); } /* BIT 7,L=(XY+o) */ +OP(xycb,7e) { BIT_XY(z80,7,RM(z80->EA)); } /* BIT 7,(XY+o) */ +OP(xycb,7f) { xycb_7e(z80); } /* BIT 7,A=(XY+o) */ + +OP(xycb,80) { _Z80_B = RES(z80, 0, RM(z80->EA) ); WM( z80->EA,_Z80_B ); } /* RES 0,B=(XY+o) */ +OP(xycb,81) { _Z80_C = RES(z80, 0, RM(z80->EA) ); WM( z80->EA,_Z80_C ); } /* RES 0,C=(XY+o) */ +OP(xycb,82) { _Z80_D = RES(z80, 0, RM(z80->EA) ); WM( z80->EA,_Z80_D ); } /* RES 0,D=(XY+o) */ +OP(xycb,83) { _Z80_E = RES(z80, 0, RM(z80->EA) ); WM( z80->EA,_Z80_E ); } /* RES 0,E=(XY+o) */ +OP(xycb,84) { _Z80_H = RES(z80, 0, RM(z80->EA) ); WM( z80->EA,_Z80_H ); } /* RES 0,H=(XY+o) */ +OP(xycb,85) { _Z80_L = RES(z80, 0, RM(z80->EA) ); WM( z80->EA,_Z80_L ); } /* RES 0,L=(XY+o) */ +OP(xycb,86) { WM( z80->EA, RES(z80, 0,RM(z80->EA)) ); } /* RES 0,(XY+o) */ +OP(xycb,87) { _Z80_A = RES(z80, 0, RM(z80->EA) ); WM( z80->EA,_Z80_A ); } /* RES 0,A=(XY+o) */ + +OP(xycb,88) { _Z80_B = RES(z80, 1, RM(z80->EA) ); WM( z80->EA,_Z80_B ); } /* RES 1,B=(XY+o) */ +OP(xycb,89) { _Z80_C = RES(z80, 1, RM(z80->EA) ); WM( z80->EA,_Z80_C ); } /* RES 1,C=(XY+o) */ +OP(xycb,8a) { _Z80_D = RES(z80, 1, RM(z80->EA) ); WM( z80->EA,_Z80_D ); } /* RES 1,D=(XY+o) */ +OP(xycb,8b) { _Z80_E = RES(z80, 1, RM(z80->EA) ); WM( z80->EA,_Z80_E ); } /* RES 1,E=(XY+o) */ +OP(xycb,8c) { _Z80_H = RES(z80, 1, RM(z80->EA) ); WM( z80->EA,_Z80_H ); } /* RES 1,H=(XY+o) */ +OP(xycb,8d) { _Z80_L = RES(z80, 1, RM(z80->EA) ); WM( z80->EA,_Z80_L ); } /* RES 1,L=(XY+o) */ +OP(xycb,8e) { WM( z80->EA, RES(z80, 1,RM(z80->EA)) ); } /* RES 1,(XY+o) */ +OP(xycb,8f) { _Z80_A = RES(z80, 1, RM(z80->EA) ); WM( z80->EA,_Z80_A ); } /* RES 1,A=(XY+o) */ + +OP(xycb,90) { _Z80_B = RES(z80, 2, RM(z80->EA) ); WM( z80->EA,_Z80_B ); } /* RES 2,B=(XY+o) */ +OP(xycb,91) { _Z80_C = RES(z80, 2, RM(z80->EA) ); WM( z80->EA,_Z80_C ); } /* RES 2,C=(XY+o) */ +OP(xycb,92) { _Z80_D = RES(z80, 2, RM(z80->EA) ); WM( z80->EA,_Z80_D ); } /* RES 2,D=(XY+o) */ +OP(xycb,93) { _Z80_E = RES(z80, 2, RM(z80->EA) ); WM( z80->EA,_Z80_E ); } /* RES 2,E=(XY+o) */ +OP(xycb,94) { _Z80_H = RES(z80, 2, RM(z80->EA) ); WM( z80->EA,_Z80_H ); } /* RES 2,H=(XY+o) */ +OP(xycb,95) { _Z80_L = RES(z80, 2, RM(z80->EA) ); WM( z80->EA,_Z80_L ); } /* RES 2,L=(XY+o) */ +OP(xycb,96) { WM( z80->EA, RES(z80, 2,RM(z80->EA)) ); } /* RES 2,(XY+o) */ +OP(xycb,97) { _Z80_A = RES(z80, 2, RM(z80->EA) ); WM( z80->EA,_Z80_A ); } /* RES 2,A=(XY+o) */ + +OP(xycb,98) { _Z80_B = RES(z80, 3, RM(z80->EA) ); WM( z80->EA,_Z80_B ); } /* RES 3,B=(XY+o) */ +OP(xycb,99) { _Z80_C = RES(z80, 3, RM(z80->EA) ); WM( z80->EA,_Z80_C ); } /* RES 3,C=(XY+o) */ +OP(xycb,9a) { _Z80_D = RES(z80, 3, RM(z80->EA) ); WM( z80->EA,_Z80_D ); } /* RES 3,D=(XY+o) */ +OP(xycb,9b) { _Z80_E = RES(z80, 3, RM(z80->EA) ); WM( z80->EA,_Z80_E ); } /* RES 3,E=(XY+o) */ +OP(xycb,9c) { _Z80_H = RES(z80, 3, RM(z80->EA) ); WM( z80->EA,_Z80_H ); } /* RES 3,H=(XY+o) */ +OP(xycb,9d) { _Z80_L = RES(z80, 3, RM(z80->EA) ); WM( z80->EA,_Z80_L ); } /* RES 3,L=(XY+o) */ +OP(xycb,9e) { WM( z80->EA, RES(z80, 3,RM(z80->EA)) ); } /* RES 3,(XY+o) */ +OP(xycb,9f) { _Z80_A = RES(z80, 3, RM(z80->EA) ); WM( z80->EA,_Z80_A ); } /* RES 3,A=(XY+o) */ + +OP(xycb,a0) { _Z80_B = RES(z80, 4, RM(z80->EA) ); WM( z80->EA,_Z80_B ); } /* RES 4,B=(XY+o) */ +OP(xycb,a1) { _Z80_C = RES(z80, 4, RM(z80->EA) ); WM( z80->EA,_Z80_C ); } /* RES 4,C=(XY+o) */ +OP(xycb,a2) { _Z80_D = RES(z80, 4, RM(z80->EA) ); WM( z80->EA,_Z80_D ); } /* RES 4,D=(XY+o) */ +OP(xycb,a3) { _Z80_E = RES(z80, 4, RM(z80->EA) ); WM( z80->EA,_Z80_E ); } /* RES 4,E=(XY+o) */ +OP(xycb,a4) { _Z80_H = RES(z80, 4, RM(z80->EA) ); WM( z80->EA,_Z80_H ); } /* RES 4,H=(XY+o) */ +OP(xycb,a5) { _Z80_L = RES(z80, 4, RM(z80->EA) ); WM( z80->EA,_Z80_L ); } /* RES 4,L=(XY+o) */ +OP(xycb,a6) { WM( z80->EA, RES(z80, 4,RM(z80->EA)) ); } /* RES 4,(XY+o) */ +OP(xycb,a7) { _Z80_A = RES(z80, 4, RM(z80->EA) ); WM( z80->EA,_Z80_A ); } /* RES 4,A=(XY+o) */ + +OP(xycb,a8) { _Z80_B = RES(z80, 5, RM(z80->EA) ); WM( z80->EA,_Z80_B ); } /* RES 5,B=(XY+o) */ +OP(xycb,a9) { _Z80_C = RES(z80, 5, RM(z80->EA) ); WM( z80->EA,_Z80_C ); } /* RES 5,C=(XY+o) */ +OP(xycb,aa) { _Z80_D = RES(z80, 5, RM(z80->EA) ); WM( z80->EA,_Z80_D ); } /* RES 5,D=(XY+o) */ +OP(xycb,ab) { _Z80_E = RES(z80, 5, RM(z80->EA) ); WM( z80->EA,_Z80_E ); } /* RES 5,E=(XY+o) */ +OP(xycb,ac) { _Z80_H = RES(z80, 5, RM(z80->EA) ); WM( z80->EA,_Z80_H ); } /* RES 5,H=(XY+o) */ +OP(xycb,ad) { _Z80_L = RES(z80, 5, RM(z80->EA) ); WM( z80->EA,_Z80_L ); } /* RES 5,L=(XY+o) */ +OP(xycb,ae) { WM( z80->EA, RES(z80, 5,RM(z80->EA)) ); } /* RES 5,(XY+o) */ +OP(xycb,af) { _Z80_A = RES(z80, 5, RM(z80->EA) ); WM( z80->EA,_Z80_A ); } /* RES 5,A=(XY+o) */ + +OP(xycb,b0) { _Z80_B = RES(z80, 6, RM(z80->EA) ); WM( z80->EA,_Z80_B ); } /* RES 6,B=(XY+o) */ +OP(xycb,b1) { _Z80_C = RES(z80, 6, RM(z80->EA) ); WM( z80->EA,_Z80_C ); } /* RES 6,C=(XY+o) */ +OP(xycb,b2) { _Z80_D = RES(z80, 6, RM(z80->EA) ); WM( z80->EA,_Z80_D ); } /* RES 6,D=(XY+o) */ +OP(xycb,b3) { _Z80_E = RES(z80, 6, RM(z80->EA) ); WM( z80->EA,_Z80_E ); } /* RES 6,E=(XY+o) */ +OP(xycb,b4) { _Z80_H = RES(z80, 6, RM(z80->EA) ); WM( z80->EA,_Z80_H ); } /* RES 6,H=(XY+o) */ +OP(xycb,b5) { _Z80_L = RES(z80, 6, RM(z80->EA) ); WM( z80->EA,_Z80_L ); } /* RES 6,L=(XY+o) */ +OP(xycb,b6) { WM( z80->EA, RES(z80, 6,RM(z80->EA)) ); } /* RES 6,(XY+o) */ +OP(xycb,b7) { _Z80_A = RES(z80, 6, RM(z80->EA) ); WM( z80->EA,_Z80_A ); } /* RES 6,A=(XY+o) */ + +OP(xycb,b8) { _Z80_B = RES(z80, 7, RM(z80->EA) ); WM( z80->EA,_Z80_B ); } /* RES 7,B=(XY+o) */ +OP(xycb,b9) { _Z80_C = RES(z80, 7, RM(z80->EA) ); WM( z80->EA,_Z80_C ); } /* RES 7,C=(XY+o) */ +OP(xycb,ba) { _Z80_D = RES(z80, 7, RM(z80->EA) ); WM( z80->EA,_Z80_D ); } /* RES 7,D=(XY+o) */ +OP(xycb,bb) { _Z80_E = RES(z80, 7, RM(z80->EA) ); WM( z80->EA,_Z80_E ); } /* RES 7,E=(XY+o) */ +OP(xycb,bc) { _Z80_H = RES(z80, 7, RM(z80->EA) ); WM( z80->EA,_Z80_H ); } /* RES 7,H=(XY+o) */ +OP(xycb,bd) { _Z80_L = RES(z80, 7, RM(z80->EA) ); WM( z80->EA,_Z80_L ); } /* RES 7,L=(XY+o) */ +OP(xycb,be) { WM( z80->EA, RES(z80, 7,RM(z80->EA)) ); } /* RES 7,(XY+o) */ +OP(xycb,bf) { _Z80_A = RES(z80, 7, RM(z80->EA) ); WM( z80->EA,_Z80_A ); } /* RES 7,A=(XY+o) */ + +OP(xycb,c0) { _Z80_B = SET(z80, 0, RM(z80->EA) ); WM( z80->EA,_Z80_B ); } /* SET 0,B=(XY+o) */ +OP(xycb,c1) { _Z80_C = SET(z80, 0, RM(z80->EA) ); WM( z80->EA,_Z80_C ); } /* SET 0,C=(XY+o) */ +OP(xycb,c2) { _Z80_D = SET(z80, 0, RM(z80->EA) ); WM( z80->EA,_Z80_D ); } /* SET 0,D=(XY+o) */ +OP(xycb,c3) { _Z80_E = SET(z80, 0, RM(z80->EA) ); WM( z80->EA,_Z80_E ); } /* SET 0,E=(XY+o) */ +OP(xycb,c4) { _Z80_H = SET(z80, 0, RM(z80->EA) ); WM( z80->EA,_Z80_H ); } /* SET 0,H=(XY+o) */ +OP(xycb,c5) { _Z80_L = SET(z80, 0, RM(z80->EA) ); WM( z80->EA,_Z80_L ); } /* SET 0,L=(XY+o) */ +OP(xycb,c6) { WM( z80->EA, SET(z80, 0,RM(z80->EA)) ); } /* SET 0,(XY+o) */ +OP(xycb,c7) { _Z80_A = SET(z80, 0, RM(z80->EA) ); WM( z80->EA,_Z80_A ); } /* SET 0,A=(XY+o) */ + +OP(xycb,c8) { _Z80_B = SET(z80, 1, RM(z80->EA) ); WM( z80->EA,_Z80_B ); } /* SET 1,B=(XY+o) */ +OP(xycb,c9) { _Z80_C = SET(z80, 1, RM(z80->EA) ); WM( z80->EA,_Z80_C ); } /* SET 1,C=(XY+o) */ +OP(xycb,ca) { _Z80_D = SET(z80, 1, RM(z80->EA) ); WM( z80->EA,_Z80_D ); } /* SET 1,D=(XY+o) */ +OP(xycb,cb) { _Z80_E = SET(z80, 1, RM(z80->EA) ); WM( z80->EA,_Z80_E ); } /* SET 1,E=(XY+o) */ +OP(xycb,cc) { _Z80_H = SET(z80, 1, RM(z80->EA) ); WM( z80->EA,_Z80_H ); } /* SET 1,H=(XY+o) */ +OP(xycb,cd) { _Z80_L = SET(z80, 1, RM(z80->EA) ); WM( z80->EA,_Z80_L ); } /* SET 1,L=(XY+o) */ +OP(xycb,ce) { WM( z80->EA, SET(z80, 1,RM(z80->EA)) ); } /* SET 1,(XY+o) */ +OP(xycb,cf) { _Z80_A = SET(z80, 1, RM(z80->EA) ); WM( z80->EA,_Z80_A ); } /* SET 1,A=(XY+o) */ + +OP(xycb,d0) { _Z80_B = SET(z80, 2, RM(z80->EA) ); WM( z80->EA,_Z80_B ); } /* SET 2,B=(XY+o) */ +OP(xycb,d1) { _Z80_C = SET(z80, 2, RM(z80->EA) ); WM( z80->EA,_Z80_C ); } /* SET 2,C=(XY+o) */ +OP(xycb,d2) { _Z80_D = SET(z80, 2, RM(z80->EA) ); WM( z80->EA,_Z80_D ); } /* SET 2,D=(XY+o) */ +OP(xycb,d3) { _Z80_E = SET(z80, 2, RM(z80->EA) ); WM( z80->EA,_Z80_E ); } /* SET 2,E=(XY+o) */ +OP(xycb,d4) { _Z80_H = SET(z80, 2, RM(z80->EA) ); WM( z80->EA,_Z80_H ); } /* SET 2,H=(XY+o) */ +OP(xycb,d5) { _Z80_L = SET(z80, 2, RM(z80->EA) ); WM( z80->EA,_Z80_L ); } /* SET 2,L=(XY+o) */ +OP(xycb,d6) { WM( z80->EA, SET(z80, 2,RM(z80->EA)) ); } /* SET 2,(XY+o) */ +OP(xycb,d7) { _Z80_A = SET(z80, 2, RM(z80->EA) ); WM( z80->EA,_Z80_A ); } /* SET 2,A=(XY+o) */ + +OP(xycb,d8) { _Z80_B = SET(z80, 3, RM(z80->EA) ); WM( z80->EA,_Z80_B ); } /* SET 3,B=(XY+o) */ +OP(xycb,d9) { _Z80_C = SET(z80, 3, RM(z80->EA) ); WM( z80->EA,_Z80_C ); } /* SET 3,C=(XY+o) */ +OP(xycb,da) { _Z80_D = SET(z80, 3, RM(z80->EA) ); WM( z80->EA,_Z80_D ); } /* SET 3,D=(XY+o) */ +OP(xycb,db) { _Z80_E = SET(z80, 3, RM(z80->EA) ); WM( z80->EA,_Z80_E ); } /* SET 3,E=(XY+o) */ +OP(xycb,dc) { _Z80_H = SET(z80, 3, RM(z80->EA) ); WM( z80->EA,_Z80_H ); } /* SET 3,H=(XY+o) */ +OP(xycb,dd) { _Z80_L = SET(z80, 3, RM(z80->EA) ); WM( z80->EA,_Z80_L ); } /* SET 3,L=(XY+o) */ +OP(xycb,de) { WM( z80->EA, SET(z80, 3,RM(z80->EA)) ); } /* SET 3,(XY+o) */ +OP(xycb,df) { _Z80_A = SET(z80, 3, RM(z80->EA) ); WM( z80->EA,_Z80_A ); } /* SET 3,A=(XY+o) */ + +OP(xycb,e0) { _Z80_B = SET(z80, 4, RM(z80->EA) ); WM( z80->EA,_Z80_B ); } /* SET 4,B=(XY+o) */ +OP(xycb,e1) { _Z80_C = SET(z80, 4, RM(z80->EA) ); WM( z80->EA,_Z80_C ); } /* SET 4,C=(XY+o) */ +OP(xycb,e2) { _Z80_D = SET(z80, 4, RM(z80->EA) ); WM( z80->EA,_Z80_D ); } /* SET 4,D=(XY+o) */ +OP(xycb,e3) { _Z80_E = SET(z80, 4, RM(z80->EA) ); WM( z80->EA,_Z80_E ); } /* SET 4,E=(XY+o) */ +OP(xycb,e4) { _Z80_H = SET(z80, 4, RM(z80->EA) ); WM( z80->EA,_Z80_H ); } /* SET 4,H=(XY+o) */ +OP(xycb,e5) { _Z80_L = SET(z80, 4, RM(z80->EA) ); WM( z80->EA,_Z80_L ); } /* SET 4,L=(XY+o) */ +OP(xycb,e6) { WM( z80->EA, SET(z80, 4,RM(z80->EA)) ); } /* SET 4,(XY+o) */ +OP(xycb,e7) { _Z80_A = SET(z80, 4, RM(z80->EA) ); WM( z80->EA,_Z80_A ); } /* SET 4,A=(XY+o) */ + +OP(xycb,e8) { _Z80_B = SET(z80, 5, RM(z80->EA) ); WM( z80->EA,_Z80_B ); } /* SET 5,B=(XY+o) */ +OP(xycb,e9) { _Z80_C = SET(z80, 5, RM(z80->EA) ); WM( z80->EA,_Z80_C ); } /* SET 5,C=(XY+o) */ +OP(xycb,ea) { _Z80_D = SET(z80, 5, RM(z80->EA) ); WM( z80->EA,_Z80_D ); } /* SET 5,D=(XY+o) */ +OP(xycb,eb) { _Z80_E = SET(z80, 5, RM(z80->EA) ); WM( z80->EA,_Z80_E ); } /* SET 5,E=(XY+o) */ +OP(xycb,ec) { _Z80_H = SET(z80, 5, RM(z80->EA) ); WM( z80->EA,_Z80_H ); } /* SET 5,H=(XY+o) */ +OP(xycb,ed) { _Z80_L = SET(z80, 5, RM(z80->EA) ); WM( z80->EA,_Z80_L ); } /* SET 5,L=(XY+o) */ +OP(xycb,ee) { WM( z80->EA, SET(z80, 5,RM(z80->EA)) ); } /* SET 5,(XY+o) */ +OP(xycb,ef) { _Z80_A = SET(z80, 5, RM(z80->EA) ); WM( z80->EA,_Z80_A ); } /* SET 5,A=(XY+o) */ + +OP(xycb,f0) { _Z80_B = SET(z80, 6, RM(z80->EA) ); WM( z80->EA,_Z80_B ); } /* SET 6,B=(XY+o) */ +OP(xycb,f1) { _Z80_C = SET(z80, 6, RM(z80->EA) ); WM( z80->EA,_Z80_C ); } /* SET 6,C=(XY+o) */ +OP(xycb,f2) { _Z80_D = SET(z80, 6, RM(z80->EA) ); WM( z80->EA,_Z80_D ); } /* SET 6,D=(XY+o) */ +OP(xycb,f3) { _Z80_E = SET(z80, 6, RM(z80->EA) ); WM( z80->EA,_Z80_E ); } /* SET 6,E=(XY+o) */ +OP(xycb,f4) { _Z80_H = SET(z80, 6, RM(z80->EA) ); WM( z80->EA,_Z80_H ); } /* SET 6,H=(XY+o) */ +OP(xycb,f5) { _Z80_L = SET(z80, 6, RM(z80->EA) ); WM( z80->EA,_Z80_L ); } /* SET 6,L=(XY+o) */ +OP(xycb,f6) { WM( z80->EA, SET(z80, 6,RM(z80->EA)) ); } /* SET 6,(XY+o) */ +OP(xycb,f7) { _Z80_A = SET(z80, 6, RM(z80->EA) ); WM( z80->EA,_Z80_A ); } /* SET 6,A=(XY+o) */ + +OP(xycb,f8) { _Z80_B = SET(z80, 7, RM(z80->EA) ); WM( z80->EA,_Z80_B ); } /* SET 7,B=(XY+o) */ +OP(xycb,f9) { _Z80_C = SET(z80, 7, RM(z80->EA) ); WM( z80->EA,_Z80_C ); } /* SET 7,C=(XY+o) */ +OP(xycb,fa) { _Z80_D = SET(z80, 7, RM(z80->EA) ); WM( z80->EA,_Z80_D ); } /* SET 7,D=(XY+o) */ +OP(xycb,fb) { _Z80_E = SET(z80, 7, RM(z80->EA) ); WM( z80->EA,_Z80_E ); } /* SET 7,E=(XY+o) */ +OP(xycb,fc) { _Z80_H = SET(z80, 7, RM(z80->EA) ); WM( z80->EA,_Z80_H ); } /* SET 7,H=(XY+o) */ +OP(xycb,fd) { _Z80_L = SET(z80, 7, RM(z80->EA) ); WM( z80->EA,_Z80_L ); } /* SET 7,L=(XY+o) */ +OP(xycb,fe) { WM( z80->EA, SET(z80, 7,RM(z80->EA)) ); } /* SET 7,(XY+o) */ +OP(xycb,ff) { _Z80_A = SET(z80, 7, RM(z80->EA) ); WM( z80->EA,_Z80_A ); } /* SET 7,A=(XY+o) */ + +OP(illegal,1) { + logerror("Z80 #%d ill. opcode $%02x $%02x\n", + cpu_getactivecpu(), cpu_readop(z80->userdata,(_PCD-1)&0xffff), cpu_readop(z80->userdata,_PCD)); +} + +/********************************************************** + * IX register related opcodes (DD prefix) + **********************************************************/ +OP(dd,00) { illegal_1(z80); op_00(z80); } /* DB DD */ +OP(dd,01) { illegal_1(z80); op_01(z80); } /* DB DD */ +OP(dd,02) { illegal_1(z80); op_02(z80); } /* DB DD */ +OP(dd,03) { illegal_1(z80); op_03(z80); } /* DB DD */ +OP(dd,04) { illegal_1(z80); op_04(z80); } /* DB DD */ +OP(dd,05) { illegal_1(z80); op_05(z80); } /* DB DD */ +OP(dd,06) { illegal_1(z80); op_06(z80); } /* DB DD */ +OP(dd,07) { illegal_1(z80); op_07(z80); } /* DB DD */ + +OP(dd,08) { illegal_1(z80); op_08(z80); } /* DB DD */ +OP(dd,09) { _Z80_R++; ADD16(z80,IX,BC); } /* ADD IX,BC */ +OP(dd,0a) { illegal_1(z80); op_0a(z80); } /* DB DD */ +OP(dd,0b) { illegal_1(z80); op_0b(z80); } /* DB DD */ +OP(dd,0c) { illegal_1(z80); op_0c(z80); } /* DB DD */ +OP(dd,0d) { illegal_1(z80); op_0d(z80); } /* DB DD */ +OP(dd,0e) { illegal_1(z80); op_0e(z80); } /* DB DD */ +OP(dd,0f) { illegal_1(z80); op_0f(z80); } /* DB DD */ + +OP(dd,10) { illegal_1(z80); op_10(z80); } /* DB DD */ +OP(dd,11) { illegal_1(z80); op_11(z80); } /* DB DD */ +OP(dd,12) { illegal_1(z80); op_12(z80); } /* DB DD */ +OP(dd,13) { illegal_1(z80); op_13(z80); } /* DB DD */ +OP(dd,14) { illegal_1(z80); op_14(z80); } /* DB DD */ +OP(dd,15) { illegal_1(z80); op_15(z80); } /* DB DD */ +OP(dd,16) { illegal_1(z80); op_16(z80); } /* DB DD */ +OP(dd,17) { illegal_1(z80); op_17(z80); } /* DB DD */ + +OP(dd,18) { illegal_1(z80); op_18(z80); } /* DB DD */ +OP(dd,19) { _Z80_R++; ADD16(z80,IX,DE); } /* ADD IX,DE */ +OP(dd,1a) { illegal_1(z80); op_1a(z80); } /* DB DD */ +OP(dd,1b) { illegal_1(z80); op_1b(z80); } /* DB DD */ +OP(dd,1c) { illegal_1(z80); op_1c(z80); } /* DB DD */ +OP(dd,1d) { illegal_1(z80); op_1d(z80); } /* DB DD */ +OP(dd,1e) { illegal_1(z80); op_1e(z80); } /* DB DD */ +OP(dd,1f) { illegal_1(z80); op_1f(z80); } /* DB DD */ + +OP(dd,20) { illegal_1(z80); op_20(z80); } /* DB DD */ +OP(dd,21) { _Z80_R++; _IX = ARG16(z80); } /* LD IX,w */ +OP(dd,22) { _Z80_R++; z80->EA = ARG16(z80); WM16(z80, z80->EA, &z80->Z80.IX ); } /* LD (w),IX */ +OP(dd,23) { _Z80_R++; _IX++; } /* INC IX */ +OP(dd,24) { _Z80_R++; _HX = INC(z80,_HX); } /* INC HX */ +OP(dd,25) { _Z80_R++; _HX = DEC(z80,_HX); } /* DEC HX */ +OP(dd,26) { _Z80_R++; _HX = ARG(z80); } /* LD HX,n */ +OP(dd,27) { illegal_1(z80); op_27(z80); } /* DB DD */ + +OP(dd,28) { illegal_1(z80); op_28(z80); } /* DB DD */ +OP(dd,29) { _Z80_R++; ADD16(z80,IX,IX); } /* ADD IX,IX */ +OP(dd,2a) { _Z80_R++; z80->EA = ARG16(z80); RM16(z80, z80->EA, &z80->Z80.IX ); } /* LD IX,(w) */ +OP(dd,2b) { _Z80_R++; _IX--; } /* DEC IX */ +OP(dd,2c) { _Z80_R++; _LX = INC(z80,_LX); } /* INC LX */ +OP(dd,2d) { _Z80_R++; _LX = DEC(z80,_LX); } /* DEC LX */ +OP(dd,2e) { _Z80_R++; _LX = ARG(z80); } /* LD LX,n */ +OP(dd,2f) { illegal_1(z80); op_2f(z80); } /* DB DD */ + +OP(dd,30) { illegal_1(z80); op_30(z80); } /* DB DD */ +OP(dd,31) { illegal_1(z80); op_31(z80); } /* DB DD */ +OP(dd,32) { illegal_1(z80); op_32(z80); } /* DB DD */ +OP(dd,33) { illegal_1(z80); op_33(z80); } /* DB DD */ +OP(dd,34) { _Z80_R++; EAX; WM( z80->EA, INC(z80,RM(z80->EA)) ); } /* INC (IX+o) */ +OP(dd,35) { _Z80_R++; EAX; WM( z80->EA, DEC(z80,RM(z80->EA)) ); } /* DEC (IX+o) */ +OP(dd,36) { _Z80_R++; EAX; WM( z80->EA, ARG(z80) ); } /* LD (IX+o),n */ +OP(dd,37) { illegal_1(z80); op_37(z80); } /* DB DD */ + +OP(dd,38) { illegal_1(z80); op_38(z80); } /* DB DD */ +OP(dd,39) { _Z80_R++; ADD16(z80,IX,SP); } /* ADD IX,SP */ +OP(dd,3a) { illegal_1(z80); op_3a(z80); } /* DB DD */ +OP(dd,3b) { illegal_1(z80); op_3b(z80); } /* DB DD */ +OP(dd,3c) { illegal_1(z80); op_3c(z80); } /* DB DD */ +OP(dd,3d) { illegal_1(z80); op_3d(z80); } /* DB DD */ +OP(dd,3e) { illegal_1(z80); op_3e(z80); } /* DB DD */ +OP(dd,3f) { illegal_1(z80); op_3f(z80); } /* DB DD */ + +OP(dd,40) { illegal_1(z80); op_40(z80); } /* DB DD */ +OP(dd,41) { illegal_1(z80); op_41(z80); } /* DB DD */ +OP(dd,42) { illegal_1(z80); op_42(z80); } /* DB DD */ +OP(dd,43) { illegal_1(z80); op_43(z80); } /* DB DD */ +OP(dd,44) { _Z80_R++; _Z80_B = _HX; } /* LD B,HX */ +OP(dd,45) { _Z80_R++; _Z80_B = _LX; } /* LD B,LX */ +OP(dd,46) { _Z80_R++; EAX; _Z80_B = RM(z80->EA); } /* LD B,(IX+o) */ +OP(dd,47) { illegal_1(z80); op_47(z80); } /* DB DD */ + +OP(dd,48) { illegal_1(z80); op_48(z80); } /* DB DD */ +OP(dd,49) { illegal_1(z80); op_49(z80); } /* DB DD */ +OP(dd,4a) { illegal_1(z80); op_4a(z80); } /* DB DD */ +OP(dd,4b) { illegal_1(z80); op_4b(z80); } /* DB DD */ +OP(dd,4c) { _Z80_R++; _Z80_C = _HX; } /* LD C,HX */ +OP(dd,4d) { _Z80_R++; _Z80_C = _LX; } /* LD C,LX */ +OP(dd,4e) { _Z80_R++; EAX; _Z80_C = RM(z80->EA); } /* LD C,(IX+o) */ +OP(dd,4f) { illegal_1(z80); op_4f(z80); } /* DB DD */ + +OP(dd,50) { illegal_1(z80); op_50(z80); } /* DB DD */ +OP(dd,51) { illegal_1(z80); op_51(z80); } /* DB DD */ +OP(dd,52) { illegal_1(z80); op_52(z80); } /* DB DD */ +OP(dd,53) { illegal_1(z80); op_53(z80); } /* DB DD */ +OP(dd,54) { _Z80_R++; _Z80_D = _HX; } /* LD D,HX */ +OP(dd,55) { _Z80_R++; _Z80_D = _LX; } /* LD D,LX */ +OP(dd,56) { _Z80_R++; EAX; _Z80_D = RM(z80->EA); } /* LD D,(IX+o) */ +OP(dd,57) { illegal_1(z80); op_57(z80); } /* DB DD */ + +OP(dd,58) { illegal_1(z80); op_58(z80); } /* DB DD */ +OP(dd,59) { illegal_1(z80); op_59(z80); } /* DB DD */ +OP(dd,5a) { illegal_1(z80); op_5a(z80); } /* DB DD */ +OP(dd,5b) { illegal_1(z80); op_5b(z80); } /* DB DD */ +OP(dd,5c) { _Z80_R++; _Z80_E = _HX; } /* LD E,HX */ +OP(dd,5d) { _Z80_R++; _Z80_E = _LX; } /* LD E,LX */ +OP(dd,5e) { _Z80_R++; EAX; _Z80_E = RM(z80->EA); } /* LD E,(IX+o) */ +OP(dd,5f) { illegal_1(z80); op_5f(z80); } /* DB DD */ + +OP(dd,60) { _Z80_R++; _HX = _Z80_B; } /* LD HX,B */ +OP(dd,61) { _Z80_R++; _HX = _Z80_C; } /* LD HX,C */ +OP(dd,62) { _Z80_R++; _HX = _Z80_D; } /* LD HX,D */ +OP(dd,63) { _Z80_R++; _HX = _Z80_E; } /* LD HX,E */ +OP(dd,64) { } /* LD HX,HX */ +OP(dd,65) { _Z80_R++; _HX = _LX; } /* LD HX,LX */ +OP(dd,66) { _Z80_R++; EAX; _Z80_H = RM(z80->EA); } /* LD H,(IX+o) */ +OP(dd,67) { _Z80_R++; _HX = _Z80_A; } /* LD HX,A */ + +OP(dd,68) { _Z80_R++; _LX = _Z80_B; } /* LD LX,B */ +OP(dd,69) { _Z80_R++; _LX = _Z80_C; } /* LD LX,C */ +OP(dd,6a) { _Z80_R++; _LX = _Z80_D; } /* LD LX,D */ +OP(dd,6b) { _Z80_R++; _LX = _Z80_E; } /* LD LX,E */ +OP(dd,6c) { _Z80_R++; _LX = _HX; } /* LD LX,HX */ +OP(dd,6d) { } /* LD LX,LX */ +OP(dd,6e) { _Z80_R++; EAX; _Z80_L = RM(z80->EA); } /* LD L,(IX+o) */ +OP(dd,6f) { _Z80_R++; _LX = _Z80_A; } /* LD LX,A */ + +OP(dd,70) { _Z80_R++; EAX; WM( z80->EA, _Z80_B ); } /* LD (IX+o),B */ +OP(dd,71) { _Z80_R++; EAX; WM( z80->EA, _Z80_C ); } /* LD (IX+o),C */ +OP(dd,72) { _Z80_R++; EAX; WM( z80->EA, _Z80_D ); } /* LD (IX+o),D */ +OP(dd,73) { _Z80_R++; EAX; WM( z80->EA, _Z80_E ); } /* LD (IX+o),E */ +OP(dd,74) { _Z80_R++; EAX; WM( z80->EA, _Z80_H ); } /* LD (IX+o),H */ +OP(dd,75) { _Z80_R++; EAX; WM( z80->EA, _Z80_L ); } /* LD (IX+o),L */ +OP(dd,76) { illegal_1(z80); op_76(z80); } /* DB DD */ +OP(dd,77) { _Z80_R++; EAX; WM( z80->EA, _Z80_A ); } /* LD (IX+o),A */ + +OP(dd,78) { illegal_1(z80); op_78(z80); } /* DB DD */ +OP(dd,79) { illegal_1(z80); op_79(z80); } /* DB DD */ +OP(dd,7a) { illegal_1(z80); op_7a(z80); } /* DB DD */ +OP(dd,7b) { illegal_1(z80); op_7b(z80); } /* DB DD */ +OP(dd,7c) { _Z80_R++; _Z80_A = _HX; } /* LD A,HX */ +OP(dd,7d) { _Z80_R++; _Z80_A = _LX; } /* LD A,LX */ +OP(dd,7e) { _Z80_R++; EAX; _Z80_A = RM(z80->EA); } /* LD A,(IX+o) */ +OP(dd,7f) { illegal_1(z80); op_7f(z80); } /* DB DD */ + +OP(dd,80) { illegal_1(z80); op_80(z80); } /* DB DD */ +OP(dd,81) { illegal_1(z80); op_81(z80); } /* DB DD */ +OP(dd,82) { illegal_1(z80); op_82(z80); } /* DB DD */ +OP(dd,83) { illegal_1(z80); op_83(z80); } /* DB DD */ +OP(dd,84) { _Z80_R++; ADD(z80,_HX); } /* ADD A,HX */ +OP(dd,85) { _Z80_R++; ADD(z80,_LX); } /* ADD A,LX */ +OP(dd,86) { _Z80_R++; EAX; ADD(z80,RM(z80->EA)); } /* ADD A,(IX+o) */ +OP(dd,87) { illegal_1(z80); op_87(z80); } /* DB DD */ + +OP(dd,88) { illegal_1(z80); op_88(z80); } /* DB DD */ +OP(dd,89) { illegal_1(z80); op_89(z80); } /* DB DD */ +OP(dd,8a) { illegal_1(z80); op_8a(z80); } /* DB DD */ +OP(dd,8b) { illegal_1(z80); op_8b(z80); } /* DB DD */ +OP(dd,8c) { _Z80_R++; ADC(_HX); } /* ADC A,HX */ +OP(dd,8d) { _Z80_R++; ADC(_LX); } /* ADC A,LX */ +OP(dd,8e) { _Z80_R++; EAX; ADC(RM(z80->EA)); } /* ADC A,(IX+o) */ +OP(dd,8f) { illegal_1(z80); op_8f(z80); } /* DB DD */ + +OP(dd,90) { illegal_1(z80); op_90(z80); } /* DB DD */ +OP(dd,91) { illegal_1(z80); op_91(z80); } /* DB DD */ +OP(dd,92) { illegal_1(z80); op_92(z80); } /* DB DD */ +OP(dd,93) { illegal_1(z80); op_93(z80); } /* DB DD */ +OP(dd,94) { _Z80_R++; SUB(_HX); } /* SUB HX */ +OP(dd,95) { _Z80_R++; SUB(_LX); } /* SUB LX */ +OP(dd,96) { _Z80_R++; EAX; SUB(RM(z80->EA)); } /* SUB (IX+o) */ +OP(dd,97) { illegal_1(z80); op_97(z80); } /* DB DD */ + +OP(dd,98) { illegal_1(z80); op_98(z80); } /* DB DD */ +OP(dd,99) { illegal_1(z80); op_99(z80); } /* DB DD */ +OP(dd,9a) { illegal_1(z80); op_9a(z80); } /* DB DD */ +OP(dd,9b) { illegal_1(z80); op_9b(z80); } /* DB DD */ +OP(dd,9c) { _Z80_R++; SBC(_HX); } /* SBC A,HX */ +OP(dd,9d) { _Z80_R++; SBC(_LX); } /* SBC A,LX */ +OP(dd,9e) { _Z80_R++; EAX; SBC(RM(z80->EA)); } /* SBC A,(IX+o) */ +OP(dd,9f) { illegal_1(z80); op_9f(z80); } /* DB DD */ + +OP(dd,a0) { illegal_1(z80); op_a0(z80); } /* DB DD */ +OP(dd,a1) { illegal_1(z80); op_a1(z80); } /* DB DD */ +OP(dd,a2) { illegal_1(z80); op_a2(z80); } /* DB DD */ +OP(dd,a3) { illegal_1(z80); op_a3(z80); } /* DB DD */ +OP(dd,a4) { _Z80_R++; AND(_HX); } /* AND HX */ +OP(dd,a5) { _Z80_R++; AND(_LX); } /* AND LX */ +OP(dd,a6) { _Z80_R++; EAX; AND(RM(z80->EA)); } /* AND (IX+o) */ +OP(dd,a7) { illegal_1(z80); op_a7(z80); } /* DB DD */ + +OP(dd,a8) { illegal_1(z80); op_a8(z80); } /* DB DD */ +OP(dd,a9) { illegal_1(z80); op_a9(z80); } /* DB DD */ +OP(dd,aa) { illegal_1(z80); op_aa(z80); } /* DB DD */ +OP(dd,ab) { illegal_1(z80); op_ab(z80); } /* DB DD */ +OP(dd,ac) { _Z80_R++; XOR(_HX); } /* XOR HX */ +OP(dd,ad) { _Z80_R++; XOR(_LX); } /* XOR LX */ +OP(dd,ae) { _Z80_R++; EAX; XOR(RM(z80->EA)); } /* XOR (IX+o) */ +OP(dd,af) { illegal_1(z80); op_af(z80); } /* DB DD */ + +OP(dd,b0) { illegal_1(z80); op_b0(z80); } /* DB DD */ +OP(dd,b1) { illegal_1(z80); op_b1(z80); } /* DB DD */ +OP(dd,b2) { illegal_1(z80); op_b2(z80); } /* DB DD */ +OP(dd,b3) { illegal_1(z80); op_b3(z80); } /* DB DD */ +OP(dd,b4) { _Z80_R++; OR(_HX); } /* OR HX */ +OP(dd,b5) { _Z80_R++; OR(_LX); } /* OR LX */ +OP(dd,b6) { _Z80_R++; EAX; OR(RM(z80->EA)); } /* OR (IX+o) */ +OP(dd,b7) { illegal_1(z80); op_b7(z80); } /* DB DD */ + +OP(dd,b8) { illegal_1(z80); op_b8(z80); } /* DB DD */ +OP(dd,b9) { illegal_1(z80); op_b9(z80); } /* DB DD */ +OP(dd,ba) { illegal_1(z80); op_ba(z80); } /* DB DD */ +OP(dd,bb) { illegal_1(z80); op_bb(z80); } /* DB DD */ +OP(dd,bc) { _Z80_R++; CP(_HX); } /* CP HX */ +OP(dd,bd) { _Z80_R++; CP(_LX); } /* CP LX */ +OP(dd,be) { _Z80_R++; EAX; CP(RM(z80->EA)); } /* CP (IX+o) */ +OP(dd,bf) { illegal_1(z80); op_bf(z80); } /* DB DD */ + +OP(dd,c0) { illegal_1(z80); op_c0(z80); } /* DB DD */ +OP(dd,c1) { illegal_1(z80); op_c1(z80); } /* DB DD */ +OP(dd,c2) { illegal_1(z80); op_c2(z80); } /* DB DD */ +OP(dd,c3) { illegal_1(z80); op_c3(z80); } /* DB DD */ +OP(dd,c4) { illegal_1(z80); op_c4(z80); } /* DB DD */ +OP(dd,c5) { illegal_1(z80); op_c5(z80); } /* DB DD */ +OP(dd,c6) { illegal_1(z80); op_c6(z80); } /* DB DD */ +OP(dd,c7) { illegal_1(z80); op_c7(z80); } /* DB DD */ + +OP(dd,c8) { illegal_1(z80); op_c8(z80); } /* DB DD */ +OP(dd,c9) { illegal_1(z80); op_c9(z80); } /* DB DD */ +OP(dd,ca) { illegal_1(z80); op_ca(z80); } /* DB DD */ +OP(dd,cb) { _Z80_R++; EAX; EXEC(xycb,ARG(z80)); } /* ** DD CB xx */ +OP(dd,cc) { illegal_1(z80); op_cc(z80); } /* DB DD */ +OP(dd,cd) { illegal_1(z80); op_cd(z80); } /* DB DD */ +OP(dd,ce) { illegal_1(z80); op_ce(z80); } /* DB DD */ +OP(dd,cf) { illegal_1(z80); op_cf(z80); } /* DB DD */ + +OP(dd,d0) { illegal_1(z80); op_d0(z80); } /* DB DD */ +OP(dd,d1) { illegal_1(z80); op_d1(z80); } /* DB DD */ +OP(dd,d2) { illegal_1(z80); op_d2(z80); } /* DB DD */ +OP(dd,d3) { illegal_1(z80); op_d3(z80); } /* DB DD */ +OP(dd,d4) { illegal_1(z80); op_d4(z80); } /* DB DD */ +OP(dd,d5) { illegal_1(z80); op_d5(z80); } /* DB DD */ +OP(dd,d6) { illegal_1(z80); op_d6(z80); } /* DB DD */ +OP(dd,d7) { illegal_1(z80); op_d7(z80); } /* DB DD */ + +OP(dd,d8) { illegal_1(z80); op_d8(z80); } /* DB DD */ +OP(dd,d9) { illegal_1(z80); op_d9(z80); } /* DB DD */ +OP(dd,da) { illegal_1(z80); op_da(z80); } /* DB DD */ +OP(dd,db) { illegal_1(z80); op_db(z80); } /* DB DD */ +OP(dd,dc) { illegal_1(z80); op_dc(z80); } /* DB DD */ +OP(dd,dd) { illegal_1(z80); op_dd(z80); } /* DB DD */ +OP(dd,de) { illegal_1(z80); op_de(z80); } /* DB DD */ +OP(dd,df) { illegal_1(z80); op_df(z80); } /* DB DD */ + +OP(dd,e0) { illegal_1(z80); op_e0(z80); } /* DB DD */ +OP(dd,e1) { _Z80_R++; POP(IX); } /* POP IX */ +OP(dd,e2) { illegal_1(z80); op_e2(z80); } /* DB DD */ +OP(dd,e3) { _Z80_R++; EXSP(IX); } /* EX (SP),IX */ +OP(dd,e4) { illegal_1(z80); op_e4(z80); } /* DB DD */ +OP(dd,e5) { _Z80_R++; PUSH( IX ); } /* PUSH IX */ +OP(dd,e6) { illegal_1(z80); op_e6(z80); } /* DB DD */ +OP(dd,e7) { illegal_1(z80); op_e7(z80); } /* DB DD */ + +OP(dd,e8) { illegal_1(z80); op_e8(z80); } /* DB DD */ +OP(dd,e9) { _Z80_R++; _PC = _IX; change_pc16(_PCD); } /* JP (IX) */ +OP(dd,ea) { illegal_1(z80); op_ea(z80); } /* DB DD */ +OP(dd,eb) { illegal_1(z80); op_eb(z80); } /* DB DD */ +OP(dd,ec) { illegal_1(z80); op_ec(z80); } /* DB DD */ +OP(dd,ed) { illegal_1(z80); op_ed(z80); } /* DB DD */ +OP(dd,ee) { illegal_1(z80); op_ee(z80); } /* DB DD */ +OP(dd,ef) { illegal_1(z80); op_ef(z80); } /* DB DD */ + +OP(dd,f0) { illegal_1(z80); op_f0(z80); } /* DB DD */ +OP(dd,f1) { illegal_1(z80); op_f1(z80); } /* DB DD */ +OP(dd,f2) { illegal_1(z80); op_f2(z80); } /* DB DD */ +OP(dd,f3) { illegal_1(z80); op_f3(z80); } /* DB DD */ +OP(dd,f4) { illegal_1(z80); op_f4(z80); } /* DB DD */ +OP(dd,f5) { illegal_1(z80); op_f5(z80); } /* DB DD */ +OP(dd,f6) { illegal_1(z80); op_f6(z80); } /* DB DD */ +OP(dd,f7) { illegal_1(z80); op_f7(z80); } /* DB DD */ + +OP(dd,f8) { illegal_1(z80); op_f8(z80); } /* DB DD */ +OP(dd,f9) { _Z80_R++; _SP = _IX; } /* LD SP,IX */ +OP(dd,fa) { illegal_1(z80); op_fa(z80); } /* DB DD */ +OP(dd,fb) { illegal_1(z80); op_fb(z80); } /* DB DD */ +OP(dd,fc) { illegal_1(z80); op_fc(z80); } /* DB DD */ +OP(dd,fd) { illegal_1(z80); op_fd(z80); } /* DB DD */ +OP(dd,fe) { illegal_1(z80); op_fe(z80); } /* DB DD */ +OP(dd,ff) { illegal_1(z80); op_ff(z80); } /* DB DD */ + +/********************************************************** + * IY register related opcodes (FD prefix) + **********************************************************/ +OP(fd,00) { illegal_1(z80); op_00(z80); } /* DB FD */ +OP(fd,01) { illegal_1(z80); op_01(z80); } /* DB FD */ +OP(fd,02) { illegal_1(z80); op_02(z80); } /* DB FD */ +OP(fd,03) { illegal_1(z80); op_03(z80); } /* DB FD */ +OP(fd,04) { illegal_1(z80); op_04(z80); } /* DB FD */ +OP(fd,05) { illegal_1(z80); op_05(z80); } /* DB FD */ +OP(fd,06) { illegal_1(z80); op_06(z80); } /* DB FD */ +OP(fd,07) { illegal_1(z80); op_07(z80); } /* DB FD */ + +OP(fd,08) { illegal_1(z80); op_08(z80); } /* DB FD */ +OP(fd,09) { _Z80_R++; ADD16(z80,IY,BC); } /* ADD IY,BC */ +OP(fd,0a) { illegal_1(z80); op_0a(z80); } /* DB FD */ +OP(fd,0b) { illegal_1(z80); op_0b(z80); } /* DB FD */ +OP(fd,0c) { illegal_1(z80); op_0c(z80); } /* DB FD */ +OP(fd,0d) { illegal_1(z80); op_0d(z80); } /* DB FD */ +OP(fd,0e) { illegal_1(z80); op_0e(z80); } /* DB FD */ +OP(fd,0f) { illegal_1(z80); op_0f(z80); } /* DB FD */ + +OP(fd,10) { illegal_1(z80); op_10(z80); } /* DB FD */ +OP(fd,11) { illegal_1(z80); op_11(z80); } /* DB FD */ +OP(fd,12) { illegal_1(z80); op_12(z80); } /* DB FD */ +OP(fd,13) { illegal_1(z80); op_13(z80); } /* DB FD */ +OP(fd,14) { illegal_1(z80); op_14(z80); } /* DB FD */ +OP(fd,15) { illegal_1(z80); op_15(z80); } /* DB FD */ +OP(fd,16) { illegal_1(z80); op_16(z80); } /* DB FD */ +OP(fd,17) { illegal_1(z80); op_17(z80); } /* DB FD */ + +OP(fd,18) { illegal_1(z80); op_18(z80); } /* DB FD */ +OP(fd,19) { _Z80_R++; ADD16(z80,IY,DE); } /* ADD IY,DE */ +OP(fd,1a) { illegal_1(z80); op_1a(z80); } /* DB FD */ +OP(fd,1b) { illegal_1(z80); op_1b(z80); } /* DB FD */ +OP(fd,1c) { illegal_1(z80); op_1c(z80); } /* DB FD */ +OP(fd,1d) { illegal_1(z80); op_1d(z80); } /* DB FD */ +OP(fd,1e) { illegal_1(z80); op_1e(z80); } /* DB FD */ +OP(fd,1f) { illegal_1(z80); op_1f(z80); } /* DB FD */ + +OP(fd,20) { illegal_1(z80); op_20(z80); } /* DB FD */ +OP(fd,21) { _Z80_R++; _IY = ARG16(z80); } /* LD IY,w */ +OP(fd,22) { _Z80_R++; z80->EA = ARG16(z80); WM16(z80, z80->EA, &z80->Z80.IY ); } /* LD (w),IY */ +OP(fd,23) { _Z80_R++; _IY++; } /* INC IY */ +OP(fd,24) { _Z80_R++; _HY = INC(z80,_HY); } /* INC HY */ +OP(fd,25) { _Z80_R++; _HY = DEC(z80,_HY); } /* DEC HY */ +OP(fd,26) { _Z80_R++; _HY = ARG(z80); } /* LD HY,n */ +OP(fd,27) { illegal_1(z80); op_27(z80); } /* DB FD */ + +OP(fd,28) { illegal_1(z80); op_28(z80); } /* DB FD */ +OP(fd,29) { _Z80_R++; ADD16(z80,IY,IY); } /* ADD IY,IY */ +OP(fd,2a) { _Z80_R++; z80->EA = ARG16(z80); RM16(z80, z80->EA, &z80->Z80.IY ); } /* LD IY,(w) */ +OP(fd,2b) { _Z80_R++; _IY--; } /* DEC IY */ +OP(fd,2c) { _Z80_R++; _LY = INC(z80,_LY); } /* INC LY */ +OP(fd,2d) { _Z80_R++; _LY = DEC(z80,_LY); } /* DEC LY */ +OP(fd,2e) { _Z80_R++; _LY = ARG(z80); } /* LD LY,n */ +OP(fd,2f) { illegal_1(z80); op_2f(z80); } /* DB FD */ + +OP(fd,30) { illegal_1(z80); op_30(z80); } /* DB FD */ +OP(fd,31) { illegal_1(z80); op_31(z80); } /* DB FD */ +OP(fd,32) { illegal_1(z80); op_32(z80); } /* DB FD */ +OP(fd,33) { illegal_1(z80); op_33(z80); } /* DB FD */ +OP(fd,34) { _Z80_R++; EAY; WM( z80->EA, INC(z80,RM(z80->EA)) ); } /* INC (IY+o) */ +OP(fd,35) { _Z80_R++; EAY; WM( z80->EA, DEC(z80,RM(z80->EA)) ); } /* DEC (IY+o) */ +OP(fd,36) { _Z80_R++; EAY; WM( z80->EA, ARG(z80) ); } /* LD (IY+o),n */ +OP(fd,37) { illegal_1(z80); op_37(z80); } /* DB FD */ + +OP(fd,38) { illegal_1(z80); op_38(z80); } /* DB FD */ +OP(fd,39) { _Z80_R++; ADD16(z80,IY,SP); } /* ADD IY,SP */ +OP(fd,3a) { illegal_1(z80); op_3a(z80); } /* DB FD */ +OP(fd,3b) { illegal_1(z80); op_3b(z80); } /* DB FD */ +OP(fd,3c) { illegal_1(z80); op_3c(z80); } /* DB FD */ +OP(fd,3d) { illegal_1(z80); op_3d(z80); } /* DB FD */ +OP(fd,3e) { illegal_1(z80); op_3e(z80); } /* DB FD */ +OP(fd,3f) { illegal_1(z80); op_3f(z80); } /* DB FD */ + +OP(fd,40) { illegal_1(z80); op_40(z80); } /* DB FD */ +OP(fd,41) { illegal_1(z80); op_41(z80); } /* DB FD */ +OP(fd,42) { illegal_1(z80); op_42(z80); } /* DB FD */ +OP(fd,43) { illegal_1(z80); op_43(z80); } /* DB FD */ +OP(fd,44) { _Z80_R++; _Z80_B = _HY; } /* LD B,HY */ +OP(fd,45) { _Z80_R++; _Z80_B = _LY; } /* LD B,LY */ +OP(fd,46) { _Z80_R++; EAY; _Z80_B = RM(z80->EA); } /* LD B,(IY+o) */ +OP(fd,47) { illegal_1(z80); op_47(z80); } /* DB FD */ + +OP(fd,48) { illegal_1(z80); op_48(z80); } /* DB FD */ +OP(fd,49) { illegal_1(z80); op_49(z80); } /* DB FD */ +OP(fd,4a) { illegal_1(z80); op_4a(z80); } /* DB FD */ +OP(fd,4b) { illegal_1(z80); op_4b(z80); } /* DB FD */ +OP(fd,4c) { _Z80_R++; _Z80_C = _HY; } /* LD C,HY */ +OP(fd,4d) { _Z80_R++; _Z80_C = _LY; } /* LD C,LY */ +OP(fd,4e) { _Z80_R++; EAY; _Z80_C = RM(z80->EA); } /* LD C,(IY+o) */ +OP(fd,4f) { illegal_1(z80); op_4f(z80); } /* DB FD */ + +OP(fd,50) { illegal_1(z80); op_50(z80); } /* DB FD */ +OP(fd,51) { illegal_1(z80); op_51(z80); } /* DB FD */ +OP(fd,52) { illegal_1(z80); op_52(z80); } /* DB FD */ +OP(fd,53) { illegal_1(z80); op_53(z80); } /* DB FD */ +OP(fd,54) { _Z80_R++; _Z80_D = _HY; } /* LD D,HY */ +OP(fd,55) { _Z80_R++; _Z80_D = _LY; } /* LD D,LY */ +OP(fd,56) { _Z80_R++; EAY; _Z80_D = RM(z80->EA); } /* LD D,(IY+o) */ +OP(fd,57) { illegal_1(z80); op_57(z80); } /* DB FD */ + +OP(fd,58) { illegal_1(z80); op_58(z80); } /* DB FD */ +OP(fd,59) { illegal_1(z80); op_59(z80); } /* DB FD */ +OP(fd,5a) { illegal_1(z80); op_5a(z80); } /* DB FD */ +OP(fd,5b) { illegal_1(z80); op_5b(z80); } /* DB FD */ +OP(fd,5c) { _Z80_R++; _Z80_E = _HY; } /* LD E,HY */ +OP(fd,5d) { _Z80_R++; _Z80_E = _LY; } /* LD E,LY */ +OP(fd,5e) { _Z80_R++; EAY; _Z80_E = RM(z80->EA); } /* LD E,(IY+o) */ +OP(fd,5f) { illegal_1(z80); op_5f(z80); } /* DB FD */ + +OP(fd,60) { _Z80_R++; _HY = _Z80_B; } /* LD HY,B */ +OP(fd,61) { _Z80_R++; _HY = _Z80_C; } /* LD HY,C */ +OP(fd,62) { _Z80_R++; _HY = _Z80_D; } /* LD HY,D */ +OP(fd,63) { _Z80_R++; _HY = _Z80_E; } /* LD HY,E */ +OP(fd,64) { _Z80_R++; } /* LD HY,HY */ +OP(fd,65) { _Z80_R++; _HY = _LY; } /* LD HY,LY */ +OP(fd,66) { _Z80_R++; EAY; _Z80_H = RM(z80->EA); } /* LD H,(IY+o) */ +OP(fd,67) { _Z80_R++; _HY = _Z80_A; } /* LD HY,A */ + +OP(fd,68) { _Z80_R++; _LY = _Z80_B; } /* LD LY,B */ +OP(fd,69) { _Z80_R++; _LY = _Z80_C; } /* LD LY,C */ +OP(fd,6a) { _Z80_R++; _LY = _Z80_D; } /* LD LY,D */ +OP(fd,6b) { _Z80_R++; _LY = _Z80_E; } /* LD LY,E */ +OP(fd,6c) { _Z80_R++; _LY = _HY; } /* LD LY,HY */ +OP(fd,6d) { _Z80_R++; } /* LD LY,LY */ +OP(fd,6e) { _Z80_R++; EAY; _Z80_L = RM(z80->EA); } /* LD L,(IY+o) */ +OP(fd,6f) { _Z80_R++; _LY = _Z80_A; } /* LD LY,A */ + +OP(fd,70) { _Z80_R++; EAY; WM( z80->EA, _Z80_B ); } /* LD (IY+o),B */ +OP(fd,71) { _Z80_R++; EAY; WM( z80->EA, _Z80_C ); } /* LD (IY+o),C */ +OP(fd,72) { _Z80_R++; EAY; WM( z80->EA, _Z80_D ); } /* LD (IY+o),D */ +OP(fd,73) { _Z80_R++; EAY; WM( z80->EA, _Z80_E ); } /* LD (IY+o),E */ +OP(fd,74) { _Z80_R++; EAY; WM( z80->EA, _Z80_H ); } /* LD (IY+o),H */ +OP(fd,75) { _Z80_R++; EAY; WM( z80->EA, _Z80_L ); } /* LD (IY+o),L */ +OP(fd,76) { illegal_1(z80); op_76(z80); } /* DB FD */ +OP(fd,77) { _Z80_R++; EAY; WM( z80->EA, _Z80_A ); } /* LD (IY+o),A */ + +OP(fd,78) { illegal_1(z80); op_78(z80); } /* DB FD */ +OP(fd,79) { illegal_1(z80); op_79(z80); } /* DB FD */ +OP(fd,7a) { illegal_1(z80); op_7a(z80); } /* DB FD */ +OP(fd,7b) { illegal_1(z80); op_7b(z80); } /* DB FD */ +OP(fd,7c) { _Z80_R++; _Z80_A = _HY; } /* LD A,HY */ +OP(fd,7d) { _Z80_R++; _Z80_A = _LY; } /* LD A,LY */ +OP(fd,7e) { _Z80_R++; EAY; _Z80_A = RM(z80->EA); } /* LD A,(IY+o) */ +OP(fd,7f) { illegal_1(z80); op_7f(z80); } /* DB FD */ + +OP(fd,80) { illegal_1(z80); op_80(z80); } /* DB FD */ +OP(fd,81) { illegal_1(z80); op_81(z80); } /* DB FD */ +OP(fd,82) { illegal_1(z80); op_82(z80); } /* DB FD */ +OP(fd,83) { illegal_1(z80); op_83(z80); } /* DB FD */ +OP(fd,84) { _Z80_R++; ADD(z80,_HY); } /* ADD A,HY */ +OP(fd,85) { _Z80_R++; ADD(z80,_LY); } /* ADD A,LY */ +OP(fd,86) { _Z80_R++; EAY; ADD(z80,RM(z80->EA)); } /* ADD A,(IY+o) */ +OP(fd,87) { illegal_1(z80); op_87(z80); } /* DB FD */ + +OP(fd,88) { illegal_1(z80); op_88(z80); } /* DB FD */ +OP(fd,89) { illegal_1(z80); op_89(z80); } /* DB FD */ +OP(fd,8a) { illegal_1(z80); op_8a(z80); } /* DB FD */ +OP(fd,8b) { illegal_1(z80); op_8b(z80); } /* DB FD */ +OP(fd,8c) { _Z80_R++; ADC(_HY); } /* ADC A,HY */ +OP(fd,8d) { _Z80_R++; ADC(_LY); } /* ADC A,LY */ +OP(fd,8e) { _Z80_R++; EAY; ADC(RM(z80->EA)); } /* ADC A,(IY+o) */ +OP(fd,8f) { illegal_1(z80); op_8f(z80); } /* DB FD */ + +OP(fd,90) { illegal_1(z80); op_90(z80); } /* DB FD */ +OP(fd,91) { illegal_1(z80); op_91(z80); } /* DB FD */ +OP(fd,92) { illegal_1(z80); op_92(z80); } /* DB FD */ +OP(fd,93) { illegal_1(z80); op_93(z80); } /* DB FD */ +OP(fd,94) { _Z80_R++; SUB(_HY); } /* SUB HY */ +OP(fd,95) { _Z80_R++; SUB(_LY); } /* SUB LY */ +OP(fd,96) { _Z80_R++; EAY; SUB(RM(z80->EA)); } /* SUB (IY+o) */ +OP(fd,97) { illegal_1(z80); op_97(z80); } /* DB FD */ + +OP(fd,98) { illegal_1(z80); op_98(z80); } /* DB FD */ +OP(fd,99) { illegal_1(z80); op_99(z80); } /* DB FD */ +OP(fd,9a) { illegal_1(z80); op_9a(z80); } /* DB FD */ +OP(fd,9b) { illegal_1(z80); op_9b(z80); } /* DB FD */ +OP(fd,9c) { _Z80_R++; SBC(_HY); } /* SBC A,HY */ +OP(fd,9d) { _Z80_R++; SBC(_LY); } /* SBC A,LY */ +OP(fd,9e) { _Z80_R++; EAY; SBC(RM(z80->EA)); } /* SBC A,(IY+o) */ +OP(fd,9f) { illegal_1(z80); op_9f(z80); } /* DB FD */ + +OP(fd,a0) { illegal_1(z80); op_a0(z80); } /* DB FD */ +OP(fd,a1) { illegal_1(z80); op_a1(z80); } /* DB FD */ +OP(fd,a2) { illegal_1(z80); op_a2(z80); } /* DB FD */ +OP(fd,a3) { illegal_1(z80); op_a3(z80); } /* DB FD */ +OP(fd,a4) { _Z80_R++; AND(_HY); } /* AND HY */ +OP(fd,a5) { _Z80_R++; AND(_LY); } /* AND LY */ +OP(fd,a6) { _Z80_R++; EAY; AND(RM(z80->EA)); } /* AND (IY+o) */ +OP(fd,a7) { illegal_1(z80); op_a7(z80); } /* DB FD */ + +OP(fd,a8) { illegal_1(z80); op_a8(z80); } /* DB FD */ +OP(fd,a9) { illegal_1(z80); op_a9(z80); } /* DB FD */ +OP(fd,aa) { illegal_1(z80); op_aa(z80); } /* DB FD */ +OP(fd,ab) { illegal_1(z80); op_ab(z80); } /* DB FD */ +OP(fd,ac) { _Z80_R++; XOR(_HY); } /* XOR HY */ +OP(fd,ad) { _Z80_R++; XOR(_LY); } /* XOR LY */ +OP(fd,ae) { _Z80_R++; EAY; XOR(RM(z80->EA)); } /* XOR (IY+o) */ +OP(fd,af) { illegal_1(z80); op_af(z80); } /* DB FD */ + +OP(fd,b0) { illegal_1(z80); op_b0(z80); } /* DB FD */ +OP(fd,b1) { illegal_1(z80); op_b1(z80); } /* DB FD */ +OP(fd,b2) { illegal_1(z80); op_b2(z80); } /* DB FD */ +OP(fd,b3) { illegal_1(z80); op_b3(z80); } /* DB FD */ +OP(fd,b4) { _Z80_R++; OR(_HY); } /* OR HY */ +OP(fd,b5) { _Z80_R++; OR(_LY); } /* OR LY */ +OP(fd,b6) { _Z80_R++; EAY; OR(RM(z80->EA)); } /* OR (IY+o) */ +OP(fd,b7) { illegal_1(z80); op_b7(z80); } /* DB FD */ + +OP(fd,b8) { illegal_1(z80); op_b8(z80); } /* DB FD */ +OP(fd,b9) { illegal_1(z80); op_b9(z80); } /* DB FD */ +OP(fd,ba) { illegal_1(z80); op_ba(z80); } /* DB FD */ +OP(fd,bb) { illegal_1(z80); op_bb(z80); } /* DB FD */ +OP(fd,bc) { _Z80_R++; CP(_HY); } /* CP HY */ +OP(fd,bd) { _Z80_R++; CP(_LY); } /* CP LY */ +OP(fd,be) { _Z80_R++; EAY; CP(RM(z80->EA)); } /* CP (IY+o) */ +OP(fd,bf) { illegal_1(z80); op_bf(z80); } /* DB FD */ + +OP(fd,c0) { illegal_1(z80); op_c0(z80); } /* DB FD */ +OP(fd,c1) { illegal_1(z80); op_c1(z80); } /* DB FD */ +OP(fd,c2) { illegal_1(z80); op_c2(z80); } /* DB FD */ +OP(fd,c3) { illegal_1(z80); op_c3(z80); } /* DB FD */ +OP(fd,c4) { illegal_1(z80); op_c4(z80); } /* DB FD */ +OP(fd,c5) { illegal_1(z80); op_c5(z80); } /* DB FD */ +OP(fd,c6) { illegal_1(z80); op_c6(z80); } /* DB FD */ +OP(fd,c7) { illegal_1(z80); op_c7(z80); } /* DB FD */ + +OP(fd,c8) { illegal_1(z80); op_c8(z80); } /* DB FD */ +OP(fd,c9) { illegal_1(z80); op_c9(z80); } /* DB FD */ +OP(fd,ca) { illegal_1(z80); op_ca(z80); } /* DB FD */ +OP(fd,cb) { _Z80_R++; EAY; EXEC(xycb,ARG(z80)); } /* ** FD CB xx */ +OP(fd,cc) { illegal_1(z80); op_cc(z80); } /* DB FD */ +OP(fd,cd) { illegal_1(z80); op_cd(z80); } /* DB FD */ +OP(fd,ce) { illegal_1(z80); op_ce(z80); } /* DB FD */ +OP(fd,cf) { illegal_1(z80); op_cf(z80); } /* DB FD */ + +OP(fd,d0) { illegal_1(z80); op_d0(z80); } /* DB FD */ +OP(fd,d1) { illegal_1(z80); op_d1(z80); } /* DB FD */ +OP(fd,d2) { illegal_1(z80); op_d2(z80); } /* DB FD */ +OP(fd,d3) { illegal_1(z80); op_d3(z80); } /* DB FD */ +OP(fd,d4) { illegal_1(z80); op_d4(z80); } /* DB FD */ +OP(fd,d5) { illegal_1(z80); op_d5(z80); } /* DB FD */ +OP(fd,d6) { illegal_1(z80); op_d6(z80); } /* DB FD */ +OP(fd,d7) { illegal_1(z80); op_d7(z80); } /* DB FD */ + +OP(fd,d8) { illegal_1(z80); op_d8(z80); } /* DB FD */ +OP(fd,d9) { illegal_1(z80); op_d9(z80); } /* DB FD */ +OP(fd,da) { illegal_1(z80); op_da(z80); } /* DB FD */ +OP(fd,db) { illegal_1(z80); op_db(z80); } /* DB FD */ +OP(fd,dc) { illegal_1(z80); op_dc(z80); } /* DB FD */ +OP(fd,dd) { illegal_1(z80); op_dd(z80); } /* DB FD */ +OP(fd,de) { illegal_1(z80); op_de(z80); } /* DB FD */ +OP(fd,df) { illegal_1(z80); op_df(z80); } /* DB FD */ + +OP(fd,e0) { illegal_1(z80); op_e0(z80); } /* DB FD */ +OP(fd,e1) { _Z80_R++; POP(IY); } /* POP IY */ +OP(fd,e2) { illegal_1(z80); op_e2(z80); } /* DB FD */ +OP(fd,e3) { _Z80_R++; EXSP(IY); } /* EX (SP),IY */ +OP(fd,e4) { illegal_1(z80); op_e4(z80); } /* DB FD */ +OP(fd,e5) { _Z80_R++; PUSH( IY ); } /* PUSH IY */ +OP(fd,e6) { illegal_1(z80); op_e6(z80); } /* DB FD */ +OP(fd,e7) { illegal_1(z80); op_e7(z80); } /* DB FD */ + +OP(fd,e8) { illegal_1(z80); op_e8(z80); } /* DB FD */ +OP(fd,e9) { _Z80_R++; _PC = _IY; change_pc16(_PCD); } /* JP (IY) */ +OP(fd,ea) { illegal_1(z80); op_ea(z80); } /* DB FD */ +OP(fd,eb) { illegal_1(z80); op_eb(z80); } /* DB FD */ +OP(fd,ec) { illegal_1(z80); op_ec(z80); } /* DB FD */ +OP(fd,ed) { illegal_1(z80); op_ed(z80); } /* DB FD */ +OP(fd,ee) { illegal_1(z80); op_ee(z80); } /* DB FD */ +OP(fd,ef) { illegal_1(z80); op_ef(z80); } /* DB FD */ + +OP(fd,f0) { illegal_1(z80); op_f0(z80); } /* DB FD */ +OP(fd,f1) { illegal_1(z80); op_f1(z80); } /* DB FD */ +OP(fd,f2) { illegal_1(z80); op_f2(z80); } /* DB FD */ +OP(fd,f3) { illegal_1(z80); op_f3(z80); } /* DB FD */ +OP(fd,f4) { illegal_1(z80); op_f4(z80); } /* DB FD */ +OP(fd,f5) { illegal_1(z80); op_f5(z80); } /* DB FD */ +OP(fd,f6) { illegal_1(z80); op_f6(z80); } /* DB FD */ +OP(fd,f7) { illegal_1(z80); op_f7(z80); } /* DB FD */ + +OP(fd,f8) { illegal_1(z80); op_f8(z80); } /* DB FD */ +OP(fd,f9) { _Z80_R++; _SP = _IY; } /* LD SP,IY */ +OP(fd,fa) { illegal_1(z80); op_fa(z80); } /* DB FD */ +OP(fd,fb) { illegal_1(z80); op_fb(z80); } /* DB FD */ +OP(fd,fc) { illegal_1(z80); op_fc(z80); } /* DB FD */ +OP(fd,fd) { illegal_1(z80); op_fd(z80); } /* DB FD */ +OP(fd,fe) { illegal_1(z80); op_fe(z80); } /* DB FD */ +OP(fd,ff) { illegal_1(z80); op_ff(z80); } /* DB FD */ + +OP(illegal,2) +{ + logerror("Z80 #%d ill. opcode $ed $%02x\n", + cpu_getactivecpu(), cpu_readop(z80->userdata,(_PCD-1)&0xffff)); +} + +/********************************************************** + * special opcodes (ED prefix) + **********************************************************/ +OP(ed,00) { illegal_2(z80); } /* DB ED */ +OP(ed,01) { illegal_2(z80); } /* DB ED */ +OP(ed,02) { illegal_2(z80); } /* DB ED */ +OP(ed,03) { illegal_2(z80); } /* DB ED */ +OP(ed,04) { illegal_2(z80); } /* DB ED */ +OP(ed,05) { illegal_2(z80); } /* DB ED */ +OP(ed,06) { illegal_2(z80); } /* DB ED */ +OP(ed,07) { illegal_2(z80); } /* DB ED */ + +OP(ed,08) { illegal_2(z80); } /* DB ED */ +OP(ed,09) { illegal_2(z80); } /* DB ED */ +OP(ed,0a) { illegal_2(z80); } /* DB ED */ +OP(ed,0b) { illegal_2(z80); } /* DB ED */ +OP(ed,0c) { illegal_2(z80); } /* DB ED */ +OP(ed,0d) { illegal_2(z80); } /* DB ED */ +OP(ed,0e) { illegal_2(z80); } /* DB ED */ +OP(ed,0f) { illegal_2(z80); } /* DB ED */ + +OP(ed,10) { illegal_2(z80); } /* DB ED */ +OP(ed,11) { illegal_2(z80); } /* DB ED */ +OP(ed,12) { illegal_2(z80); } /* DB ED */ +OP(ed,13) { illegal_2(z80); } /* DB ED */ +OP(ed,14) { illegal_2(z80); } /* DB ED */ +OP(ed,15) { illegal_2(z80); } /* DB ED */ +OP(ed,16) { illegal_2(z80); } /* DB ED */ +OP(ed,17) { illegal_2(z80); } /* DB ED */ + +OP(ed,18) { illegal_2(z80); } /* DB ED */ +OP(ed,19) { illegal_2(z80); } /* DB ED */ +OP(ed,1a) { illegal_2(z80); } /* DB ED */ +OP(ed,1b) { illegal_2(z80); } /* DB ED */ +OP(ed,1c) { illegal_2(z80); } /* DB ED */ +OP(ed,1d) { illegal_2(z80); } /* DB ED */ +OP(ed,1e) { illegal_2(z80); } /* DB ED */ +OP(ed,1f) { illegal_2(z80); } /* DB ED */ + +OP(ed,20) { illegal_2(z80); } /* DB ED */ +OP(ed,21) { illegal_2(z80); } /* DB ED */ +OP(ed,22) { illegal_2(z80); } /* DB ED */ +OP(ed,23) { illegal_2(z80); } /* DB ED */ +OP(ed,24) { illegal_2(z80); } /* DB ED */ +OP(ed,25) { illegal_2(z80); } /* DB ED */ +OP(ed,26) { illegal_2(z80); } /* DB ED */ +OP(ed,27) { illegal_2(z80); } /* DB ED */ + +OP(ed,28) { illegal_2(z80); } /* DB ED */ +OP(ed,29) { illegal_2(z80); } /* DB ED */ +OP(ed,2a) { illegal_2(z80); } /* DB ED */ +OP(ed,2b) { illegal_2(z80); } /* DB ED */ +OP(ed,2c) { illegal_2(z80); } /* DB ED */ +OP(ed,2d) { illegal_2(z80); } /* DB ED */ +OP(ed,2e) { illegal_2(z80); } /* DB ED */ +OP(ed,2f) { illegal_2(z80); } /* DB ED */ + +OP(ed,30) { illegal_2(z80); } /* DB ED */ +OP(ed,31) { illegal_2(z80); } /* DB ED */ +OP(ed,32) { illegal_2(z80); } /* DB ED */ +OP(ed,33) { illegal_2(z80); } /* DB ED */ +OP(ed,34) { illegal_2(z80); } /* DB ED */ +OP(ed,35) { illegal_2(z80); } /* DB ED */ +OP(ed,36) { illegal_2(z80); } /* DB ED */ +OP(ed,37) { illegal_2(z80); } /* DB ED */ + +OP(ed,38) { illegal_2(z80); } /* DB ED */ +OP(ed,39) { illegal_2(z80); } /* DB ED */ +OP(ed,3a) { illegal_2(z80); } /* DB ED */ +OP(ed,3b) { illegal_2(z80); } /* DB ED */ +OP(ed,3c) { illegal_2(z80); } /* DB ED */ +OP(ed,3d) { illegal_2(z80); } /* DB ED */ +OP(ed,3e) { illegal_2(z80); } /* DB ED */ +OP(ed,3f) { illegal_2(z80); } /* DB ED */ + +OP(ed,40) { _Z80_B = IN(_BC); _F = (_F & CF) | z80->SZP[_Z80_B]; } /* IN B,(C) */ +OP(ed,41) { OUT(_BC,_Z80_B); } /* OUT (C),B */ +OP(ed,42) { SBC16( BC ); } /* SBC HL,BC */ +OP(ed,43) { z80->EA = ARG16(z80); WM16(z80, z80->EA, &z80->Z80.BC ); } /* LD (w),BC */ +OP(ed,44) { NEG; } /* NEG */ +OP(ed,45) { RETN; } /* RETN; */ +OP(ed,46) { _IM = 0; } /* IM 0 */ +OP(ed,47) { LD_I_A; } /* LD I,A */ + +OP(ed,48) { _Z80_C = IN(_BC); _F = (_F & CF) | z80->SZP[_Z80_C]; } /* IN C,(C) */ +OP(ed,49) { OUT(_BC,_Z80_C); } /* OUT (C),C */ +OP(ed,4a) { ADC16( BC ); } /* ADC HL,BC */ +OP(ed,4b) { z80->EA = ARG16(z80); RM16(z80, z80->EA, &z80->Z80.BC ); } /* LD BC,(w) */ +OP(ed,4c) { NEG; } /* NEG */ +OP(ed,4d) { RETI; } /* RETI */ +OP(ed,4e) { _IM = 0; } /* IM 0 */ +OP(ed,4f) { LD_R_A; } /* LD R,A */ + +OP(ed,50) { _Z80_D = IN(_BC); _F = (_F & CF) | z80->SZP[_Z80_D]; } /* IN D,(C) */ +OP(ed,51) { OUT(_BC,_Z80_D); } /* OUT (C),D */ +OP(ed,52) { SBC16( DE ); } /* SBC HL,DE */ +OP(ed,53) { z80->EA = ARG16(z80); WM16(z80, z80->EA, &z80->Z80.DE ); } /* LD (w),DE */ +OP(ed,54) { NEG; } /* NEG */ +OP(ed,55) { RETN; } /* RETN; */ +OP(ed,56) { _IM = 1; } /* IM 1 */ +OP(ed,57) { LD_A_I; } /* LD A,I */ + +OP(ed,58) { _Z80_E = IN(_BC); _F = (_F & CF) | z80->SZP[_Z80_E]; } /* IN E,(C) */ +OP(ed,59) { OUT(_BC,_Z80_E); } /* OUT (C),E */ +OP(ed,5a) { ADC16( DE ); } /* ADC HL,DE */ +OP(ed,5b) { z80->EA = ARG16(z80); RM16(z80, z80->EA, &z80->Z80.DE ); } /* LD DE,(w) */ +OP(ed,5c) { NEG; } /* NEG */ +OP(ed,5d) { RETI; } /* RETI */ +OP(ed,5e) { _IM = 2; } /* IM 2 */ +OP(ed,5f) { LD_A_R; } /* LD A,R */ + +OP(ed,60) { _Z80_H = IN(_BC); _F = (_F & CF) | z80->SZP[_Z80_H]; } /* IN H,(C) */ +OP(ed,61) { OUT(_BC,_Z80_H); } /* OUT (C),H */ +OP(ed,62) { SBC16( HL ); } /* SBC HL,HL */ +OP(ed,63) { z80->EA = ARG16(z80); WM16(z80, z80->EA, &z80->Z80.HL ); } /* LD (w),HL */ +OP(ed,64) { NEG; } /* NEG */ +OP(ed,65) { RETN; } /* RETN; */ +OP(ed,66) { _IM = 0; } /* IM 0 */ +OP(ed,67) { RRD; } /* RRD (HL) */ + +OP(ed,68) { _Z80_L = IN(_BC); _F = (_F & CF) | z80->SZP[_Z80_L]; } /* IN L,(C) */ +OP(ed,69) { OUT(_BC,_Z80_L); } /* OUT (C),L */ +OP(ed,6a) { ADC16( HL ); } /* ADC HL,HL */ +OP(ed,6b) { z80->EA = ARG16(z80); RM16(z80, z80->EA, &z80->Z80.HL ); } /* LD HL,(w) */ +OP(ed,6c) { NEG; } /* NEG */ +OP(ed,6d) { RETI; } /* RETI */ +OP(ed,6e) { _IM = 0; } /* IM 0 */ +OP(ed,6f) { RLD; } /* RLD (HL) */ + +OP(ed,70) { UINT8 res = IN(_BC); _F = (_F & CF) | z80->SZP[res]; } /* IN 0,(C) */ +OP(ed,71) { OUT(_BC,0); } /* OUT (C),0 */ +OP(ed,72) { SBC16( SP ); } /* SBC HL,SP */ +OP(ed,73) { z80->EA = ARG16(z80); WM16(z80, z80->EA, &z80->Z80.SP ); } /* LD (w),SP */ +OP(ed,74) { NEG; } /* NEG */ +OP(ed,75) { RETN; } /* RETN; */ +OP(ed,76) { _IM = 1; } /* IM 1 */ +OP(ed,77) { illegal_2(z80); } /* DB ED,77 */ + +OP(ed,78) { _Z80_A = IN(_BC); _F = (_F & CF) | z80->SZP[_Z80_A]; } /* IN E,(C) */ +OP(ed,79) { OUT(_BC,_Z80_A); } /* OUT (C),E */ +OP(ed,7a) { ADC16( SP ); } /* ADC HL,SP */ +OP(ed,7b) { z80->EA = ARG16(z80); RM16(z80, z80->EA, &z80->Z80.SP ); } /* LD SP,(w) */ +OP(ed,7c) { NEG; } /* NEG */ +OP(ed,7d) { RETI; } /* RETI */ +OP(ed,7e) { _IM = 2; } /* IM 2 */ +OP(ed,7f) { illegal_2(z80); } /* DB ED,7F */ + +OP(ed,80) { illegal_2(z80); } /* DB ED */ +OP(ed,81) { illegal_2(z80); } /* DB ED */ +OP(ed,82) { illegal_2(z80); } /* DB ED */ +OP(ed,83) { illegal_2(z80); } /* DB ED */ +OP(ed,84) { illegal_2(z80); } /* DB ED */ +OP(ed,85) { illegal_2(z80); } /* DB ED */ +OP(ed,86) { illegal_2(z80); } /* DB ED */ +OP(ed,87) { illegal_2(z80); } /* DB ED */ + +OP(ed,88) { illegal_2(z80); } /* DB ED */ +OP(ed,89) { illegal_2(z80); } /* DB ED */ +OP(ed,8a) { illegal_2(z80); } /* DB ED */ +OP(ed,8b) { illegal_2(z80); } /* DB ED */ +OP(ed,8c) { illegal_2(z80); } /* DB ED */ +OP(ed,8d) { illegal_2(z80); } /* DB ED */ +OP(ed,8e) { illegal_2(z80); } /* DB ED */ +OP(ed,8f) { illegal_2(z80); } /* DB ED */ + +OP(ed,90) { illegal_2(z80); } /* DB ED */ +OP(ed,91) { illegal_2(z80); } /* DB ED */ +OP(ed,92) { illegal_2(z80); } /* DB ED */ +OP(ed,93) { illegal_2(z80); } /* DB ED */ +OP(ed,94) { illegal_2(z80); } /* DB ED */ +OP(ed,95) { illegal_2(z80); } /* DB ED */ +OP(ed,96) { illegal_2(z80); } /* DB ED */ +OP(ed,97) { illegal_2(z80); } /* DB ED */ + +OP(ed,98) { illegal_2(z80); } /* DB ED */ +OP(ed,99) { illegal_2(z80); } /* DB ED */ +OP(ed,9a) { illegal_2(z80); } /* DB ED */ +OP(ed,9b) { illegal_2(z80); } /* DB ED */ +OP(ed,9c) { illegal_2(z80); } /* DB ED */ +OP(ed,9d) { illegal_2(z80); } /* DB ED */ +OP(ed,9e) { illegal_2(z80); } /* DB ED */ +OP(ed,9f) { illegal_2(z80); } /* DB ED */ + +OP(ed,a0) { LDI; } /* LDI */ +OP(ed,a1) { CPI; } /* CPI */ +OP(ed,a2) { INI; } /* INI */ +OP(ed,a3) { OUTI; } /* OUTI */ +OP(ed,a4) { illegal_2(z80); } /* DB ED */ +OP(ed,a5) { illegal_2(z80); } /* DB ED */ +OP(ed,a6) { illegal_2(z80); } /* DB ED */ +OP(ed,a7) { illegal_2(z80); } /* DB ED */ + +OP(ed,a8) { LDD; } /* LDD */ +OP(ed,a9) { CPD; } /* CPD */ +OP(ed,aa) { IND; } /* IND */ +OP(ed,ab) { OUTD; } /* OUTD */ +OP(ed,ac) { illegal_2(z80); } /* DB ED */ +OP(ed,ad) { illegal_2(z80); } /* DB ED */ +OP(ed,ae) { illegal_2(z80); } /* DB ED */ +OP(ed,af) { illegal_2(z80); } /* DB ED */ + +OP(ed,b0) { LDIR; } /* LDIR */ +OP(ed,b1) { CPIR; } /* CPIR */ +OP(ed,b2) { INIR; } /* INIR */ +OP(ed,b3) { OTIR; } /* OTIR */ +OP(ed,b4) { illegal_2(z80); } /* DB ED */ +OP(ed,b5) { illegal_2(z80); } /* DB ED */ +OP(ed,b6) { illegal_2(z80); } /* DB ED */ +OP(ed,b7) { illegal_2(z80); } /* DB ED */ + +OP(ed,b8) { LDDR; } /* LDDR */ +OP(ed,b9) { CPDR; } /* CPDR */ +OP(ed,ba) { INDR; } /* INDR */ +OP(ed,bb) { OTDR; } /* OTDR */ +OP(ed,bc) { illegal_2(z80); } /* DB ED */ +OP(ed,bd) { illegal_2(z80); } /* DB ED */ +OP(ed,be) { illegal_2(z80); } /* DB ED */ +OP(ed,bf) { illegal_2(z80); } /* DB ED */ + +OP(ed,c0) { illegal_2(z80); } /* DB ED */ +OP(ed,c1) { illegal_2(z80); } /* DB ED */ +OP(ed,c2) { illegal_2(z80); } /* DB ED */ +OP(ed,c3) { illegal_2(z80); } /* DB ED */ +OP(ed,c4) { illegal_2(z80); } /* DB ED */ +OP(ed,c5) { illegal_2(z80); } /* DB ED */ +OP(ed,c6) { illegal_2(z80); } /* DB ED */ +OP(ed,c7) { illegal_2(z80); } /* DB ED */ + +OP(ed,c8) { illegal_2(z80); } /* DB ED */ +OP(ed,c9) { illegal_2(z80); } /* DB ED */ +OP(ed,ca) { illegal_2(z80); } /* DB ED */ +OP(ed,cb) { illegal_2(z80); } /* DB ED */ +OP(ed,cc) { illegal_2(z80); } /* DB ED */ +OP(ed,cd) { illegal_2(z80); } /* DB ED */ +OP(ed,ce) { illegal_2(z80); } /* DB ED */ +OP(ed,cf) { illegal_2(z80); } /* DB ED */ + +OP(ed,d0) { illegal_2(z80); } /* DB ED */ +OP(ed,d1) { illegal_2(z80); } /* DB ED */ +OP(ed,d2) { illegal_2(z80); } /* DB ED */ +OP(ed,d3) { illegal_2(z80); } /* DB ED */ +OP(ed,d4) { illegal_2(z80); } /* DB ED */ +OP(ed,d5) { illegal_2(z80); } /* DB ED */ +OP(ed,d6) { illegal_2(z80); } /* DB ED */ +OP(ed,d7) { illegal_2(z80); } /* DB ED */ + +OP(ed,d8) { illegal_2(z80); } /* DB ED */ +OP(ed,d9) { illegal_2(z80); } /* DB ED */ +OP(ed,da) { illegal_2(z80); } /* DB ED */ +OP(ed,db) { illegal_2(z80); } /* DB ED */ +OP(ed,dc) { illegal_2(z80); } /* DB ED */ +OP(ed,dd) { illegal_2(z80); } /* DB ED */ +OP(ed,de) { illegal_2(z80); } /* DB ED */ +OP(ed,df) { illegal_2(z80); } /* DB ED */ + +OP(ed,e0) { illegal_2(z80); } /* DB ED */ +OP(ed,e1) { illegal_2(z80); } /* DB ED */ +OP(ed,e2) { illegal_2(z80); } /* DB ED */ +OP(ed,e3) { illegal_2(z80); } /* DB ED */ +OP(ed,e4) { illegal_2(z80); } /* DB ED */ +OP(ed,e5) { illegal_2(z80); } /* DB ED */ +OP(ed,e6) { illegal_2(z80); } /* DB ED */ +OP(ed,e7) { illegal_2(z80); } /* DB ED */ + +OP(ed,e8) { illegal_2(z80); } /* DB ED */ +OP(ed,e9) { illegal_2(z80); } /* DB ED */ +OP(ed,ea) { illegal_2(z80); } /* DB ED */ +OP(ed,eb) { illegal_2(z80); } /* DB ED */ +OP(ed,ec) { illegal_2(z80); } /* DB ED */ +OP(ed,ed) { illegal_2(z80); } /* DB ED */ +OP(ed,ee) { illegal_2(z80); } /* DB ED */ +OP(ed,ef) { illegal_2(z80); } /* DB ED */ + +OP(ed,f0) { illegal_2(z80); } /* DB ED */ +OP(ed,f1) { illegal_2(z80); } /* DB ED */ +OP(ed,f2) { illegal_2(z80); } /* DB ED */ +OP(ed,f3) { illegal_2(z80); } /* DB ED */ +OP(ed,f4) { illegal_2(z80); } /* DB ED */ +OP(ed,f5) { illegal_2(z80); } /* DB ED */ +OP(ed,f6) { illegal_2(z80); } /* DB ED */ +OP(ed,f7) { illegal_2(z80); } /* DB ED */ + +OP(ed,f8) { illegal_2(z80); } /* DB ED */ +OP(ed,f9) { illegal_2(z80); } /* DB ED */ +OP(ed,fa) { illegal_2(z80); } /* DB ED */ +OP(ed,fb) { illegal_2(z80); } /* DB ED */ +OP(ed,fc) { illegal_2(z80); } /* DB ED */ +OP(ed,fd) { illegal_2(z80); } /* DB ED */ +OP(ed,fe) { illegal_2(z80); } /* DB ED */ +OP(ed,ff) { illegal_2(z80); } /* DB ED */ + +#if TIME_LOOP_HACKS + +#define CHECK_BC_LOOP \ +if( _BC > 1 && _PCD < 0xfffc ) { \ + UINT8 op1 = cpu_readop(z80->userdata,_PCD); \ + UINT8 op2 = cpu_readop(z80->userdata,_PCD+1); \ + if( (op1==0x78 && op2==0xb1) || (op1==0x79 && op2==0xb0) ) \ + { \ + UINT8 op3 = cpu_readop(z80->userdata,_PCD+2); \ + UINT8 op4 = cpu_readop(z80->userdata,_PCD+3); \ + if( op3==0x20 && op4==0xfb ) \ + { \ + int cnt = \ + cc[Z80_TABLE_op][0x78] + \ + cc[Z80_TABLE_op][0xb1] + \ + cc[Z80_TABLE_op][0x20] + \ + cc[Z80_TABLE_ex][0x20]; \ + while( _BC > 0 && z80->z80_ICount > cnt ) \ + { \ + BURNODD( z80, cnt, 4, cnt ); \ + _BC--; \ + } \ + } \ + else \ + if( op3 == 0xc2 ) \ + { \ + UINT8 ad1 = cpu_readop_arg(z80->userdata,_PCD+3); \ + UINT8 ad2 = cpu_readop_arg(z80->userdata,_PCD+4); \ + if( (ad1 + 256 * ad2) == (_PCD - 1) ) \ + { \ + int cnt = \ + cc[Z80_TABLE_op][0x78] + \ + cc[Z80_TABLE_op][0xb1] + \ + cc[Z80_TABLE_op][0xc2] + \ + cc[Z80_TABLE_ex][0xc2]; \ + while( _BC > 0 && z80->z80_ICount > cnt ) \ + { \ + BURNODD( z80, cnt, 4, cnt ); \ + _BC--; \ + } \ + } \ + } \ + } \ +} + +#define CHECK_DE_LOOP \ +if( _DE > 1 && _PCD < 0xfffc ) { \ + UINT8 op1 = cpu_readop(z80->userdata,_PCD); \ + UINT8 op2 = cpu_readop(z80->userdata,_PCD+1); \ + if( (op1==0x7a && op2==0xb3) || (op1==0x7b && op2==0xb2) ) \ + { \ + UINT8 op3 = cpu_readop(z80->userdata,_PCD+2); \ + UINT8 op4 = cpu_readop(z80->userdata,_PCD+3); \ + if( op3==0x20 && op4==0xfb ) \ + { \ + int cnt = \ + cc[Z80_TABLE_op][0x7a] + \ + cc[Z80_TABLE_op][0xb3] + \ + cc[Z80_TABLE_op][0x20] + \ + cc[Z80_TABLE_ex][0x20]; \ + while( _DE > 0 && z80->z80_ICount > cnt ) \ + { \ + BURNODD( z80, cnt, 4, cnt ); \ + _DE--; \ + } \ + } \ + else \ + if( op3==0xc2 ) \ + { \ + UINT8 ad1 = cpu_readop_arg(z80->userdata,_PCD+3); \ + UINT8 ad2 = cpu_readop_arg(z80->userdata,_PCD+4); \ + if( (ad1 + 256 * ad2) == (_PCD - 1) ) \ + { \ + int cnt = \ + cc[Z80_TABLE_op][0x7a] + \ + cc[Z80_TABLE_op][0xb3] + \ + cc[Z80_TABLE_op][0xc2] + \ + cc[Z80_TABLE_ex][0xc2]; \ + while( _DE > 0 && z80->z80_ICount > cnt ) \ + { \ + BURNODD( z80, cnt, 4, cnt ); \ + _DE--; \ + } \ + } \ + } \ + } \ +} + +#define CHECK_HL_LOOP \ +if( _HL > 1 && _PCD < 0xfffc ) { \ + UINT8 op1 = cpu_readop(z80->userdata,_PCD); \ + UINT8 op2 = cpu_readop(z80->userdata,_PCD+1); \ + if( (op1==0x7c && op2==0xb5) || (op1==0x7d && op2==0xb4) ) \ + { \ + UINT8 op3 = cpu_readop(z80->userdata,_PCD+2); \ + UINT8 op4 = cpu_readop(z80->userdata,_PCD+3); \ + if( op3==0x20 && op4==0xfb ) \ + { \ + int cnt = \ + cc[Z80_TABLE_op][0x7c] + \ + cc[Z80_TABLE_op][0xb5] + \ + cc[Z80_TABLE_op][0x20] + \ + cc[Z80_TABLE_ex][0x20]; \ + while( _HL > 0 && z80->z80_ICount > cnt ) \ + { \ + BURNODD( z80, cnt, 4, cnt ); \ + _HL--; \ + } \ + } \ + else \ + if( op3==0xc2 ) \ + { \ + UINT8 ad1 = cpu_readop_arg(z80->userdata,_PCD+3); \ + UINT8 ad2 = cpu_readop_arg(z80->userdata,_PCD+4); \ + if( (ad1 + 256 * ad2) == (_PCD - 1) ) \ + { \ + int cnt = \ + cc[Z80_TABLE_op][0x7c] + \ + cc[Z80_TABLE_op][0xb5] + \ + cc[Z80_TABLE_op][0xc2] + \ + cc[Z80_TABLE_ex][0xc2]; \ + while( _HL > 0 && z80->z80_ICount > cnt ) \ + { \ + BURNODD( z80, cnt, 4, cnt ); \ + _HL--; \ + } \ + } \ + } \ + } \ +} + +#else + +#define CHECK_BC_LOOP +#define CHECK_DE_LOOP +#define CHECK_HL_LOOP + +#endif + +/********************************************************** + * main opcodes + **********************************************************/ +OP(op,00) { } /* NOP */ +OP(op,01) { _BC = ARG16(z80); } /* LD BC,w */ +OP(op,02) { WM( _BC, _Z80_A ); } /* LD (BC),A */ +OP(op,03) { _BC++; } /* INC BC */ +OP(op,04) { _Z80_B = INC(z80,_Z80_B); } /* INC B */ +OP(op,05) { _Z80_B = DEC(z80,_Z80_B); } /* DEC B */ +OP(op,06) { _Z80_B = ARG(z80); } /* LD B,n */ +OP(op,07) { RLCA; } /* RLCA */ + +OP(op,08) { EX_AF; } /* EX AF,AF' */ +OP(op,09) { ADD16(z80,HL,BC); } /* ADD HL,BC */ +OP(op,0a) { _Z80_A = RM(_BC); } /* LD A,(BC) */ +OP(op,0b) { _BC--; CHECK_BC_LOOP; } /* DEC BC */ +OP(op,0c) { _Z80_C = INC(z80,_Z80_C); } /* INC C */ +OP(op,0d) { _Z80_C = DEC(z80,_Z80_C); } /* DEC C */ +OP(op,0e) { _Z80_C = ARG(z80); } /* LD C,n */ +OP(op,0f) { RRCA; } /* RRCA */ + +OP(op,10) { _Z80_B--; JR_COND( _Z80_B, 0x10 ); } /* DJNZ o */ +OP(op,11) { _DE = ARG16(z80); } /* LD DE,w */ +OP(op,12) { WM( _DE, _Z80_A ); } /* LD (DE),A */ +OP(op,13) { _DE++; } /* INC DE */ +OP(op,14) { _Z80_D = INC(z80,_Z80_D); } /* INC D */ +OP(op,15) { _Z80_D = DEC(z80,_Z80_D); } /* DEC D */ +OP(op,16) { _Z80_D = ARG(z80); } /* LD D,n */ +OP(op,17) { RLA; } /* RLA */ + +OP(op,18) { JR(); } /* JR o */ +OP(op,19) { ADD16(z80,HL,DE); } /* ADD HL,DE */ +OP(op,1a) { _Z80_A = RM(_DE); } /* LD A,(DE) */ +OP(op,1b) { _DE--; CHECK_DE_LOOP; } /* DEC DE */ +OP(op,1c) { _Z80_E = INC(z80,_Z80_E); } /* INC E */ +OP(op,1d) { _Z80_E = DEC(z80,_Z80_E); } /* DEC E */ +OP(op,1e) { _Z80_E = ARG(z80); } /* LD E,n */ +OP(op,1f) { RRA; } /* RRA */ + +OP(op,20) { JR_COND( !(_F & ZF), 0x20 ); } /* JR NZ,o */ +OP(op,21) { _HL = ARG16(z80); } /* LD HL,w */ +OP(op,22) { z80->EA = ARG16(z80); WM16(z80, z80->EA, &z80->Z80.HL ); } /* LD (w),HL */ +OP(op,23) { _HL++; } /* INC HL */ +OP(op,24) { _Z80_H = INC(z80,_Z80_H); } /* INC H */ +OP(op,25) { _Z80_H = DEC(z80,_Z80_H); } /* DEC H */ +OP(op,26) { _Z80_H = ARG(z80); } /* LD H,n */ +OP(op,27) { DAA; } /* DAA */ + +OP(op,28) { JR_COND( _F & ZF, 0x28 ); } /* JR Z,o */ +OP(op,29) { ADD16(z80,HL,HL); } /* ADD HL,HL */ +OP(op,2a) { z80->EA = ARG16(z80); RM16(z80, z80->EA, &z80->Z80.HL ); } /* LD HL,(w) */ +OP(op,2b) { _HL--; CHECK_HL_LOOP; } /* DEC HL */ +OP(op,2c) { _Z80_L = INC(z80,_Z80_L); } /* INC L */ +OP(op,2d) { _Z80_L = DEC(z80,_Z80_L); } /* DEC L */ +OP(op,2e) { _Z80_L = ARG(z80); } /* LD L,n */ +OP(op,2f) { _Z80_A ^= 0xff; _F = (_F&(SF|ZF|PF|CF))|HF|NF|(_Z80_A&(YF|XF)); } /* CPL */ + +OP(op,30) { JR_COND( !(_F & CF), 0x30 ); } /* JR NC,o */ +OP(op,31) { _SP = ARG16(z80); } /* LD SP,w */ +OP(op,32) { z80->EA = ARG16(z80); WM( z80->EA, _Z80_A ); } /* LD (w),A */ +OP(op,33) { _SP++; } /* INC SP */ +OP(op,34) { WM( _HL, INC(z80,RM(_HL)) ); } /* INC (HL) */ +OP(op,35) { WM( _HL, DEC(z80,RM(_HL)) ); } /* DEC (HL) */ +OP(op,36) { WM( _HL, ARG(z80) ); } /* LD (HL),n */ +OP(op,37) { _F = (_F & (SF|ZF|PF)) | CF | (_Z80_A & (YF|XF)); } /* SCF */ + +OP(op,38) { JR_COND( _F & CF, 0x38 ); } /* JR C,o */ +OP(op,39) { ADD16(z80,HL,SP); } /* ADD HL,SP */ +OP(op,3a) { z80->EA = ARG16(z80); _Z80_A = RM( z80->EA ); } /* LD A,(w) */ +OP(op,3b) { _SP--; } /* DEC SP */ +OP(op,3c) { _Z80_A = INC(z80,_Z80_A); } /* INC A */ +OP(op,3d) { _Z80_A = DEC(z80,_Z80_A); } /* DEC A */ +OP(op,3e) { _Z80_A = ARG(z80); } /* LD A,n */ +OP(op,3f) { _F = ((_F&(SF|ZF|PF|CF))|((_F&CF)<<4)|(_Z80_A&(YF|XF)))^CF; } /* CCF */ +/*OP(op,3f) { _F = ((_F & ~(HF|NF)) | ((_F & CF)<<4)) ^ CF; } CCF */ + +OP(op,40) { } /* LD B,B */ +OP(op,41) { _Z80_B = _Z80_C; } /* LD B,C */ +OP(op,42) { _Z80_B = _Z80_D; } /* LD B,D */ +OP(op,43) { _Z80_B = _Z80_E; } /* LD B,E */ +OP(op,44) { _Z80_B = _Z80_H; } /* LD B,H */ +OP(op,45) { _Z80_B = _Z80_L; } /* LD B,L */ +OP(op,46) { _Z80_B = RM(_HL); } /* LD B,(HL) */ +OP(op,47) { _Z80_B = _Z80_A; } /* LD B,A */ + +OP(op,48) { _Z80_C = _Z80_B; } /* LD C,B */ +OP(op,49) { } /* LD C,C */ +OP(op,4a) { _Z80_C = _Z80_D; } /* LD C,D */ +OP(op,4b) { _Z80_C = _Z80_E; } /* LD C,E */ +OP(op,4c) { _Z80_C = _Z80_H; } /* LD C,H */ +OP(op,4d) { _Z80_C = _Z80_L; } /* LD C,L */ +OP(op,4e) { _Z80_C = RM(_HL); } /* LD C,(HL) */ +OP(op,4f) { _Z80_C = _Z80_A; } /* LD C,A */ + +OP(op,50) { _Z80_D = _Z80_B; } /* LD D,B */ +OP(op,51) { _Z80_D = _Z80_C; } /* LD D,C */ +OP(op,52) { } /* LD D,D */ +OP(op,53) { _Z80_D = _Z80_E; } /* LD D,E */ +OP(op,54) { _Z80_D = _Z80_H; } /* LD D,H */ +OP(op,55) { _Z80_D = _Z80_L; } /* LD D,L */ +OP(op,56) { _Z80_D = RM(_HL); } /* LD D,(HL) */ +OP(op,57) { _Z80_D = _Z80_A; } /* LD D,A */ + +OP(op,58) { _Z80_E = _Z80_B; } /* LD E,B */ +OP(op,59) { _Z80_E = _Z80_C; } /* LD E,C */ +OP(op,5a) { _Z80_E = _Z80_D; } /* LD E,D */ +OP(op,5b) { } /* LD E,E */ +OP(op,5c) { _Z80_E = _Z80_H; } /* LD E,H */ +OP(op,5d) { _Z80_E = _Z80_L; } /* LD E,L */ +OP(op,5e) { _Z80_E = RM(_HL); } /* LD E,(HL) */ +OP(op,5f) { _Z80_E = _Z80_A; } /* LD E,A */ + +OP(op,60) { _Z80_H = _Z80_B; } /* LD H,B */ +OP(op,61) { _Z80_H = _Z80_C; } /* LD H,C */ +OP(op,62) { _Z80_H = _Z80_D; } /* LD H,D */ +OP(op,63) { _Z80_H = _Z80_E; } /* LD H,E */ +OP(op,64) { } /* LD H,H */ +OP(op,65) { _Z80_H = _Z80_L; } /* LD H,L */ +OP(op,66) { _Z80_H = RM(_HL); } /* LD H,(HL) */ +OP(op,67) { _Z80_H = _Z80_A; } /* LD H,A */ + +OP(op,68) { _Z80_L = _Z80_B; } /* LD L,B */ +OP(op,69) { _Z80_L = _Z80_C; } /* LD L,C */ +OP(op,6a) { _Z80_L = _Z80_D; } /* LD L,D */ +OP(op,6b) { _Z80_L = _Z80_E; } /* LD L,E */ +OP(op,6c) { _Z80_L = _Z80_H; } /* LD L,H */ +OP(op,6d) { } /* LD L,L */ +OP(op,6e) { _Z80_L = RM(_HL); } /* LD L,(HL) */ +OP(op,6f) { _Z80_L = _Z80_A; } /* LD L,A */ + +OP(op,70) { WM( _HL, _Z80_B ); } /* LD (HL),B */ +OP(op,71) { WM( _HL, _Z80_C ); } /* LD (HL),C */ +OP(op,72) { WM( _HL, _Z80_D ); } /* LD (HL),D */ +OP(op,73) { WM( _HL, _Z80_E ); } /* LD (HL),E */ +OP(op,74) { WM( _HL, _Z80_H ); } /* LD (HL),H */ +OP(op,75) { WM( _HL, _Z80_L ); } /* LD (HL),L */ +OP(op,76) { ENTER_HALT; } /* HALT */ +OP(op,77) { WM( _HL, _Z80_A ); } /* LD (HL),A */ + +OP(op,78) { _Z80_A = _Z80_B; } /* LD A,B */ +OP(op,79) { _Z80_A = _Z80_C; } /* LD A,C */ +OP(op,7a) { _Z80_A = _Z80_D; } /* LD A,D */ +OP(op,7b) { _Z80_A = _Z80_E; } /* LD A,E */ +OP(op,7c) { _Z80_A = _Z80_H; } /* LD A,H */ +OP(op,7d) { _Z80_A = _Z80_L; } /* LD A,L */ +OP(op,7e) { _Z80_A = RM(_HL); } /* LD A,(HL) */ +OP(op,7f) { } /* LD A,A */ + +OP(op,80) { ADD(z80,_Z80_B); } /* ADD A,B */ +OP(op,81) { ADD(z80,_Z80_C); } /* ADD A,C */ +OP(op,82) { ADD(z80,_Z80_D); } /* ADD A,D */ +OP(op,83) { ADD(z80,_Z80_E); } /* ADD A,E */ +OP(op,84) { ADD(z80,_Z80_H); } /* ADD A,H */ +OP(op,85) { ADD(z80,_Z80_L); } /* ADD A,L */ +OP(op,86) { ADD(z80,RM(_HL)); } /* ADD A,(HL) */ +OP(op,87) { ADD(z80,_Z80_A); } /* ADD A,A */ + +OP(op,88) { ADC(_Z80_B); } /* ADC A,B */ +OP(op,89) { ADC(_Z80_C); } /* ADC A,C */ +OP(op,8a) { ADC(_Z80_D); } /* ADC A,D */ +OP(op,8b) { ADC(_Z80_E); } /* ADC A,E */ +OP(op,8c) { ADC(_Z80_H); } /* ADC A,H */ +OP(op,8d) { ADC(_Z80_L); } /* ADC A,L */ +OP(op,8e) { ADC(RM(_HL)); } /* ADC A,(HL) */ +OP(op,8f) { ADC(_Z80_A); } /* ADC A,A */ + +OP(op,90) { SUB(_Z80_B); } /* SUB B */ +OP(op,91) { SUB(_Z80_C); } /* SUB C */ +OP(op,92) { SUB(_Z80_D); } /* SUB D */ +OP(op,93) { SUB(_Z80_E); } /* SUB E */ +OP(op,94) { SUB(_Z80_H); } /* SUB H */ +OP(op,95) { SUB(_Z80_L); } /* SUB L */ +OP(op,96) { SUB(RM(_HL)); } /* SUB (HL) */ +OP(op,97) { SUB(_Z80_A); } /* SUB A */ + +OP(op,98) { SBC(_Z80_B); } /* SBC A,B */ +OP(op,99) { SBC(_Z80_C); } /* SBC A,C */ +OP(op,9a) { SBC(_Z80_D); } /* SBC A,D */ +OP(op,9b) { SBC(_Z80_E); } /* SBC A,E */ +OP(op,9c) { SBC(_Z80_H); } /* SBC A,H */ +OP(op,9d) { SBC(_Z80_L); } /* SBC A,L */ +OP(op,9e) { SBC(RM(_HL)); } /* SBC A,(HL) */ +OP(op,9f) { SBC(_Z80_A); } /* SBC A,A */ + +OP(op,a0) { AND(_Z80_B); } /* AND B */ +OP(op,a1) { AND(_Z80_C); } /* AND C */ +OP(op,a2) { AND(_Z80_D); } /* AND D */ +OP(op,a3) { AND(_Z80_E); } /* AND E */ +OP(op,a4) { AND(_Z80_H); } /* AND H */ +OP(op,a5) { AND(_Z80_L); } /* AND L */ +OP(op,a6) { AND(RM(_HL)); } /* AND (HL) */ +OP(op,a7) { AND(_Z80_A); } /* AND A */ + +OP(op,a8) { XOR(_Z80_B); } /* XOR B */ +OP(op,a9) { XOR(_Z80_C); } /* XOR C */ +OP(op,aa) { XOR(_Z80_D); } /* XOR D */ +OP(op,ab) { XOR(_Z80_E); } /* XOR E */ +OP(op,ac) { XOR(_Z80_H); } /* XOR H */ +OP(op,ad) { XOR(_Z80_L); } /* XOR L */ +OP(op,ae) { XOR(RM(_HL)); } /* XOR (HL) */ +OP(op,af) { XOR(_Z80_A); } /* XOR A */ + +OP(op,b0) { OR(_Z80_B); } /* OR B */ +OP(op,b1) { OR(_Z80_C); } /* OR C */ +OP(op,b2) { OR(_Z80_D); } /* OR D */ +OP(op,b3) { OR(_Z80_E); } /* OR E */ +OP(op,b4) { OR(_Z80_H); } /* OR H */ +OP(op,b5) { OR(_Z80_L); } /* OR L */ +OP(op,b6) { OR(RM(_HL)); } /* OR (HL) */ +OP(op,b7) { OR(_Z80_A); } /* OR A */ + +OP(op,b8) { CP(_Z80_B); } /* CP B */ +OP(op,b9) { CP(_Z80_C); } /* CP C */ +OP(op,ba) { CP(_Z80_D); } /* CP D */ +OP(op,bb) { CP(_Z80_E); } /* CP E */ +OP(op,bc) { CP(_Z80_H); } /* CP H */ +OP(op,bd) { CP(_Z80_L); } /* CP L */ +OP(op,be) { CP(RM(_HL)); } /* CP (HL) */ +OP(op,bf) { CP(_Z80_A); } /* CP A */ + +OP(op,c0) { RET_COND( !(_F & ZF), 0xc0 ); } /* RET NZ */ +OP(op,c1) { POP(BC); } /* POP BC */ +OP(op,c2) { JP_COND( !(_F & ZF) ); } /* JP NZ,a */ +OP(op,c3) { JP; } /* JP a */ +OP(op,c4) { CALL_COND( !(_F & ZF), 0xc4 ); } /* CALL NZ,a */ +OP(op,c5) { PUSH( BC ); } /* PUSH BC */ +OP(op,c6) { ADD(z80,ARG(z80)); } /* ADD A,n */ +OP(op,c7) { RST(0x00); } /* RST 0 */ + +OP(op,c8) { RET_COND( _F & ZF, 0xc8 ); } /* RET Z */ +OP(op,c9) { POP(PC); change_pc16(_PCD); } /* RET */ +OP(op,ca) { JP_COND( _F & ZF ); } /* JP Z,a */ +OP(op,cb) { _Z80_R++; EXEC(cb,ROP(z80)); } /* **** CB xx */ +OP(op,cc) { CALL_COND( _F & ZF, 0xcc ); } /* CALL Z,a */ +OP(op,cd) { CALL(); } /* CALL a */ +OP(op,ce) { ADC(ARG(z80)); } /* ADC A,n */ +OP(op,cf) { RST(0x08); } /* RST 1 */ + +OP(op,d0) { RET_COND( !(_F & CF), 0xd0 ); } /* RET NC */ +OP(op,d1) { POP(DE); } /* POP DE */ +OP(op,d2) { JP_COND( !(_F & CF) ); } /* JP NC,a */ +OP(op,d3) { unsigned n = ARG(z80) | (_Z80_A << 8); OUT( n, _Z80_A ); } /* OUT (n),A */ +OP(op,d4) { CALL_COND( !(_F & CF), 0xd4 ); } /* CALL NC,a */ +OP(op,d5) { PUSH( DE ); } /* PUSH DE */ +OP(op,d6) { SUB(ARG(z80)); } /* SUB n */ +OP(op,d7) { RST(0x10); } /* RST 2 */ + +OP(op,d8) { RET_COND( _F & CF, 0xd8 ); } /* RET C */ +OP(op,d9) { EXX; } /* EXX */ +OP(op,da) { JP_COND( _F & CF ); } /* JP C,a */ +OP(op,db) { unsigned n = ARG(z80) | (_Z80_A << 8); _Z80_A = IN( n ); } /* IN A,(n) */ +OP(op,dc) { CALL_COND( _F & CF, 0xdc ); } /* CALL C,a */ +OP(op,dd) { _Z80_R++; EXEC(dd,ROP(z80)); } /* **** DD xx */ +OP(op,de) { SBC(ARG(z80)); } /* SBC A,n */ +OP(op,df) { RST(0x18); } /* RST 3 */ + +OP(op,e0) { RET_COND( !(_F & PF), 0xe0 ); } /* RET PO */ +OP(op,e1) { POP(HL); } /* POP HL */ +OP(op,e2) { JP_COND( !(_F & PF) ); } /* JP PO,a */ +OP(op,e3) { EXSP(HL); } /* EX HL,(SP) */ +OP(op,e4) { CALL_COND( !(_F & PF), 0xe4 ); } /* CALL PO,a */ +OP(op,e5) { PUSH( HL ); } /* PUSH HL */ +OP(op,e6) { AND(ARG(z80)); } /* AND n */ +OP(op,e7) { RST(0x20); } /* RST 4 */ + +OP(op,e8) { RET_COND( _F & PF, 0xe8 ); } /* RET PE */ +OP(op,e9) { _PC = _HL; change_pc16(_PCD); } /* JP (HL) */ +OP(op,ea) { JP_COND( _F & PF ); } /* JP PE,a */ +OP(op,eb) { EX_DE_HL; } /* EX DE,HL */ +OP(op,ec) { CALL_COND( _F & PF, 0xec ); } /* CALL PE,a */ +OP(op,ed) { _Z80_R++; EXEC(ed,ROP(z80)); } /* **** ED xx */ +OP(op,ee) { XOR(ARG(z80)); } /* XOR n */ +OP(op,ef) { RST(0x28); } /* RST 5 */ + +OP(op,f0) { RET_COND( !(_F & SF), 0xf0 ); } /* RET P */ +OP(op,f1) { POP(AF); } /* POP AF */ +OP(op,f2) { JP_COND( !(_F & SF) ); } /* JP P,a */ +OP(op,f3) { _IFF1 = _IFF2 = 0; } /* DI */ +OP(op,f4) { CALL_COND( !(_F & SF), 0xf4 ); } /* CALL P,a */ +OP(op,f5) { PUSH( AF ); } /* PUSH AF */ +OP(op,f6) { OR(ARG(z80)); } /* OR n */ +OP(op,f7) { RST(0x30); } /* RST 6 */ + +OP(op,f8) { RET_COND( _F & SF, 0xf8 ); } /* RET M */ +OP(op,f9) { _SP = _HL; } /* LD SP,HL */ +OP(op,fa) { JP_COND(_F & SF); } /* JP M,a */ +OP(op,fb) { EI; } /* EI */ +OP(op,fc) { CALL_COND( _F & SF, 0xfc ); } /* CALL M,a */ +OP(op,fd) { _Z80_R++; EXEC(fd,ROP(z80)); } /* **** FD xx */ +OP(op,fe) { CP(ARG(z80)); } /* CP n */ +OP(op,ff) { RST(0x38); } /* RST 7 */ + + +static void take_interrupt(z80_state_t *z80) +{ + if( _IFF1 ) + { + int irq_vector; + + /* there isn't a valid previous program counter */ + _PPC = -1; + + /* Check if processor was halted */ + LEAVE_HALT; + + if( z80->Z80.irq_max ) /* daisy chain mode */ + { + if( z80->Z80.request_irq >= 0 ) + { + /* Clear both interrupt flip flops */ + _IFF1 = _IFF2 = 0; + irq_vector = z80->Z80.irq[z80->Z80.request_irq].interrupt_entry(z80->Z80.irq[z80->Z80.request_irq].irq_param); + LOG(("Z80 #%d daisy chain irq_vector $%02x\n", cpu_getactivecpu(), irq_vector)); + z80->Z80.request_irq = -1; + } else return; + } + else + { + /* Clear both interrupt flip flops */ + _IFF1 = _IFF2 = 0; + /* call back the cpu interface to retrieve the vector */ + irq_vector = (*z80->Z80.irq_callback)(0); + LOG(("Z80 #%d single int. irq_vector $%02x\n", cpu_getactivecpu(), irq_vector)); + } + + /* Interrupt mode 2. Call [z80->Z80.I:databyte] */ + if( _IM == 2 ) + { + irq_vector = (irq_vector & 0xff) | (_Z80_I << 8); + PUSH( PC ); + RM16(z80, irq_vector, &z80->Z80.PC ); + LOG(("Z80 #%d IM2 [$%04x] = $%04x\n",cpu_getactivecpu() , irq_vector, _PCD)); + /* CALL opcode timing */ + z80->Z80.extra_cycles += cc[Z80_TABLE_op][0xcd]; + } + else + /* Interrupt mode 1. RST 38h */ + if( _IM == 1 ) + { + LOG(("Z80 #%d IM1 $0038\n",cpu_getactivecpu() )); + PUSH( PC ); + _PCD = 0x0038; + /* RST $38 + 'interrupt latency' cycles */ + z80->Z80.extra_cycles += cc[Z80_TABLE_op][0xff] + cc[Z80_TABLE_ex][0xff]; + } + else + { + /* Interrupt mode 0. We check for CALL and JP instructions, */ + /* if neither of these were found we assume a 1 byte opcode */ + /* was placed on the databus */ + LOG(("Z80 #%d IM0 $%04x\n",cpu_getactivecpu() , irq_vector)); + switch (irq_vector & 0xff0000) + { + case 0xcd0000: /* call */ + PUSH( PC ); + _PCD = irq_vector & 0xffff; + /* CALL $xxxx + 'interrupt latency' cycles */ + z80->Z80.extra_cycles += cc[Z80_TABLE_op][0xcd] + cc[Z80_TABLE_ex][0xff]; + break; + case 0xc30000: /* jump */ + _PCD = irq_vector & 0xffff; + /* JP $xxxx + 2 cycles */ + z80->Z80.extra_cycles += cc[Z80_TABLE_op][0xc3] + cc[Z80_TABLE_ex][0xff]; + break; + default: /* rst (or other opcodes?) */ + PUSH( PC ); + _PCD = irq_vector & 0x0038; + /* RST $xx + 2 cycles */ + z80->Z80.extra_cycles += cc[Z80_TABLE_op][_PCD] + cc[Z80_TABLE_ex][_PCD]; + break; + } + } + change_pc16(_PCD); + } +} + +/**************************************************************************** + * Processor initialization + ****************************************************************************/ +z80_state_t *z80_init(void) +{ +// int cpu = 0;//cpu_getactivecpu(); + int i, p; + z80_state_t *z80 = malloc (sizeof (z80_state_t)); + memset (z80, 0, sizeof (z80_state_t)); +#if BIG_FLAGS_ARRAY + if( !z80->SZHVC_add || !z80->SZHVC_sub ) + { + int oldval, newval, val; + UINT8 *padd, *padc, *psub, *psbc; + /* allocate big flag arrays once */ + z80->SZHVC_add = (UINT8 *)malloc(2*256*256); + z80->SZHVC_sub = (UINT8 *)malloc(2*256*256); + if( !z80->SZHVC_add || !z80->SZHVC_sub ) + { + LOG(("Z80: failed to allocate 2 * 128K flags arrays!!!\n")); + exit(1); + } + padd = &z80->SZHVC_add[ 0*256]; + padc = &z80->SZHVC_add[256*256]; + psub = &z80->SZHVC_sub[ 0*256]; + psbc = &z80->SZHVC_sub[256*256]; + for (oldval = 0; oldval < 256; oldval++) + { + for (newval = 0; newval < 256; newval++) + { + /* add or adc w/o carry set */ + val = newval - oldval; + *padd = (newval) ? ((newval & 0x80) ? SF : 0) : ZF; +#if Z80_EXACT + *padd |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */ +#endif + if( (newval & 0x0f) < (oldval & 0x0f) ) *padd |= HF; + if( newval < oldval ) *padd |= CF; + if( (val^oldval^0x80) & (val^newval) & 0x80 ) *padd |= VF; + padd++; + + /* adc with carry set */ + val = newval - oldval - 1; + *padc = (newval) ? ((newval & 0x80) ? SF : 0) : ZF; +#if Z80_EXACT + *padc |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */ +#endif + if( (newval & 0x0f) <= (oldval & 0x0f) ) *padc |= HF; + if( newval <= oldval ) *padc |= CF; + if( (val^oldval^0x80) & (val^newval) & 0x80 ) *padc |= VF; + padc++; + + /* cp, sub or sbc w/o carry set */ + val = oldval - newval; + *psub = NF | ((newval) ? ((newval & 0x80) ? SF : 0) : ZF); +#if Z80_EXACT + *psub |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */ +#endif + if( (newval & 0x0f) > (oldval & 0x0f) ) *psub |= HF; + if( newval > oldval ) *psub |= CF; + if( (val^oldval) & (oldval^newval) & 0x80 ) *psub |= VF; + psub++; + + /* sbc with carry set */ + val = oldval - newval - 1; + *psbc = NF | ((newval) ? ((newval & 0x80) ? SF : 0) : ZF); +#if Z80_EXACT + *psbc |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */ +#endif + if( (newval & 0x0f) >= (oldval & 0x0f) ) *psbc |= HF; + if( newval >= oldval ) *psbc |= CF; + if( (val^oldval) & (oldval^newval) & 0x80 ) *psbc |= VF; + psbc++; + } + } + } +#endif + for (i = 0; i < 256; i++) + { + p = 0; + if( i&0x01 ) ++p; + if( i&0x02 ) ++p; + if( i&0x04 ) ++p; + if( i&0x08 ) ++p; + if( i&0x10 ) ++p; + if( i&0x20 ) ++p; + if( i&0x40 ) ++p; + if( i&0x80 ) ++p; + z80->SZ[i] = i ? i & SF : ZF; +#if Z80_EXACT + z80->SZ[i] |= (i & (YF | XF)); /* undocumented flag bits 5+3 */ +#endif + z80->SZ_BIT[i] = i ? i & SF : ZF | PF; +#if Z80_EXACT + z80->SZ_BIT[i] |= (i & (YF | XF)); /* undocumented flag bits 5+3 */ +#endif + z80->SZP[i] = z80->SZ[i] | ((p & 1) ? 0 : PF); + z80->SZHV_inc[i] = z80->SZ[i]; + if( i == 0x80 ) z80->SZHV_inc[i] |= VF; + if( (i & 0x0f) == 0x00 ) z80->SZHV_inc[i] |= HF; + z80->SZHV_dec[i] = z80->SZ[i] | NF; + if( i == 0x7f ) z80->SZHV_dec[i] |= VF; + if( (i & 0x0f) == 0x0f ) z80->SZHV_dec[i] |= HF; + } + +/* + state_save_register_UINT16("z80", cpu, "AF", &z80->Z80.AF.w.l, 1); + state_save_register_UINT16("z80", cpu, "BC", &z80->Z80.BC.w.l, 1); + state_save_register_UINT16("z80", cpu, "DE", &z80->Z80.DE.w.l, 1); + state_save_register_UINT16("z80", cpu, "HL", &z80->Z80.HL.w.l, 1); + state_save_register_UINT16("z80", cpu, "IX", &z80->Z80.IX.w.l, 1); + state_save_register_UINT16("z80", cpu, "IY", &z80->Z80.IY.w.l, 1); + state_save_register_UINT16("z80", cpu, "PC", &z80->Z80.PC.w.l, 1); + state_save_register_UINT16("z80", cpu, "SP", &z80->Z80.SP.w.l, 1); + state_save_register_UINT16("z80", cpu, "AF2", &z80->Z80.AF2.w.l, 1); + state_save_register_UINT16("z80", cpu, "BC2", &z80->Z80.BC2.w.l, 1); + state_save_register_UINT16("z80", cpu, "DE2", &z80->Z80.DE2.w.l, 1); + state_save_register_UINT16("z80", cpu, "HL2", &z80->Z80.HL2.w.l, 1); + state_save_register_UINT8("z80", cpu, "R", &z80->Z80.R, 1); + state_save_register_UINT8("z80", cpu, "R2", &z80->Z80.R2, 1); + state_save_register_UINT8("z80", cpu, "IFF1", &z80->Z80.IFF1, 1); + state_save_register_UINT8("z80", cpu, "IFF2", &z80->Z80.IFF2, 1); + state_save_register_UINT8("z80", cpu, "HALT", &z80->Z80.HALT, 1); + state_save_register_UINT8("z80", cpu, "IM", &z80->Z80.IM, 1); + state_save_register_UINT8("z80", cpu, "I", &z80->Z80.I, 1); + state_save_register_UINT8("z80", cpu, "irq_max", &z80->Z80.irq_max, 1); + state_save_register_INT8("z80", cpu, "request_irq", &z80->Z80.request_irq, 1); + state_save_register_INT8("z80", cpu, "service_irq", &z80->Z80.service_irq, 1); + state_save_register_UINT8("z80", cpu, "int_state", z80->Z80.int_state, 4); + state_save_register_UINT8("z80", cpu, "nmi_state", &z80->Z80.nmi_state, 1); + state_save_register_UINT8("z80", cpu, "irq_state", &z80->Z80.irq_state, 1); +*/ + /* daisy chain needs to be saved by z80ctc.c somehow */ + + return z80; +} + +void z80_free (z80_state_t *z80) { + if (z80) { + if( z80->SZHVC_add) { + free (z80->SZHVC_add); + } + if (z80->SZHVC_sub) { + free (z80->SZHVC_sub); + } + free (z80); + } +} + +/**************************************************************************** + * Reset registers to their initial values + ****************************************************************************/ +void z80_reset(z80_state_t *z80, void *param) +{ + Z80_DaisyChain *daisy_chain = (Z80_DaisyChain *)param; + memset(&z80->Z80, 0, sizeof(z80->Z80)); + _IX = _IY = 0xffff; /* IX and IY are FFFF after a reset! */ + _F = ZF; /* Zero flag is set */ + z80->Z80.request_irq = -1; + z80->Z80.service_irq = -1; + z80->Z80.nmi_state = CLEAR_LINE; + z80->Z80.irq_state = CLEAR_LINE; + + if( daisy_chain ) + { + while( daisy_chain->irq_param != -1 && z80->Z80.irq_max < Z80_MAXDAISY ) + { + /* set callbackhandler after reti */ + z80->Z80.irq[z80->Z80.irq_max] = *daisy_chain; + /* device reset */ + if( z80->Z80.irq[z80->Z80.irq_max].reset ) + z80->Z80.irq[z80->Z80.irq_max].reset(z80->Z80.irq[z80->Z80.irq_max].irq_param); + z80->Z80.irq_max++; + daisy_chain++; + } + } + + change_pc16(_PCD); +} + +void z80_exit(z80_state_t *z80) +{ +#if BIG_FLAGS_ARRAY + if (z80->SZHVC_add) free(z80->SZHVC_add); + z80->SZHVC_add = NULL; + if (z80->SZHVC_sub) free(z80->SZHVC_sub); + z80->SZHVC_sub = NULL; +#endif +} + +/**************************************************************************** + * Execute 'cycles' T-states. Return number of T-states really executed + ****************************************************************************/ +int z80_execute(z80_state_t *z80, int cycles) +{ + z80->z80_ICount = cycles - z80->Z80.extra_cycles; + z80->Z80.extra_cycles = 0; + + do + { + _PPC = _PCD; + CALL_MAME_DEBUG; + _Z80_R++; + EXEC_INLINE(op,ROP(z80)); + } while( z80->z80_ICount > 0 ); + + z80->z80_ICount -= z80->Z80.extra_cycles; + z80->Z80.extra_cycles = 0; + + return cycles - z80->z80_ICount; +} + +/**************************************************************************** + * Burn 'cycles' T-states. Adjust R register for the lost time + ****************************************************************************/ +void z80_burn(z80_state_t *z80, int cycles) +{ + if( cycles > 0 ) + { + /* NOP takes 4 cycles per instruction */ + int n = (cycles + 3) / 4; + _Z80_R += n; + z80->z80_ICount -= 4 * n; + } +} + +/**************************************************************************** + * Get all registers in given buffer + ****************************************************************************/ +unsigned z80_get_context (z80_state_t *z80, void *dst) +{ + if( dst ) + *(Z80_Regs*)dst = z80->Z80; + return sizeof(Z80_Regs); +} + +/**************************************************************************** + * Set all registers to given values + ****************************************************************************/ +void z80_set_context (z80_state_t *z80, void *src) +{ + if( src ) + z80->Z80 = *(Z80_Regs*)src; + change_pc16(_PCD); +} + +/**************************************************************************** + * Get a pointer to a cycle count table + ****************************************************************************/ +const void *z80_get_cycle_table (z80_state_t *z80, int which) +{ + if (which >= 0 && which <= Z80_TABLE_xycb) + return cc[which]; + return NULL; +} + +/**************************************************************************** + * Set a new cycle count table + ****************************************************************************/ +void z80_set_cycle_table (z80_state_t *z80, int which, void *new_table) +{ + if (which >= 0 && which <= Z80_TABLE_ex) + cc[which] = new_table; +} + +/**************************************************************************** + * Return a specific register + ****************************************************************************/ +unsigned z80_get_reg (z80_state_t *z80, int regnum) +{ + switch( regnum ) + { + //case REG_PC: return _PCD; + case Z80_PC: return z80->Z80.PC.w.l; + //case REG_SP: return _SPD; + case Z80_SP: return z80->Z80.SP.w.l; + case Z80_AF: return z80->Z80.AF.w.l; + case Z80_BC: return z80->Z80.BC.w.l; + case Z80_DE: return z80->Z80.DE.w.l; + case Z80_HL: return z80->Z80.HL.w.l; + case Z80_IX: return z80->Z80.IX.w.l; + case Z80_IY: return z80->Z80.IY.w.l; + case Z80_R: return (z80->Z80.R & 0x7f) | (z80->Z80.R2 & 0x80); + case Z80_I: return z80->Z80.I; + case Z80_AF2: return z80->Z80.AF2.w.l; + case Z80_BC2: return z80->Z80.BC2.w.l; + case Z80_DE2: return z80->Z80.DE2.w.l; + case Z80_HL2: return z80->Z80.HL2.w.l; + case Z80_IM: return z80->Z80.IM; + case Z80_IFF1: return z80->Z80.IFF1; + case Z80_IFF2: return z80->Z80.IFF2; + case Z80_HALT: return z80->Z80.HALT; + case Z80_NMI_STATE: return z80->Z80.nmi_state; + case Z80_IRQ_STATE: return z80->Z80.irq_state; + case Z80_DC0: return z80->Z80.int_state[0]; + case Z80_DC1: return z80->Z80.int_state[1]; + case Z80_DC2: return z80->Z80.int_state[2]; + case Z80_DC3: return z80->Z80.int_state[3]; + case REG_PREVIOUSPC: return z80->Z80.PREPC.w.l; + default: + if( regnum <= REG_SP_CONTENTS ) + { + unsigned offset = _SPD + 2 * (REG_SP_CONTENTS - regnum); + if( offset < 0xffff ) + return RM( offset ) | ( RM( offset + 1) << 8 ); + } + } + return 0; +} + +/**************************************************************************** + * Set a specific register + ****************************************************************************/ +void z80_set_reg (z80_state_t *z80, int regnum, unsigned val) +{ + switch( regnum ) + { + //case REG_PC: _PC = val; change_pc16(_PCD); break; + case Z80_PC: z80->Z80.PC.w.l = val; break; + //case REG_SP: _SP = val; break; + case Z80_SP: z80->Z80.SP.w.l = val; break; + case Z80_AF: z80->Z80.AF.w.l = val; break; + case Z80_BC: z80->Z80.BC.w.l = val; break; + case Z80_DE: z80->Z80.DE.w.l = val; break; + case Z80_HL: z80->Z80.HL.w.l = val; break; + case Z80_IX: z80->Z80.IX.w.l = val; break; + case Z80_IY: z80->Z80.IY.w.l = val; break; + case Z80_R: z80->Z80.R = val; z80->Z80.R2 = val & 0x80; break; + case Z80_I: z80->Z80.I = val; break; + case Z80_AF2: z80->Z80.AF2.w.l = val; break; + case Z80_BC2: z80->Z80.BC2.w.l = val; break; + case Z80_DE2: z80->Z80.DE2.w.l = val; break; + case Z80_HL2: z80->Z80.HL2.w.l = val; break; + case Z80_IM: z80->Z80.IM = val; break; + case Z80_IFF1: z80->Z80.IFF1 = val; break; + case Z80_IFF2: z80->Z80.IFF2 = val; break; + case Z80_HALT: z80->Z80.HALT = val; break; + case Z80_NMI_STATE: z80_set_irq_line(z80,IRQ_LINE_NMI,val); break; + case Z80_IRQ_STATE: z80_set_irq_line(z80,0,val); break; + case Z80_DC0: z80->Z80.int_state[0] = val; break; + case Z80_DC1: z80->Z80.int_state[1] = val; break; + case Z80_DC2: z80->Z80.int_state[2] = val; break; + case Z80_DC3: z80->Z80.int_state[3] = val; break; + default: + if( regnum <= REG_SP_CONTENTS ) + { + unsigned offset = _SPD + 2 * (REG_SP_CONTENTS - regnum); + if( offset < 0xffff ) + { + WM( offset, val & 0xff ); + WM( offset+1, (val >> 8) & 0xff ); + } + } + } +} + +/**************************************************************************** + * Set IRQ line state + ****************************************************************************/ +void z80_set_irq_line(z80_state_t *z80, int irqline, int state) +{ + if (irqline == IRQ_LINE_NMI) + { + if( z80->Z80.nmi_state == state ) return; + + LOG(("Z80 #%d set_irq_line (NMI) %d\n", cpu_getactivecpu(), state)); + z80->Z80.nmi_state = state; + if( state == CLEAR_LINE ) return; + + LOG(("Z80 #%d take NMI\n", cpu_getactivecpu())); + _PPC = -1; /* there isn't a valid previous program counter */ + LEAVE_HALT; /* Check if processor was halted */ + + _IFF1 = 0; + PUSH( PC ); + _PCD = 0x0066; + z80->Z80.extra_cycles += 11; + } + else + { + LOG(("Z80 #%d set_irq_line %d\n",cpu_getactivecpu() , state)); + z80->Z80.irq_state = state; + if( state == CLEAR_LINE ) return; + + if( z80->Z80.irq_max ) + { + int daisychain, device, int_state; + daisychain = (*z80->Z80.irq_callback)(irqline); + device = daisychain >> 8; + int_state = daisychain & 0xff; + LOG(("Z80 #%d daisy chain $%04x -> device %d, state $%02x",cpu_getactivecpu(), daisychain, device, int_state)); + + if( z80->Z80.int_state[device] != int_state ) + { + LOG((" change\n")); + /* set new interrupt status */ + z80->Z80.int_state[device] = int_state; + /* check interrupt status */ + z80->Z80.request_irq = z80->Z80.service_irq = -1; + + /* search higher IRQ or IEO */ + for( device = 0 ; device < z80->Z80.irq_max ; device ++ ) + { + /* IEO = disable ? */ + if( z80->Z80.int_state[device] & Z80_INT_IEO ) + { + z80->Z80.request_irq = -1; /* if IEO is disable , masking lower IRQ */ + z80->Z80.service_irq = device; /* set highest interrupt service device */ + } + /* IRQ = request ? */ + if( z80->Z80.int_state[device] & Z80_INT_REQ ) + z80->Z80.request_irq = device; + } + LOG(("Z80 #%d daisy chain service_irq $%02x, request_irq $%02x\n", cpu_getactivecpu(), z80->Z80.service_irq, z80->Z80.request_irq)); + if( z80->Z80.request_irq < 0 ) return; + } + else + { + LOG((" no change\n")); + return; + } + } + take_interrupt(z80); + } +} + +/**************************************************************************** + * Set IRQ vector callback + ****************************************************************************/ +void z80_set_irq_callback(z80_state_t *z80, int (*callback)(int)) +{ + LOG(("Z80 #%d set_irq_callback $%08x\n",cpu_getactivecpu() , (int)callback)); + z80->Z80.irq_callback = callback; +} + +/**************************************************************************** + * Return a formatted string for a register + ****************************************************************************/ +const char *z80_info(z80_state_t *z80, void *context, int regnum) +{ + static char buffer[32][47+1]; + static int which = 0; + Z80_Regs *r = context; + + which = (which+1) % 32; + buffer[which][0] = '\0'; + if( !context ) + r = &z80->Z80; + + switch( regnum ) + { + case CPU_INFO_REG+Z80_PC: sprintf(buffer[which], "PC:%04X", r->PC.w.l); break; + case CPU_INFO_REG+Z80_SP: sprintf(buffer[which], "SP:%04X", r->SP.w.l); break; + case CPU_INFO_REG+Z80_AF: sprintf(buffer[which], "AF:%04X", r->AF.w.l); break; + case CPU_INFO_REG+Z80_BC: sprintf(buffer[which], "BC:%04X", r->BC.w.l); break; + case CPU_INFO_REG+Z80_DE: sprintf(buffer[which], "DE:%04X", r->DE.w.l); break; + case CPU_INFO_REG+Z80_HL: sprintf(buffer[which], "HL:%04X", r->HL.w.l); break; + case CPU_INFO_REG+Z80_IX: sprintf(buffer[which], "IX:%04X", r->IX.w.l); break; + case CPU_INFO_REG+Z80_IY: sprintf(buffer[which], "IY:%04X", r->IY.w.l); break; + case CPU_INFO_REG+Z80_R: sprintf(buffer[which], "R:%02X", (r->R & 0x7f) | (r->R2 & 0x80)); break; + case CPU_INFO_REG+Z80_I: sprintf(buffer[which], "I:%02X", r->I); break; + case CPU_INFO_REG+Z80_AF2: sprintf(buffer[which], "AF'%04X", r->AF2.w.l); break; + case CPU_INFO_REG+Z80_BC2: sprintf(buffer[which], "BC'%04X", r->BC2.w.l); break; + case CPU_INFO_REG+Z80_DE2: sprintf(buffer[which], "DE'%04X", r->DE2.w.l); break; + case CPU_INFO_REG+Z80_HL2: sprintf(buffer[which], "HL'%04X", r->HL2.w.l); break; + case CPU_INFO_REG+Z80_IM: sprintf(buffer[which], "IM:%X", r->IM); break; + case CPU_INFO_REG+Z80_IFF1: sprintf(buffer[which], "IFF1:%X", r->IFF1); break; + case CPU_INFO_REG+Z80_IFF2: sprintf(buffer[which], "IFF2:%X", r->IFF2); break; + case CPU_INFO_REG+Z80_HALT: sprintf(buffer[which], "HALT:%X", r->HALT); break; + case CPU_INFO_REG+Z80_NMI_STATE: sprintf(buffer[which], "NMI:%X", r->nmi_state); break; + case CPU_INFO_REG+Z80_IRQ_STATE: sprintf(buffer[which], "IRQ:%X", r->irq_state); break; + case CPU_INFO_REG+Z80_DC0: if(z80->Z80.irq_max >= 1) sprintf(buffer[which], "DC0:%X", r->int_state[0]); break; + case CPU_INFO_REG+Z80_DC1: if(z80->Z80.irq_max >= 2) sprintf(buffer[which], "DC1:%X", r->int_state[1]); break; + case CPU_INFO_REG+Z80_DC2: if(z80->Z80.irq_max >= 3) sprintf(buffer[which], "DC2:%X", r->int_state[2]); break; + case CPU_INFO_REG+Z80_DC3: if(z80->Z80.irq_max >= 4) sprintf(buffer[which], "DC3:%X", r->int_state[3]); break; + case CPU_INFO_FLAGS: + sprintf(buffer[which], "%c%c%c%c%c%c%c%c", + r->AF.b.l & 0x80 ? 'S':'.', + r->AF.b.l & 0x40 ? 'Z':'.', + r->AF.b.l & 0x20 ? '5':'.', + r->AF.b.l & 0x10 ? 'H':'.', + r->AF.b.l & 0x08 ? '3':'.', + r->AF.b.l & 0x04 ? 'P':'.', + r->AF.b.l & 0x02 ? 'N':'.', + r->AF.b.l & 0x01 ? 'C':'.'); + break; + case CPU_INFO_NAME: return "Z80"; + case CPU_INFO_FAMILY: return "Zilog Z80"; + case CPU_INFO_VERSION: return "3.5"; + case CPU_INFO_FILE: return __FILE__; + case CPU_INFO_CREDITS: return "Copyright (C) 1998,1999,2000 Juergen Buchmueller, all rights reserved."; + case CPU_INFO_REG_LAYOUT: return (const char *)z80_reg_layout; + case CPU_INFO_WIN_LAYOUT: return (const char *)z80_win_layout; + } + return buffer[which]; +} + +unsigned z80_dasm( z80_state_t *z80, char *buffer, unsigned pc ) +{ +#ifdef MAME_DEBUG + return DasmZ80( buffer, pc ); +#else + sprintf( buffer, "$%02X", cpu_readop(z80->userdata,pc) ); + return 1; +#endif +} + diff --git a/plugins/ao/eng_qsf/z80.h b/plugins/ao/eng_qsf/z80.h new file mode 100644 index 00000000..17808cfc --- /dev/null +++ b/plugins/ao/eng_qsf/z80.h @@ -0,0 +1,117 @@ +#ifndef Z80_H
+#define Z80_H
+
+#include "cpuintrf.h"
+#include "osd_cpu.h"
+
+#undef VERBOSE
+#define VERBOSE 0
+
+#if VERBOSE
+#define LOG(x) logerror x
+#else
+#define LOG(x)
+#endif
+
+/* execute main opcodes inside a big switch statement */
+#ifndef BIG_SWITCH
+#define BIG_SWITCH 1
+#endif
+
+/* big flags array for ADD/ADC/SUB/SBC/CP results */
+#define BIG_FLAGS_ARRAY 1
+
+/* Set to 1 for a more exact (but somewhat slower) Z80 emulation */
+#define Z80_EXACT 1
+
+/* on JP and JR opcodes check for tight loops */
+#define BUSY_LOOP_HACKS 1
+
+/* check for delay loops counting down BC */
+#define TIME_LOOP_HACKS 1
+
+#ifdef X86_ASM
+#undef BIG_FLAGS_ARRAY
+#define BIG_FLAGS_ARRAY 0
+#endif
+
+enum {
+ Z80_PC=1, Z80_SP, Z80_AF, Z80_BC, Z80_DE, Z80_HL,
+ Z80_IX, Z80_IY, Z80_AF2, Z80_BC2, Z80_DE2, Z80_HL2,
+ Z80_R, Z80_I, Z80_IM, Z80_IFF1, Z80_IFF2, Z80_HALT,
+ Z80_NMI_STATE, Z80_IRQ_STATE, Z80_DC0, Z80_DC1, Z80_DC2, Z80_DC3
+};
+
+enum {
+ Z80_TABLE_op,
+ Z80_TABLE_cb,
+ Z80_TABLE_ed,
+ Z80_TABLE_xy,
+ Z80_TABLE_xycb,
+ Z80_TABLE_ex /* cycles counts for taken jr/jp/call and interrupt latency (rst opcodes) */
+};
+
+/****************************************************************************/
+/* The Z80 registers. HALT is set to 1 when the CPU is halted, the refresh */
+/* register is calculated as follows: refresh=(Regs.R&127)|(Regs.R2&128) */
+/****************************************************************************/
+typedef struct {
+/* 00 */ PAIR PREPC,PC,SP,AF,BC,DE,HL,IX,IY;
+/* 24 */ PAIR AF2,BC2,DE2,HL2;
+/* 34 */ UINT8 R,R2,IFF1,IFF2,HALT,IM,I;
+/* 3B */ UINT8 irq_max; /* number of daisy chain devices */
+/* 3C */ INT8 request_irq; /* daisy chain next request device */
+/* 3D */ INT8 service_irq; /* daisy chain next reti handling device */
+/* 3E */ UINT8 nmi_state; /* nmi line state */
+/* 3F */ UINT8 irq_state; /* irq line state */
+/* 40 */ UINT8 int_state[Z80_MAXDAISY];
+/* 44 */ Z80_DaisyChain irq[Z80_MAXDAISY];
+/* 84 */ int (*irq_callback)(int irqline);
+/* 88 */ int extra_cycles; /* extra cycles for interrupts */
+} Z80_Regs;
+
+
+typedef struct {
+ int z80_ICount; /* T-state count */
+ Z80_Regs Z80;
+ UINT32 EA;
+ int after_EI;
+
+ UINT8 SZ[256]; /* zero and sign flags */
+ UINT8 SZ_BIT[256]; /* zero, sign and parity/overflow (=zero) flags for BIT opcode */
+ UINT8 SZP[256]; /* zero, sign and parity flags */
+ UINT8 SZHV_inc[256]; /* zero, sign, half carry and overflow flags INC r8 */
+ UINT8 SZHV_dec[256]; /* zero, sign, half carry and overflow flags DEC r8 */
+
+#if BIG_FLAGS_ARRAY
+ UINT8 *SZHVC_add;
+ UINT8 *SZHVC_sub;
+#endif
+
+ void *userdata;
+} z80_state_t;
+
+z80_state_t *z80_init(void);
+void z80_free (z80_state_t *z80);
+void z80_reset (z80_state_t *z80, void *param);
+void z80_exit (z80_state_t *z80);
+int z80_execute(z80_state_t *z80, int cycles);
+void z80_burn(z80_state_t *z80, int cycles);
+unsigned z80_get_context (z80_state_t *z80, void *dst);
+void z80_set_context (z80_state_t *z80, void *src);
+const void *z80_get_cycle_table (z80_state_t *z80, int which);
+void z80_set_cycle_table (z80_state_t *z80, int which, void *new_tbl);
+unsigned z80_get_reg (z80_state_t *z80, int regnum);
+void z80_set_reg (z80_state_t *z80, int regnum, unsigned val);
+void z80_set_irq_line(z80_state_t *z80, int irqline, int state);
+void z80_set_irq_callback(z80_state_t *z80, int (*irq_callback)(int));
+const char *z80_info(z80_state_t *z80, void *context, int regnum);
+unsigned z80_dasm(z80_state_t *z80, char *buffer, unsigned pc);
+
+#ifdef MAME_DEBUG
+unsigned DasmZ80(z80_state_t *z80, char *buffer, unsigned pc);
+#endif
+
+void cps1_decode(unsigned char *rom, int swap_key1,int swap_key2,int addr_key,int xor_key);
+#endif
+
diff --git a/plugins/ao/eng_qsf/z80dasm.c b/plugins/ao/eng_qsf/z80dasm.c new file mode 100644 index 00000000..29cbb769 --- /dev/null +++ b/plugins/ao/eng_qsf/z80dasm.c @@ -0,0 +1,597 @@ +/***************************************************************************** + * + * z80dasm.c + * Portable Z80 disassembler + * + * Copyright (C) 1998 Juergen Buchmueller, all rights reserved. + * + * - This source code is released as freeware for non-commercial purposes. + * - You are free to use and redistribute this code in modified or + * unmodified form, provided you list me in the credits. + * - If you modify this source code, you must add a notice to each modified + * source file that it has been changed. If you're a nice person, you + * will clearly mark each change too. :) + * - If you wish to use this for commercial purposes, please contact me at + * pullmoll@t-online.de + * - The author of this copywritten work reserves the right to change the + * terms of its usage and license at any time, including retroactively + * - This entire notice must remain in the source code. + * + *****************************************************************************/ + +#include <stdio.h> +#include <string.h> +#ifdef MAME_DEBUG +#include "driver.h" +#include "mamedbg.h" +#include "z80.h" + +enum e_mnemonics { + zADC ,zADD ,zAND ,zBIT ,zCALL ,zCCF ,zCP ,zCPD , + zCPDR ,zCPI ,zCPIR ,zCPL ,zDAA ,zDB ,zDEC ,zDI , + zDJNZ ,zEI ,zEX ,zEXX ,zHLT ,zIM ,zIN ,zINC , + zIND ,zINDR ,zINI ,zINIR ,zJP ,zJR ,zLD ,zLDD , + zLDDR ,zLDI ,zLDIR ,zNEG ,zNOP ,zOR ,zOTDR ,zOTIR , + zOUT ,zOUTD ,zOUTI ,zPOP ,zPUSH ,zRES ,zRET ,zRETI , + zRETN ,zRL ,zRLA ,zRLC ,zRLCA ,zRLD ,zRR ,zRRA , + zRRC ,zRRCA ,zRRD ,zRST ,zSBC ,zSCF ,zSET ,zSLA , + zSLL ,zSRA ,zSRL ,zSUB ,zXOR +}; + +static const char *s_mnemonic[] = { + "adc", "add", "and", "bit", "call","ccf", "cp", "cpd", + "cpdr","cpi", "cpir","cpl", "daa", "db", "dec", "di", + "djnz","ei", "ex", "exx", "halt","im", "in", "inc", + "ind", "indr","ini", "inir","jp", "jr", "ld", "ldd", + "lddr","ldi", "ldir","neg", "nop", "or", "otdr","otir", + "out", "outd","outi","pop", "push","res", "ret", "reti", + "retn","rl", "rla", "rlc", "rlca","rld", "rr", "rra", + "rrc", "rrca","rrd", "rst", "sbc", "scf", "set", "sla", + "sll", "sra", "srl", "sub", "xor " +}; + +typedef struct { + UINT8 access; + UINT8 mnemonic; + const char *arguments; +} z80dasm; + +#define _0 EA_NONE +#define _JP EA_ABS_PC +#define _JR EA_REL_PC +#define _RM EA_MEM_RD +#define _WM EA_MEM_WR +#define _RW EA_MEM_RDWR +#define _RP EA_PORT_RD +#define _WP EA_PORT_WR + +static z80dasm mnemonic_xx_cb[256]= { + {_RW,zRLC,"b=Y"}, {_RW,zRLC,"c=Y"}, {_RW,zRLC,"d=Y"}, {_RW,zRLC,"e=Y"}, + {_RW,zRLC,"h=Y"}, {_RW,zRLC,"l=Y"}, {_RW,zRLC,"Y"}, {_RW,zRLC,"a=Y"}, + {_RW,zRRC,"b=Y"}, {_RW,zRRC,"c=Y"}, {_RW,zRRC,"d=Y"}, {_RW,zRRC,"e=Y"}, + {_RW,zRRC,"h=Y"}, {_RW,zRRC,"l=Y"}, {_RW,zRRC,"Y"}, {_RW,zRRC,"a=Y"}, + {_RW,zRL,"b=Y"}, {_RW,zRL,"c=Y"}, {_RW,zRL,"d=Y"}, {_RW,zRL,"e=Y"}, + {_RW,zRL,"h=Y"}, {_RW,zRL,"l=Y"}, {_RW,zRL,"Y"}, {_RW,zRL,"a=Y"}, + {_RW,zRR,"b=Y"}, {_RW,zRR,"c=Y"}, {_RW,zRR,"d=Y"}, {_RW,zRR,"e=Y"}, + {_RW,zRR,"h=Y"}, {_RW,zRR,"l=Y"}, {_RW,zRR,"Y"}, {_RW,zRR,"a=Y"}, + {_RW,zSLA,"b=Y"}, {_RW,zSLA,"c=Y"}, {_RW,zSLA,"d=Y"}, {_RW,zSLA,"e=Y"}, + {_RW,zSLA,"h=Y"}, {_RW,zSLA,"l=Y"}, {_RW,zSLA,"Y"}, {_RW,zSLA,"a=Y"}, + {_RW,zSRA,"b=Y"}, {_RW,zSRA,"c=Y"}, {_RW,zSRA,"d=Y"}, {_RW,zSRA,"e=Y"}, + {_RW,zSRA,"h=Y"}, {_RW,zSRA,"l=Y"}, {_RW,zSRA,"Y"}, {_RW,zSRA,"a=Y"}, + {_RW,zSLL,"b=Y"}, {_RW,zSLL,"c=Y"}, {_RW,zSLL,"d=Y"}, {_RW,zSLL,"e=Y"}, + {_RW,zSLL,"h=Y"}, {_RW,zSLL,"l=Y"}, {_RW,zSLL,"Y"}, {_RW,zSLL,"a=Y"}, + {_RW,zSRL,"b=Y"}, {_RW,zSRL,"c=Y"}, {_RW,zSRL,"d=Y"}, {_RW,zSRL,"e=Y"}, + {_RW,zSRL,"h=Y"}, {_RW,zSRL,"l=Y"}, {_RW,zSRL,"Y"}, {_RW,zSRL,"a=Y"}, + {_RM,zBIT,"b=0,Y"}, {_RM,zBIT,"c=0,Y"}, {_RM,zBIT,"d=0,Y"}, {_RM,zBIT,"e=0,Y"}, + {_RM,zBIT,"h=0,Y"}, {_RM,zBIT,"l=0,Y"}, {_RM,zBIT,"0,Y"}, {_RM,zBIT,"a=0,Y"}, + {_RM,zBIT,"b=1,Y"}, {_RM,zBIT,"c=1,Y"}, {_RM,zBIT,"d=1,Y"}, {_RM,zBIT,"e=1,Y"}, + {_RM,zBIT,"h=1,Y"}, {_RM,zBIT,"l=1,Y"}, {_RM,zBIT,"1,Y"}, {_RM,zBIT,"a=1,Y"}, + {_RM,zBIT,"b=2,Y"}, {_RM,zBIT,"c=2,Y"}, {_RM,zBIT,"d=2,Y"}, {_RM,zBIT,"e=2,Y"}, + {_RM,zBIT,"h=2,Y"}, {_RM,zBIT,"l=2,Y"}, {_RM,zBIT,"2,Y"}, {_RM,zBIT,"a=2,Y"}, + {_RM,zBIT,"b=3,Y"}, {_RM,zBIT,"c=3,Y"}, {_RM,zBIT,"d=3,Y"}, {_RM,zBIT,"e=3,Y"}, + {_RM,zBIT,"h=3,Y"}, {_RM,zBIT,"l=3,Y"}, {_RM,zBIT,"3,Y"}, {_RM,zBIT,"a=3,Y"}, + {_RM,zBIT,"b=4,Y"}, {_RM,zBIT,"c=4,Y"}, {_RM,zBIT,"d=4,Y"}, {_RM,zBIT,"e=4,Y"}, + {_RM,zBIT,"h=4,Y"}, {_RM,zBIT,"l=4,Y"}, {_RM,zBIT,"4,Y"}, {_RM,zBIT,"a=4,Y"}, + {_RM,zBIT,"b=5,Y"}, {_RM,zBIT,"c=5,Y"}, {_RM,zBIT,"d=5,Y"}, {_RM,zBIT,"e=5,Y"}, + {_RM,zBIT,"h=5,Y"}, {_RM,zBIT,"l=5,Y"}, {_RM,zBIT,"5,Y"}, {_RM,zBIT,"a=5,Y"}, + {_RM,zBIT,"b=6,Y"}, {_RM,zBIT,"c=6,Y"}, {_RM,zBIT,"d=6,Y"}, {_RM,zBIT,"e=6,Y"}, + {_RM,zBIT,"h=6,Y"}, {_RM,zBIT,"l=6,Y"}, {_RM,zBIT,"6,Y"}, {_RM,zBIT,"a=6,Y"}, + {_RM,zBIT,"b=7,Y"}, {_RM,zBIT,"c=7,Y"}, {_RM,zBIT,"d=7,Y"}, {_RM,zBIT,"e=7,Y"}, + {_RM,zBIT,"h=7,Y"}, {_RM,zBIT,"l=7,Y"}, {_RM,zBIT,"7,Y"}, {_RM,zBIT,"a=7,Y"}, + {_WM,zRES,"b=0,Y"}, {_WM,zRES,"c=0,Y"}, {_WM,zRES,"d=0,Y"}, {_WM,zRES,"e=0,Y"}, + {_WM,zRES,"h=0,Y"}, {_WM,zRES,"l=0,Y"}, {_WM,zRES,"0,Y"}, {_WM,zRES,"a=0,Y"}, + {_WM,zRES,"b=1,Y"}, {_WM,zRES,"c=1,Y"}, {_WM,zRES,"d=1,Y"}, {_WM,zRES,"e=1,Y"}, + {_WM,zRES,"h=1,Y"}, {_WM,zRES,"l=1,Y"}, {_WM,zRES,"1,Y"}, {_WM,zRES,"a=1,Y"}, + {_WM,zRES,"b=2,Y"}, {_WM,zRES,"c=2,Y"}, {_WM,zRES,"d=2,Y"}, {_WM,zRES,"e=2,Y"}, + {_WM,zRES,"h=2,Y"}, {_WM,zRES,"l=2,Y"}, {_WM,zRES,"2,Y"}, {_WM,zRES,"a=2,Y"}, + {_WM,zRES,"b=3,Y"}, {_WM,zRES,"c=3,Y"}, {_WM,zRES,"d=3,Y"}, {_WM,zRES,"e=3,Y"}, + {_WM,zRES,"h=3,Y"}, {_WM,zRES,"l=3,Y"}, {_WM,zRES,"3,Y"}, {_WM,zRES,"a=3,Y"}, + {_WM,zRES,"b=4,Y"}, {_WM,zRES,"c=4,Y"}, {_WM,zRES,"d=4,Y"}, {_WM,zRES,"e=4,Y"}, + {_WM,zRES,"h=4,Y"}, {_WM,zRES,"l=4,Y"}, {_WM,zRES,"4,Y"}, {_WM,zRES,"a=4,Y"}, + {_WM,zRES,"b=5,Y"}, {_WM,zRES,"c=5,Y"}, {_WM,zRES,"d=5,Y"}, {_WM,zRES,"e=5,Y"}, + {_WM,zRES,"h=5,Y"}, {_WM,zRES,"l=5,Y"}, {_WM,zRES,"5,Y"}, {_WM,zRES,"a=5,Y"}, + {_WM,zRES,"b=6,Y"}, {_WM,zRES,"c=6,Y"}, {_WM,zRES,"d=6,Y"}, {_WM,zRES,"e=6,Y"}, + {_WM,zRES,"h=6,Y"}, {_WM,zRES,"l=6,Y"}, {_WM,zRES,"6,Y"}, {_WM,zRES,"a=6,Y"}, + {_WM,zRES,"b=7,Y"}, {_WM,zRES,"c=7,Y"}, {_WM,zRES,"d=7,Y"}, {_WM,zRES,"e=7,Y"}, + {_WM,zRES,"h=7,Y"}, {_WM,zRES,"l=7,Y"}, {_WM,zRES,"7,Y"}, {_WM,zRES,"a=7,Y"}, + {_WM,zSET,"b=0,Y"}, {_WM,zSET,"c=0,Y"}, {_WM,zSET,"d=0,Y"}, {_WM,zSET,"e=0,Y"}, + {_WM,zSET,"h=0,Y"}, {_WM,zSET,"l=0,Y"}, {_WM,zSET,"0,Y"}, {_WM,zSET,"a=0,Y"}, + {_WM,zSET,"b=1,Y"}, {_WM,zSET,"c=1,Y"}, {_WM,zSET,"d=1,Y"}, {_WM,zSET,"e=1,Y"}, + {_WM,zSET,"h=1,Y"}, {_WM,zSET,"l=1,Y"}, {_WM,zSET,"1,Y"}, {_WM,zSET,"a=1,Y"}, + {_WM,zSET,"b=2,Y"}, {_WM,zSET,"c=2,Y"}, {_WM,zSET,"d=2,Y"}, {_WM,zSET,"e=2,Y"}, + {_WM,zSET,"h=2,Y"}, {_WM,zSET,"l=2,Y"}, {_WM,zSET,"2,Y"}, {_WM,zSET,"a=2,Y"}, + {_WM,zSET,"b=3,Y"}, {_WM,zSET,"c=3,Y"}, {_WM,zSET,"d=3,Y"}, {_WM,zSET,"e=3,Y"}, + {_WM,zSET,"h=3,Y"}, {_WM,zSET,"l=3,Y"}, {_WM,zSET,"3,Y"}, {_WM,zSET,"a=3,Y"}, + {_WM,zSET,"b=4,Y"}, {_WM,zSET,"c=4,Y"}, {_WM,zSET,"d=4,Y"}, {_WM,zSET,"e=4,Y"}, + {_WM,zSET,"h=4,Y"}, {_WM,zSET,"l=4,Y"}, {_WM,zSET,"4,Y"}, {_WM,zSET,"a=4,Y"}, + {_WM,zSET,"b=5,Y"}, {_WM,zSET,"c=5,Y"}, {_WM,zSET,"d=5,Y"}, {_WM,zSET,"e=5,Y"}, + {_WM,zSET,"h=5,Y"}, {_WM,zSET,"l=5,Y"}, {_WM,zSET,"5,Y"}, {_WM,zSET,"a=5,Y"}, + {_WM,zSET,"b=6,Y"}, {_WM,zSET,"c=6,Y"}, {_WM,zSET,"d=6,Y"}, {_WM,zSET,"e=6,Y"}, + {_WM,zSET,"h=6,Y"}, {_WM,zSET,"l=6,Y"}, {_WM,zSET,"6,Y"}, {_WM,zSET,"a=6,Y"}, + {_WM,zSET,"b=7,Y"}, {_WM,zSET,"c=7,Y"}, {_WM,zSET,"d=7,Y"}, {_WM,zSET,"e=7,Y"}, + {_WM,zSET,"h=7,Y"}, {_WM,zSET,"l=7,Y"}, {_WM,zSET,"7,Y"}, {_WM,zSET,"a=7,Y"} +}; + +static z80dasm mnemonic_cb[256] = { + {_0, zRLC,"b"}, {_0, zRLC,"c"}, {_0, zRLC,"d"}, {_0, zRLC,"e"}, + {_0, zRLC,"h"}, {_0, zRLC,"l"}, {_RW,zRLC,"(hl)"}, {_0, zRLC,"a"}, + {_0, zRRC,"b"}, {_0, zRRC,"c"}, {_0, zRRC,"d"}, {_0, zRRC,"e"}, + {_0, zRRC,"h"}, {_0, zRRC,"l"}, {_RW,zRRC,"(hl)"}, {_0, zRRC,"a"}, + {_0, zRL,"b"}, {_0, zRL,"c"}, {_0, zRL,"d"}, {_0, zRL,"e"}, + {_0, zRL,"h"}, {_0, zRL,"l"}, {_RW,zRL,"(hl)"}, {_0, zRL,"a"}, + {_0, zRR,"b"}, {_0, zRR,"c"}, {_0, zRR,"d"}, {_0, zRR,"e"}, + {_0, zRR,"h"}, {_0, zRR,"l"}, {_RW,zRR,"(hl)"}, {_0, zRR,"a"}, + {_0, zSLA,"b"}, {_0, zSLA,"c"}, {_0, zSLA,"d"}, {_0, zSLA,"e"}, + {_0, zSLA,"h"}, {_0, zSLA,"l"}, {_RW,zSLA,"(hl)"}, {_0, zSLA,"a"}, + {_0, zSRA,"b"}, {_0, zSRA,"c"}, {_0, zSRA,"d"}, {_0, zSRA,"e"}, + {_0, zSRA,"h"}, {_0, zSRA,"l"}, {_RW,zSRA,"(hl)"}, {_0, zSRA,"a"}, + {_0, zSLL,"b"}, {_0, zSLL,"c"}, {_0, zSLL,"d"}, {_0, zSLL,"e"}, + {_0, zSLL,"h"}, {_0, zSLL,"l"}, {_RW,zSLL,"(hl)"}, {_0, zSLL,"a"}, + {_0, zSRL,"b"}, {_0, zSRL,"c"}, {_0, zSRL,"d"}, {_0, zSRL,"e"}, + {_0, zSRL,"h"}, {_0, zSRL,"l"}, {_RW,zSRL,"(hl)"}, {_0, zSRL,"a"}, + {_0, zBIT,"0,b"}, {_0, zBIT,"0,c"}, {_0, zBIT,"0,d"}, {_0, zBIT,"0,e"}, + {_0, zBIT,"0,h"}, {_0, zBIT,"0,l"}, {_RM,zBIT,"0,(hl)"},{_0, zBIT,"0,a"}, + {_0, zBIT,"1,b"}, {_0, zBIT,"1,c"}, {_0, zBIT,"1,d"}, {_0, zBIT,"1,e"}, + {_0, zBIT,"1,h"}, {_0, zBIT,"1,l"}, {_RM,zBIT,"1,(hl)"},{_0, zBIT,"1,a"}, + {_0, zBIT,"2,b"}, {_0, zBIT,"2,c"}, {_0, zBIT,"2,d"}, {_0, zBIT,"2,e"}, + {_0, zBIT,"2,h"}, {_0, zBIT,"2,l"}, {_RM,zBIT,"2,(hl)"},{_0, zBIT,"2,a"}, + {_0, zBIT,"3,b"}, {_0, zBIT,"3,c"}, {_0, zBIT,"3,d"}, {_0, zBIT,"3,e"}, + {_0, zBIT,"3,h"}, {_0, zBIT,"3,l"}, {_RM,zBIT,"3,(hl)"},{_0, zBIT,"3,a"}, + {_0, zBIT,"4,b"}, {_0, zBIT,"4,c"}, {_0, zBIT,"4,d"}, {_0, zBIT,"4,e"}, + {_0, zBIT,"4,h"}, {_0, zBIT,"4,l"}, {_RM,zBIT,"4,(hl)"},{_0, zBIT,"4,a"}, + {_0, zBIT,"5,b"}, {_0, zBIT,"5,c"}, {_0, zBIT,"5,d"}, {_0, zBIT,"5,e"}, + {_0, zBIT,"5,h"}, {_0, zBIT,"5,l"}, {_RM,zBIT,"5,(hl)"},{_0, zBIT,"5,a"}, + {_0, zBIT,"6,b"}, {_0, zBIT,"6,c"}, {_0, zBIT,"6,d"}, {_0, zBIT,"6,e"}, + {_0, zBIT,"6,h"}, {_0, zBIT,"6,l"}, {_RM,zBIT,"6,(hl)"},{_0, zBIT,"6,a"}, + {_0, zBIT,"7,b"}, {_0, zBIT,"7,c"}, {_0, zBIT,"7,d"}, {_0, zBIT,"7,e"}, + {_0, zBIT,"7,h"}, {_0, zBIT,"7,l"}, {_RM,zBIT,"7,(hl)"},{_0, zBIT,"7,a"}, + {_0, zRES,"0,b"}, {_0, zRES,"0,c"}, {_0, zRES,"0,d"}, {_0, zRES,"0,e"}, + {_0, zRES,"0,h"}, {_0, zRES,"0,l"}, {_WM,zRES,"0,(hl)"},{_0, zRES,"0,a"}, + {_0, zRES,"1,b"}, {_0, zRES,"1,c"}, {_0, zRES,"1,d"}, {_0, zRES,"1,e"}, + {_0, zRES,"1,h"}, {_0, zRES,"1,l"}, {_WM,zRES,"1,(hl)"},{_0, zRES,"1,a"}, + {_0, zRES,"2,b"}, {_0, zRES,"2,c"}, {_0, zRES,"2,d"}, {_0, zRES,"2,e"}, + {_0, zRES,"2,h"}, {_0, zRES,"2,l"}, {_WM,zRES,"2,(hl)"},{_0, zRES,"2,a"}, + {_0, zRES,"3,b"}, {_0, zRES,"3,c"}, {_0, zRES,"3,d"}, {_0, zRES,"3,e"}, + {_0, zRES,"3,h"}, {_0, zRES,"3,l"}, {_WM,zRES,"3,(hl)"},{_0, zRES,"3,a"}, + {_0, zRES,"4,b"}, {_0, zRES,"4,c"}, {_0, zRES,"4,d"}, {_0, zRES,"4,e"}, + {_0, zRES,"4,h"}, {_0, zRES,"4,l"}, {_WM,zRES,"4,(hl)"},{_0, zRES,"4,a"}, + {_0, zRES,"5,b"}, {_0, zRES,"5,c"}, {_0, zRES,"5,d"}, {_0, zRES,"5,e"}, + {_0, zRES,"5,h"}, {_0, zRES,"5,l"}, {_WM,zRES,"5,(hl)"},{_0, zRES,"5,a"}, + {_0, zRES,"6,b"}, {_0, zRES,"6,c"}, {_0, zRES,"6,d"}, {_0, zRES,"6,e"}, + {_0, zRES,"6,h"}, {_0, zRES,"6,l"}, {_WM,zRES,"6,(hl)"},{_0, zRES,"6,a"}, + {_0, zRES,"7,b"}, {_0, zRES,"7,c"}, {_0, zRES,"7,d"}, {_0, zRES,"7,e"}, + {_0, zRES,"7,h"}, {_0, zRES,"7,l"}, {_WM,zRES,"7,(hl)"},{_0, zRES,"7,a"}, + {_0, zSET,"0,b"}, {_0, zSET,"0,c"}, {_0, zSET,"0,d"}, {_0, zSET,"0,e"}, + {_0, zSET,"0,h"}, {_0, zSET,"0,l"}, {_WM,zSET,"0,(hl)"},{_0, zSET,"0,a"}, + {_0, zSET,"1,b"}, {_0, zSET,"1,c"}, {_0, zSET,"1,d"}, {_0, zSET,"1,e"}, + {_0, zSET,"1,h"}, {_0, zSET,"1,l"}, {_WM,zSET,"1,(hl)"},{_0, zSET,"1,a"}, + {_0, zSET,"2,b"}, {_0, zSET,"2,c"}, {_0, zSET,"2,d"}, {_0, zSET,"2,e"}, + {_0, zSET,"2,h"}, {_0, zSET,"2,l"}, {_WM,zSET,"2,(hl)"},{_0, zSET,"2,a"}, + {_0, zSET,"3,b"}, {_0, zSET,"3,c"}, {_0, zSET,"3,d"}, {_0, zSET,"3,e"}, + {_0, zSET,"3,h"}, {_0, zSET,"3,l"}, {_WM,zSET,"3,(hl)"},{_0, zSET,"3,a"}, + {_0, zSET,"4,b"}, {_0, zSET,"4,c"}, {_0, zSET,"4,d"}, {_0, zSET,"4,e"}, + {_0, zSET,"4,h"}, {_0, zSET,"4,l"}, {_WM,zSET,"4,(hl)"},{_0, zSET,"4,a"}, + {_0, zSET,"5,b"}, {_0, zSET,"5,c"}, {_0, zSET,"5,d"}, {_0, zSET,"5,e"}, + {_0, zSET,"5,h"}, {_0, zSET,"5,l"}, {_WM,zSET,"5,(hl)"},{_0, zSET,"5,a"}, + {_0, zSET,"6,b"}, {_0, zSET,"6,c"}, {_0, zSET,"6,d"}, {_0, zSET,"6,e"}, + {_0, zSET,"6,h"}, {_0, zSET,"6,l"}, {_WM,zSET,"6,(hl)"},{_0, zSET,"6,a"}, + {_0, zSET,"7,b"}, {_0, zSET,"7,c"}, {_0, zSET,"7,d"}, {_0, zSET,"7,e"}, + {_0, zSET,"7,h"}, {_0, zSET,"7,l"}, {_WM,zSET,"7,(hl)"},{_0, zSET,"7,a"} +}; + +static z80dasm mnemonic_ed[256]= { + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_RP,zIN,"b,(c)"}, {_WP,zOUT,"(c),b"}, {_0, zSBC,"hl,bc"}, {_WM,zLD,"(W),bc"}, + {_0, zNEG,0}, {_0, zRETN,0}, {_0, zIM,"0"}, {_0, zLD,"i,a"}, + {_RP,zIN,"c,(c)"}, {_WP,zOUT,"(c),c"}, {_0, zADC,"hl,bc"}, {_RM,zLD,"bc,(W)"}, + {_0, zNEG,"*"}, {_0, zRETI,0}, {_0, zIM,"0"}, {_0, zLD,"r,a"}, + {_RP,zIN,"d,(c)"}, {_WP,zOUT,"(c),d"}, {_0, zSBC,"hl,de"}, {_WM,zLD,"(W),de"}, + {_0, zNEG,"*"}, {_0, zRETN,0}, {_0, zIM,"1"}, {_0, zLD,"a,i"}, + {_RP,zIN,"e,(c)"}, {_WP,zOUT,"(c),e"}, {_0, zADC,"hl,de"}, {_RM,zLD,"de,(W)"}, + {_0, zNEG,"*"}, {_0, zRETI,0}, {_0, zIM,"2"}, {_0, zLD,"a,r"}, + {_RP,zIN,"h,(c)"}, {_WP,zOUT,"(c),h"}, {_0, zSBC,"hl,hl"}, {_WM,zLD,"(W),hl"}, + {_0, zNEG,"*"}, {_0, zRETN,0}, {_0, zIM,"0"}, {_RW,zRRD,"(hl)"}, + {_RP,zIN,"l,(c)"}, {_WP,zOUT,"(c),l"}, {_0, zADC,"hl,hl"}, {_RM,zLD,"hl,(W)"}, + {_0, zNEG,"*"}, {_0, zRETI,0}, {_0, zIM,"0"}, {_RW,zRLD,"(hl)"}, + {_RP,zIN,"0,(c)"}, {_WP,zOUT,"(c),0"}, {_0, zSBC,"hl,sp"}, {_WM,zLD,"(W),sp"}, + {_0, zNEG,"*"}, {_0, zRETN,0}, {_0, zIM,"1"}, {_0, zDB,"?"}, + {_RP,zIN,"a,(c)"}, {_WP,zOUT,"(c),a"}, {_0, zADC,"hl,sp"}, {_RM,zLD,"sp,(W)"}, + {_0, zNEG,"*"}, {_0, zRETI,0}, {_0, zIM,"2"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_RW,zLDI,0}, {_RM,zCPI,0}, {_RP,zINI,0}, {_WP,zOUTI,0}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_RW,zLDD,0}, {_RM,zCPD,0}, {_RP,zIND,0}, {_WP,zOUTD,0}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_RW,zLDIR,0}, {_RM,zCPIR,0}, {_RP,zINIR,0}, {_WP,zOTIR,0}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_RW,zLDDR,0}, {_RM,zCPDR,0}, {_RP,zINDR,0}, {_WP,zOTDR,0}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"} +}; + +static z80dasm mnemonic_xx[256]= { + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zADD,"I,bc"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zADD,"I,de"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zLD,"I,N"}, {_WM,zLD,"(W),I"}, {_0, zINC,"I"}, + {_0, zINC,"Ih"}, {_0, zDEC,"Ih"}, {_0, zLD,"Ih,B"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zADD,"I,I"}, {_RM,zLD,"I,(W)"}, {_0, zDEC,"I"}, + {_0, zINC,"Il"}, {_0, zDEC,"Il"}, {_0, zLD,"Il,B"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_RW,zINC,"X"}, {_RW,zDEC,"X"}, {_WM,zLD,"X,B"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zADD,"I,sp"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zLD,"b,Ih"}, {_0, zLD,"b,Il"}, {_RM,zLD,"b,X"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zLD,"c,Ih"}, {_0, zLD,"c,Il"}, {_RM,zLD,"c,X"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zLD,"d,Ih"}, {_0, zLD,"d,Il"}, {_RM,zLD,"d,X"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zLD,"e,Ih"}, {_0, zLD,"e,Il"}, {_RM,zLD,"e,X"}, {_0, zDB,"?"}, + {_0, zLD,"Ih,b"}, {_0, zLD,"Ih,c"}, {_0, zLD,"Ih,d"}, {_0, zLD,"Ih,e"}, + {_0, zLD,"Ih,Ih"}, {_0, zLD,"Ih,Il"}, {_RM,zLD,"h,X"}, {_0, zLD,"Ih,a"}, + {_0, zLD,"Il,b"}, {_0, zLD,"Il,c"}, {_0, zLD,"Il,d"}, {_0, zLD,"Il,e"}, + {_0, zLD,"Il,Ih"}, {_0, zLD,"Il,Il"}, {_RM,zLD,"l,X"}, {_0, zLD,"Il,a"}, + {_WM,zLD,"X,b"}, {_WM,zLD,"X,c"}, {_WM,zLD,"X,d"}, {_WM,zLD,"X,e"}, + {_WM,zLD,"X,h"}, {_WM,zLD,"X,l"}, {_0, zDB,"?"}, {_WM,zLD,"X,a"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zLD,"a,Ih"}, {_0, zLD,"a,Il"}, {_RM,zLD,"a,X"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zADD,"a,Ih"}, {_0, zADD,"a,Il"}, {_RM,zADD,"a,X"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zADC,"a,Ih"}, {_0, zADC,"a,Il"}, {_RM,zADC,"a,X"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zSUB,"Ih"}, {_0, zSUB,"Il"}, {_RM,zSUB,"X"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zSBC,"a,Ih"}, {_0, zSBC,"a,Il"}, {_RM,zSBC,"a,X"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zAND,"Ih"}, {_0, zAND,"Il"}, {_RM,zAND,"X"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zXOR,"Ih"}, {_0, zXOR,"Il"}, {_RM,zXOR,"X"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zOR,"Ih"}, {_0, zOR,"Il"}, {_RM,zOR,"X"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zCP,"Ih"}, {_0, zCP,"Il"}, {_RM,zCP,"X"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"cb"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zPOP,"I"}, {_0, zDB,"?"}, {_RW,zEX,"(sp),I"}, + {_0, zDB,"?"}, {_0, zPUSH,"I"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_JP,zJP,"(I)"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zLD,"sp,I"}, {_0, zDB,"?"}, {_0, zDB,"?"}, + {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"} +}; + +static z80dasm mnemonic_main[256]= { + {_0, zNOP,0}, {_0, zLD,"bc,N"}, {_WM,zLD,"(bc),a"}, {_0, zINC,"bc"}, + {_0, zINC,"b"}, {_0, zDEC,"b"}, {_0, zLD,"b,B"}, {_0, zRLCA,0}, + {_0, zEX,"af,af'"}, {_0, zADD,"hl,bc"}, {_RM,zLD,"a,(bc)"}, {_0, zDEC,"bc"}, + {_0, zINC,"c"}, {_0, zDEC,"c"}, {_0, zLD,"c,B"}, {_0, zRRCA,0}, + {_JR,zDJNZ,"O"}, {_0, zLD,"de,N"}, {_WM,zLD,"(de),a"}, {_0, zINC,"de"}, + {_0, zINC,"d"}, {_0, zDEC,"d"}, {_0, zLD,"d,B"}, {_0, zRLA,0}, + {_JR,zJR,"O"}, {_0, zADD,"hl,de"}, {_RM,zLD,"a,(de)"}, {_0, zDEC,"de"}, + {_0, zINC,"e"}, {_0, zDEC,"e"}, {_0, zLD,"e,B"}, {_0, zRRA,0}, + {_JR,zJR,"nz,O"}, {_0, zLD,"hl,N"}, {_WM,zLD,"(W),hl"}, {_0, zINC,"hl"}, + {_0, zINC,"h"}, {_0, zDEC,"h"}, {_0, zLD,"h,B"}, {_0, zDAA,0}, + {_JR,zJR,"z,O"}, {_0, zADD,"hl,hl"}, {_RM,zLD,"hl,(W)"}, {_0, zDEC,"hl"}, + {_0, zINC,"l"}, {_0, zDEC,"l"}, {_0, zLD,"l,B"}, {_0, zCPL,0}, + {_JR,zJR,"nc,O"}, {_0, zLD,"sp,N"}, {_WM,zLD,"(W),a"}, {_0, zINC,"sp"}, + {_RW,zINC,"(hl)"}, {_RW,zDEC,"(hl)"}, {_WM,zLD,"(hl),B"}, {_0, zSCF,0}, + {_JR,zJR,"c,O"}, {_0, zADD,"hl,sp"}, {_RM,zLD,"a,(W)"}, {_0, zDEC,"sp"}, + {_0, zINC,"a"}, {_0, zDEC,"a"}, {_0, zLD,"a,B"}, {_0, zCCF,0}, + {_0, zLD,"b,b"}, {_0, zLD,"b,c"}, {_0, zLD,"b,d"}, {_0, zLD,"b,e"}, + {_0, zLD,"b,h"}, {_0, zLD,"b,l"}, {_RM,zLD,"b,(hl)"}, {_0, zLD,"b,a"}, + {_0, zLD,"c,b"}, {_0, zLD,"c,c"}, {_0, zLD,"c,d"}, {_0, zLD,"c,e"}, + {_0, zLD,"c,h"}, {_0, zLD,"c,l"}, {_RM,zLD,"c,(hl)"}, {_0, zLD,"c,a"}, + {_0, zLD,"d,b"}, {_0, zLD,"d,c"}, {_0, zLD,"d,d"}, {_0, zLD,"d,e"}, + {_0, zLD,"d,h"}, {_0, zLD,"d,l"}, {_RM,zLD,"d,(hl)"}, {_0, zLD,"d,a"}, + {_0, zLD,"e,b"}, {_0, zLD,"e,c"}, {_0, zLD,"e,d"}, {_0, zLD,"e,e"}, + {_0, zLD,"e,h"}, {_0, zLD,"e,l"}, {_RM,zLD,"e,(hl)"}, {_0, zLD,"e,a"}, + {_0, zLD,"h,b"}, {_0, zLD,"h,c"}, {_0, zLD,"h,d"}, {_0, zLD,"h,e"}, + {_0, zLD,"h,h"}, {_0, zLD,"h,l"}, {_RM,zLD,"h,(hl)"}, {_0, zLD,"h,a"}, + {_0, zLD,"l,b"}, {_0, zLD,"l,c"}, {_0, zLD,"l,d"}, {_0, zLD,"l,e"}, + {_0, zLD,"l,h"}, {_0, zLD,"l,l"}, {_RM,zLD,"l,(hl)"}, {_0, zLD,"l,a"}, + {_WM,zLD,"(hl),b"}, {_WM,zLD,"(hl),c"}, {_WM,zLD,"(hl),d"}, {_WM,zLD,"(hl),e"}, + {_WM,zLD,"(hl),h"}, {_WM,zLD,"(hl),l"}, {_0, zHLT,0}, {_WM,zLD,"(hl),a"}, + {_0, zLD,"a,b"}, {_0, zLD,"a,c"}, {_0, zLD,"a,d"}, {_0, zLD,"a,e"}, + {_0, zLD,"a,h"}, {_0, zLD,"a,l"}, {_RM,zLD,"a,(hl)"}, {_0, zLD,"a,a"}, + {_0, zADD,"a,b"}, {_0, zADD,"a,c"}, {_0, zADD,"a,d"}, {_0, zADD,"a,e"}, + {_0, zADD,"a,h"}, {_0, zADD,"a,l"}, {_RM,zADD,"a,(hl)"},{_0, zADD,"a,a"}, + {_0, zADC,"a,b"}, {_0, zADC,"a,c"}, {_0, zADC,"a,d"}, {_0, zADC,"a,e"}, + {_0, zADC,"a,h"}, {_0, zADC,"a,l"}, {_RM,zADC,"a,(hl)"},{_0, zADC,"a,a"}, + {_0, zSUB,"b"}, {_0, zSUB,"c"}, {_0, zSUB,"d"}, {_0, zSUB,"e"}, + {_0, zSUB,"h"}, {_0, zSUB,"l"}, {_RM,zSUB,"(hl)"}, {_0, zSUB,"a"}, + {_0, zSBC,"a,b"}, {_0, zSBC,"a,c"}, {_0, zSBC,"a,d"}, {_0, zSBC,"a,e"}, + {_0, zSBC,"a,h"}, {_0, zSBC,"a,l"}, {_RM,zSBC,"a,(hl)"},{_0, zSBC,"a,a"}, + {_0, zAND,"b"}, {_0, zAND,"c"}, {_0, zAND,"d"}, {_0, zAND,"e"}, + {_0, zAND,"h"}, {_0, zAND,"l"}, {_RM,zAND,"(hl)"}, {_0, zAND,"a"}, + {_0, zXOR,"b"}, {_0, zXOR,"c"}, {_0, zXOR,"d"}, {_0, zXOR,"e"}, + {_0, zXOR,"h"}, {_0, zXOR,"l"}, {_RM,zXOR,"(hl)"}, {_0, zXOR,"a"}, + {_0, zOR,"b"}, {_0, zOR,"c"}, {_0, zOR,"d"}, {_0, zOR,"e"}, + {_0, zOR,"h"}, {_0, zOR,"l"}, {_RM,zOR,"(hl)"}, {_0, zOR,"a"}, + {_0, zCP,"b"}, {_0, zCP,"c"}, {_0, zCP,"d"}, {_0, zCP,"e"}, + {_0, zCP,"h"}, {_0, zCP,"l"}, {_RM,zCP,"(hl)"}, {_0, zCP,"a"}, + {_0, zRET,"nz"}, {_0, zPOP,"bc"}, {_JP,zJP,"nz,A"}, {_JP,zJP,"A"}, + {_JP,zCALL,"nz,A"}, {_0, zPUSH,"bc"}, {_0, zADD,"a,B"}, {_JP,zRST,"V"}, + {_0, zRET,"z"}, {_0, zRET,0}, {_JP,zJP,"z,A"}, {_0, zDB,"cb"}, + {_JP,zCALL,"z,A"}, {_JP,zCALL,"A"}, {_0, zADC,"a,B"}, {_JP,zRST,"V"}, + {_0, zRET,"nc"}, {_0, zPOP,"de"}, {_JP,zJP,"nc,A"}, {_WP,zOUT,"(P),a"}, + {_JP,zCALL,"nc,A"}, {_0, zPUSH,"de"}, {_0, zSUB,"B"}, {_JP,zRST,"V"}, + {_0, zRET,"c"}, {_0, zEXX,0}, {_JP,zJP,"c,A"}, {_RP,zIN,"a,(P)"}, + {_JP,zCALL,"c,A"}, {_0, zDB,"dd"}, {_0, zSBC,"a,B"}, {_JP,zRST,"V"}, + {_0, zRET,"po"}, {_0, zPOP,"hl"}, {_JP,zJP,"po,A"}, {_RW,zEX,"(sp),hl"}, + {_JP,zCALL,"po,A"}, {_0, zPUSH,"hl"}, {_0, zAND,"B"}, {_JP,zRST,"V"}, + {_0, zRET,"pe"}, {_JP,zJP,"(hl)"}, {_JP,zJP,"pe,A"}, {_0, zEX,"de,hl"}, + {_JP,zCALL,"pe,A"}, {_0, zDB,"ed"}, {_0, zXOR,"B"}, {_JP,zRST,"V"}, + {_0, zRET,"p"}, {_0, zPOP,"af"}, {_JP,zJP,"p,A"}, {_0, zDI,0}, + {_JP,zCALL,"p,A"}, {_0, zPUSH,"af"}, {_0, zOR,"B"}, {_JP,zRST,"V"}, + {_0, zRET,"m"}, {_0, zLD,"sp,hl"}, {_JP,zJP,"m,A"}, {_0, zEI,0}, + {_JP,zCALL,"m,A"}, {_0, zDB,"fd"}, {_0, zCP,"B"}, {_JP,zRST,"V"} +}; + +static char sign(INT8 offset) +{ + return (offset < 0)? '-':'+'; +} + +static int offs(INT8 offset) +{ + if (offset < 0) return -offset; + return offset; +} + +/**************************************************************************** + * Disassemble opcode at PC and return number of bytes it takes + ****************************************************************************/ +unsigned DasmZ80( char *buffer, unsigned pc ) +{ + z80dasm *d; + const char *symbol, *src; + const char *ixy; + char *dst; + unsigned PC = pc; + INT8 offset = 0; + UINT8 op, op1; + UINT16 ea = 0, xy = 0; + + ixy = "oops!!"; + dst = buffer; + symbol = NULL; + + op = cpu_readop( pc++ ); + op1 = 0; /* keep GCC happy */ + + switch (op) + { + case 0xcb: + op = cpu_readop(pc++); + d = &mnemonic_cb[op]; + break; + case 0xed: + op1 = cpu_readop(pc++); + d = &mnemonic_ed[op1]; + break; + case 0xdd: + ixy = "ix"; + op1 = cpu_readop(pc++); + if( op1 == 0xcb ) + { + offset = (INT8) cpu_readop_arg(pc++); + op1 = cpu_readop_arg(pc++); /* fourth byte from OP_RAM! */ + xy = z80_get_reg( Z80_IX ); + ea = (xy + offset) & 0xffff; + d = &mnemonic_xx_cb[op1]; + } + else d = &mnemonic_xx[op1]; + break; + case 0xfd: + ixy = "iy"; + op1 = cpu_readop(pc++); + if( op1 == 0xcb ) + { + offset = (INT8) cpu_readop_arg(pc++); + op1 = cpu_readop_arg(pc++); /* fourth byte from OP_RAM! */ + xy = z80_get_reg( Z80_IY ); + ea = (ea + offset) & 0xffff; + d = &mnemonic_xx_cb[op1]; + } + else d = &mnemonic_xx[op1]; + break; + default: + d = &mnemonic_main[op]; + break; + } + + if( d->arguments ) + { + dst += sprintf(dst, "%-4s ", s_mnemonic[d->mnemonic]); + src = d->arguments; + while( *src ) + { + switch( *src ) + { + case '?': /* illegal opcode */ + dst += sprintf( dst, "$%02x,$%02x", op, op1); + break; + case 'A': + ea = cpu_readop_arg(pc) + ( cpu_readop_arg((pc+1)&0xffff) << 8); + pc += 2; + symbol = set_ea_info(0, ea, EA_UINT16, d->access); + dst += sprintf( dst, "%s", symbol ); + break; + case 'B': /* Byte op arg */ + ea = cpu_readop_arg( pc++ ); + symbol = set_ea_info(1, ea, EA_UINT8, EA_VALUE); + dst += sprintf( dst, "%s", symbol ); + break; + case '(': /* Memory byte at (HL) */ + *dst++ = *src; + if( !strncmp( src, "(bc)", 4) ) + { + ea = z80_get_reg( Z80_BC ); + set_ea_info(0, ea, EA_UINT8, d->access); + } + else + if( !strncmp( src, "(de)", 4) ) + { + ea = z80_get_reg( Z80_DE ); + set_ea_info(0, ea, EA_UINT8, d->access); + } + else + if( !strncmp( src, "(hl)", 4) ) + { + ea = z80_get_reg( Z80_HL ); + if( d->access == EA_ABS_PC ) + set_ea_info(0, ea, EA_DEFAULT, EA_ABS_PC); + else + set_ea_info(0, ea, EA_UINT8, d->access); + } + else + if( !strncmp( src, "(sp)", 4) ) + { + ea = z80_get_reg( Z80_SP ); + set_ea_info(0, ea, EA_UINT16, d->access); + } + else + if( !strncmp( src, "(P)", 3) ) + { + ea = (z80_get_reg( Z80_AF ) & 0xff00) | cpu_readop_arg( pc ); + set_ea_info(0, ea, EA_UINT16, d->access); + } + else + if( !strncmp( src, "(c)", 3) ) + { + ea = z80_get_reg( Z80_BC ); + set_ea_info(0, ea, EA_UINT16, d->access); + } + else + if( !strncmp( src, "(I)", 3) ) + { + ea = xy; + set_ea_info(0, ea, EA_DEFAULT, d->access); + } + break; + case 'N': /* Immediate 16 bit */ + ea = cpu_readop_arg(pc) + ( cpu_readop_arg((pc+1)&0xffff) << 8 ); + pc += 2; + symbol = set_ea_info(1, ea, EA_UINT16, EA_VALUE ); + dst += sprintf( dst, "%s", symbol ); + break; + case 'O': /* Offset relative to PC */ + offset = (INT8) cpu_readop_arg(pc++); + symbol = set_ea_info(0, PC, offset + 2, d->access); + dst += sprintf( dst, "%s", symbol ); + break; + case 'P': /* Port number */ + ea = cpu_readop_arg( pc++ ); + dst += sprintf( dst, "$%02X", ea ); + break; + case 'V': /* Restart vector */ + ea = op & 0x38; + symbol = set_ea_info(0, ea, EA_UINT8, d->access); + dst += sprintf( dst, "%s", symbol ); + break; + case 'W': /* Memory address word */ + ea = cpu_readop_arg(pc) + ( cpu_readop_arg((pc+1)&0xffff) << 8); + pc += 2; + symbol = set_ea_info(0, ea, EA_UINT16, d->access); + dst += sprintf( dst, "%s", symbol ); + break; + case 'X': + offset = (INT8) cpu_readop_arg(pc++); + ea = (xy + offset) & 0xffff; + case 'Y': + symbol = set_ea_info(0, ea, EA_UINT8, d->access); + dst += sprintf( dst,"(%s%c$%02x)", ixy, sign(offset), offs(offset) ); + break; + case 'I': + dst += sprintf( dst, "%s", ixy); + break; + default: + *dst++ = *src; + } + src++; + } + *dst = '\0'; + } + else + { + dst += sprintf(dst, "%s", s_mnemonic[d->mnemonic]); + } + + return pc - PC; +} + +#endif + diff --git a/plugins/ao/eng_qsf/z80dasm.h b/plugins/ao/eng_qsf/z80dasm.h new file mode 100644 index 00000000..aaca5204 --- /dev/null +++ b/plugins/ao/eng_qsf/z80dasm.h @@ -0,0 +1,2 @@ +extern int DasmZ80(char *buffer, int PC);
+
diff --git a/plugins/ao/eng_ssf/eng_ssf.c b/plugins/ao/eng_ssf/eng_ssf.c new file mode 100644 index 00000000..0d81a665 --- /dev/null +++ b/plugins/ao/eng_ssf/eng_ssf.c @@ -0,0 +1,336 @@ +/* + Audio Overload SDK - SSF file format engine + + Copyright (c) 2007 R. Belmont and Richard Bannister. + + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + +Sega driver commands: + +00 - NOP +01 - SEQUENCE_START +02 - SEQUENCE_STOP +03 - SEQUENCE_PAUSE +04 - SEQUENCE_CONTINUE +05 - SEQUENCE_VOLUME +06 - SEQUENCE_ALLSTOP +07 - SEQUENCE_TEMPO +08 - SEQUENCE_MAP +09 - HOST_MIDI +0A - VOLUME_ANALYZE_START +0B - VOLUME_ANALYZE_STOP +0C - DSP CLEAR +0D - ALL OFF +0E - SEQUENCE PAN +0F - N/A +10 - SOUND INITIALIZE +11 - Yamaha 3D check (8C) +12 - QSound check (8B) +13 - Yamaha 3D init (8D) +80 - CD level +81 - CD pan +82 - MASTER VOLUME +83 - EFFECT_CHANGE +84 - NOP +85 - PCM stream play start +86 - PCM stream play end +87 - MIXER_CHANGE +88 - Mixer parameter change +89 - Hardware check +8A - PCM parameter change +8B - QSound check +8C - Yamaha 3D check +8D - Yamaha 3D init + +*/ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "ao.h" +#include "eng_protos.h" +#include "corlett.h" +#include "sat_hw.h" +#include "scsp.h" +#include "m68kcpu.h" + +#define DEBUG_LOADER (0) + +typedef struct { + corlett_t *c; + char psfby[256]; + uint32 decaybegin, decayend, total_samples; + uint8 init_sat_ram[512*1024]; + m68ki_cpu_core *cpu; +} ssf_synth_t; + +void *ssf_start(const char *path, uint8 *buffer, uint32 length) +{ + ssf_synth_t *s = malloc (sizeof (ssf_synth_t)); + memset (s, 0, sizeof (ssf_synth_t)); + uint8 *file, *lib_decoded, *lib_raw_file; + uint32 offset, plength, lengthMS, fadeMS; + uint64 file_len, lib_len, lib_raw_length; + corlett_t *lib; + char *libfile; + int i; + + s->cpu = m68k_init (); +// // clear Saturn work RAM before we start scribbling in it +// memset(cpu->sat_ram, 0, 512*1024); + + // Decode the current SSF + if (corlett_decode(buffer, length, &file, &file_len, &s->c) != AO_SUCCESS) + { + ssf_stop (s); + return NULL; + } + + #if DEBUG_LOADER + printf("%d bytes decoded\n", file_len); + #endif + + // Get the library file, if any + for (i=0; i<9; i++) + { + libfile = i ? s->c->libaux[i-1] : s->c->lib; + if (libfile[0] != 0) + { + uint64 tmp_length; + + #if DEBUG_LOADER + printf("Loading library: %s\n", c->lib); + #endif + if (ao_get_lib(libfile, &lib_raw_file, &tmp_length) != AO_SUCCESS) + { + ssf_stop (s); + return NULL; + } + lib_raw_length = tmp_length; + + if (corlett_decode(lib_raw_file, lib_raw_length, &lib_decoded, &lib_len, &lib) != AO_SUCCESS) + { + free(lib_raw_file); + ssf_stop (s); + return NULL; + } + + // Free up raw file + free(lib_raw_file); + + // patch the file into ram + offset = lib_decoded[0] | lib_decoded[1]<<8 | lib_decoded[2]<<16 | lib_decoded[3]<<24; + + // guard against invalid data + if ((offset + (lib_len-4)) > 0x7ffff) + { + lib_len = 0x80000-offset+4; + } + memcpy(&s->cpu->sat_ram[offset], lib_decoded+4, lib_len-4); + + // Dispose the corlett structure for the lib - we don't use it + free(lib); + } + } + + // now patch the file into RAM over the libraries + offset = file[3]<<24 | file[2]<<16 | file[1]<<8 | file[0]; + + // guard against invalid data + if ((offset + (file_len-4)) > 0x7ffff) + { + file_len = 0x80000-offset+4; + } + + memcpy(&s->cpu->sat_ram[offset], file+4, file_len-4); + + free(file); + + // Finally, set psfby tag + strcpy(s->psfby, "n/a"); + if (s->c) + { + for (i = 0; i < MAX_UNKNOWN_TAGS; i++) + { + if (!strcasecmp(s->c->tag_name[i], "psfby")) + strcpy(s->psfby, s->c->tag_data[i]); + } + } + + #if DEBUG_LOADER + { + FILE *f; + + f = fopen("satram.bin", "wb"); + fwrite(cpu->sat_ram, 512*1024, 1, f); + fclose(f); + } + #endif + + // now flip everything (this makes sense because he's using starscream) + for (i = 0; i < 512*1024; i+=2) + { + uint8 temp; + + temp = s->cpu->sat_ram[i]; + s->cpu->sat_ram[i] = s->cpu->sat_ram[i+1]; + s->cpu->sat_ram[i+1] = temp; + } + + // backup for fast restarting + memcpy (s->init_sat_ram, s->cpu->sat_ram, sizeof (s->init_sat_ram)); + + sat_hw_init(s->cpu); + + // now figure out the time in samples for the length/fade + lengthMS = psfTimeToMS(s->c->inf_length); + fadeMS = psfTimeToMS(s->c->inf_fade); + s->total_samples = 0; + + if (lengthMS == 0) + { + lengthMS = ~0; + } + + if (lengthMS == ~0) + { + s->decaybegin = lengthMS; + } + else + { + lengthMS = (lengthMS * 441) / 10; + fadeMS = (fadeMS * 441) / 10; + + s->decaybegin = lengthMS; + s->decayend = lengthMS + fadeMS; + } + + return s; +} + +int32 ssf_gen(void *handle, int16 *buffer, uint32 samples) +{ + ssf_synth_t *s = handle; + int i; + int16 output[samples], output2[samples]; + int16 *stereo[2]; + int16 *outp = buffer; + + for (i = 0; i < samples; i++) + { + m68k_execute(s->cpu, (11300000/60)/735); + stereo[0] = &output[i]; + stereo[1] = &output2[i]; + SCSP_Update(s->cpu->SCSP, NULL, stereo, 1); + } + + for (i = 0; i < samples; i++) + { + // process the fade tags + if (s->total_samples >= s->decaybegin) + { + if (s->total_samples >= s->decayend) + { + // song is done here, call out as necessary to make your player stop + output[i] = 0; + output2[i] = 0; + } + else + { + int32 fader = 256 - (256*(s->total_samples - s->decaybegin)/(s->decayend-s->decaybegin)); + output[i] = (output[i] * fader)>>8; + output2[i] = (output2[i] * fader)>>8; + + s->total_samples++; + } + } + else + { + s->total_samples++; + } + + *outp++ = output[i]; + *outp++ = output2[i]; + } + + return AO_SUCCESS; +} + +int32 ssf_stop(void *handle) +{ + ssf_synth_t *s = handle; + sat_hw_free (s->cpu); + return AO_SUCCESS; +} + +int32 ssf_command(void *handle, int32 command, int32 parameter) + +{ + ssf_synth_t *s = handle; + switch (command) + { + case COMMAND_RESTART: + sat_hw_free (s->cpu); + memcpy (s->cpu->sat_ram, s->init_sat_ram, sizeof (s->init_sat_ram)); + sat_hw_init (s->cpu); + s->total_samples = 0; + return AO_SUCCESS; + + } + return AO_FAIL; +} + +int32 ssf_fill_info(void *handle, ao_display_info *info) +{ + ssf_synth_t *s = handle; + if (s->c == NULL) + return AO_FAIL; + + strcpy(info->title[1], "Name: "); + sprintf(info->info[1], "%s", s->c->inf_title); + + strcpy(info->title[2], "Game: "); + sprintf(info->info[2], "%s", s->c->inf_game); + + strcpy(info->title[3], "Artist: "); + sprintf(info->info[3], "%s", s->c->inf_artist); + + strcpy(info->title[4], "Copyright: "); + sprintf(info->info[4], "%s", s->c->inf_copy); + + strcpy(info->title[5], "Year: "); + sprintf(info->info[5], "%s", s->c->inf_year); + + strcpy(info->title[6], "Length: "); + sprintf(info->info[6], "%s", s->c->inf_length); + + strcpy(info->title[7], "Fade: "); + sprintf(info->info[7], "%s", s->c->inf_fade); + + strcpy(info->title[8], "Ripper: "); + sprintf(info->info[8], "%s", s->psfby); + + return AO_SUCCESS; +} diff --git a/plugins/ao/eng_ssf/m68k.h b/plugins/ao/eng_ssf/m68k.h new file mode 100644 index 00000000..851c7132 --- /dev/null +++ b/plugins/ao/eng_ssf/m68k.h @@ -0,0 +1,347 @@ +#ifndef M68K__HEADER +#define M68K__HEADER + +struct m68ki_cpu_core_s; + +/* ======================================================================== */ +/* ========================= LICENSING & COPYRIGHT ======================== */ +/* ======================================================================== */ +/* + * MUSASHI + * Version 3.3 + * + * A portable Motorola M680x0 processor emulation engine. + * Copyright 1998-2001 Karl Stenerud. All rights reserved. + * + * This code may be freely used for non-commercial purposes as long as this + * copyright notice remains unaltered in the source code and any binary files + * containing this code in compiled form. + * + * All other lisencing terms must be negotiated with the author + * (Karl Stenerud). + * + * The latest version of this code can be obtained at: + * http://kstenerud.cjb.net + */ + + + +/* ======================================================================== */ +/* ============================ GENERAL DEFINES =========================== */ + +/* ======================================================================== */ + +/* There are 7 levels of interrupt to the 68K. + * A transition from < 7 to 7 will cause a non-maskable interrupt (NMI). + */ +#define M68K_IRQ_NONE 0 +#define M68K_IRQ_1 1 +#define M68K_IRQ_2 2 +#define M68K_IRQ_3 3 +#define M68K_IRQ_4 4 +#define M68K_IRQ_5 5 +#define M68K_IRQ_6 6 +#define M68K_IRQ_7 7 + + +/* Special interrupt acknowledge values. + * Use these as special returns from the interrupt acknowledge callback + * (specified later in this header). + */ + +/* Causes an interrupt autovector (0x18 + interrupt level) to be taken. + * This happens in a real 68K if VPA or AVEC is asserted during an interrupt + * acknowledge cycle instead of DTACK. + */ +#define M68K_INT_ACK_AUTOVECTOR 0xffffffff + +/* Causes the spurious interrupt vector (0x18) to be taken + * This happens in a real 68K if BERR is asserted during the interrupt + * acknowledge cycle (i.e. no devices responded to the acknowledge). + */ +#define M68K_INT_ACK_SPURIOUS 0xfffffffe + + +/* CPU types for use in m68k_set_cpu_type() */ +enum +{ + M68K_CPU_TYPE_INVALID, + M68K_CPU_TYPE_68000, + M68K_CPU_TYPE_68010, + M68K_CPU_TYPE_68EC020, + M68K_CPU_TYPE_68020, + M68K_CPU_TYPE_68030, /* Supported by disassembler ONLY */ + M68K_CPU_TYPE_68040 /* Supported by disassembler ONLY */ +}; + +/* Registers used by m68k_get_reg() and m68k_set_reg() */ +typedef enum +{ + /* Real registers */ + M68K_REG_D0, /* Data registers */ + M68K_REG_D1, + M68K_REG_D2, + M68K_REG_D3, + M68K_REG_D4, + M68K_REG_D5, + M68K_REG_D6, + M68K_REG_D7, + M68K_REG_A0, /* Address registers */ + M68K_REG_A1, + M68K_REG_A2, + M68K_REG_A3, + M68K_REG_A4, + M68K_REG_A5, + M68K_REG_A6, + M68K_REG_A7, + M68K_REG_PC, /* Program Counter */ + M68K_REG_SR, /* Status Register */ + M68K_REG_SP, /* The current Stack Pointer (located in A7) */ + M68K_REG_USP, /* User Stack Pointer */ + M68K_REG_ISP, /* Interrupt Stack Pointer */ + M68K_REG_MSP, /* Master Stack Pointer */ + M68K_REG_SFC, /* Source Function Code */ + M68K_REG_DFC, /* Destination Function Code */ + M68K_REG_VBR, /* Vector Base Register */ + M68K_REG_CACR, /* Cache Control Register */ + M68K_REG_CAAR, /* Cache Address Register */ + + /* Assumed registers */ + /* These are cheat registers which emulate the 1-longword prefetch + * present in the 68000 and 68010. + */ + M68K_REG_PREF_ADDR, /* Last prefetch address */ + M68K_REG_PREF_DATA, /* Last prefetch data */ + + /* Convenience registers */ + M68K_REG_PPC, /* Previous value in the program counter */ + M68K_REG_IR, /* Instruction register */ + M68K_REG_CPU_TYPE /* Type of CPU being run */ +} m68k_register_t; + +/* ======================================================================== */ +/* ====================== FUNCTIONS CALLED BY THE CPU ===================== */ +/* ======================================================================== */ + +/* You will have to implement these functions */ + +/* read/write functions called by the CPU to access memory. + * while values used are 32 bits, only the appropriate number + * of bits are relevant (i.e. in write_memory_8, only the lower 8 bits + * of value should be written to memory). + * + * NOTE: I have separated the immediate and PC-relative memory fetches + * from the other memory fetches because some systems require + * differentiation between PROGRAM and DATA fetches (usually + * for security setups such as encryption). + * This separation can either be achieved by setting + * M68K_SEPARATE_READS in m68kconf.h and defining + * the read functions, or by setting M68K_EMULATE_FC and + * making a function code callback function. + * Using the callback offers better emulation coverage + * because you can also monitor whether the CPU is in SYSTEM or + * USER mode, but it is also slower. + */ + +/* Read from anywhere */ +unsigned int m68k_read_memory_8(struct m68ki_cpu_core_s *cpu, unsigned int address); +unsigned int m68k_read_memory_16(struct m68ki_cpu_core_s *cpu, unsigned int address); +unsigned int m68k_read_memory_32(struct m68ki_cpu_core_s *cpu, unsigned int address); + +/* Read data immediately following the PC */ +//INLINE unsigned int m68k_read_immediate_16(unsigned int address); +//INLINE unsigned int m68k_read_immediate_32(unsigned int address); + +/* Read data relative to the PC */ +//INLINE unsigned int m68k_read_pcrelative_8(unsigned int address); +//INLINE unsigned int m68k_read_pcrelative_16(unsigned int address); +//INLINE unsigned int m68k_read_pcrelative_32(unsigned int address); + +/* Memory access for the disassembler */ +unsigned int m68k_read_disassembler_8 (struct m68ki_cpu_core_s *cpu, unsigned int address); +unsigned int m68k_read_disassembler_16 (struct m68ki_cpu_core_s *cpu, unsigned int address); +unsigned int m68k_read_disassembler_32 (struct m68ki_cpu_core_s *cpu, unsigned int address); + +/* Write to anywhere */ +void m68k_write_memory_8(struct m68ki_cpu_core_s *cpu, unsigned int address, unsigned int value); +void m68k_write_memory_16(struct m68ki_cpu_core_s *cpu, unsigned int address, unsigned int value); +void m68k_write_memory_32(struct m68ki_cpu_core_s *cpu, unsigned int address, unsigned int value); + +/* Special call to simulate undocumented 68k behavior when move.l with a + * predecrement destination mode is executed. + * To simulate real 68k behavior, first write the high word to + * [address+2], and then write the low word to [address]. + * + * Enable this functionality with M68K_SIMULATE_PD_WRITES in m68kconf.h. + */ +//INLINE void m68k_write_memory_32_pd(unsigned int address, unsigned int value); + + + +/* ======================================================================== */ +/* ============================== CALLBACKS =============================== */ +/* ======================================================================== */ + +/* These functions allow you to set callbacks to the host when specific events + * occur. Note that you must enable the corresponding value in m68kconf.h + * in order for these to do anything useful. + * Note: I have defined default callbacks which are used if you have enabled + * the corresponding #define in m68kconf.h but either haven't assigned a + * callback or have assigned a callback of NULL. + */ + +/* Set the callback for an interrupt acknowledge. + * You must enable M68K_EMULATE_INT_ACK in m68kconf.h. + * The CPU will call the callback with the interrupt level being acknowledged. + * The host program must return either a vector from 0x02-0xff, or one of the + * special interrupt acknowledge values specified earlier in this header. + * If this is not implemented, the CPU will always assume an autovectored + * interrupt, and will automatically clear the interrupt request when it + * services the interrupt. + * Default behavior: return M68K_INT_ACK_AUTOVECTOR. + */ +void m68k_set_int_ack_callback(struct m68ki_cpu_core_s *cpu, int (*callback)(struct m68ki_cpu_core_s *cpu, int int_level)); + + +/* Set the callback for a breakpoint acknowledge (68010+). + * You must enable M68K_EMULATE_BKPT_ACK in m68kconf.h. + * The CPU will call the callback with whatever was in the data field of the + * BKPT instruction for 68020+, or 0 for 68010. + * Default behavior: do nothing. + */ +void m68k_set_bkpt_ack_callback(struct m68ki_cpu_core_s *cpu, void (*callback)(struct m68ki_cpu_core_s *cpu, unsigned int data)); + + +/* Set the callback for the RESET instruction. + * You must enable M68K_EMULATE_RESET in m68kconf.h. + * The CPU calls this callback every time it encounters a RESET instruction. + * Default behavior: do nothing. + */ +void m68k_set_reset_instr_callback(struct m68ki_cpu_core_s *cpu, void (*callback)(struct m68ki_cpu_core_s *cpu)); + + +/* Set the callback for informing of a large PC change. + * You must enable M68K_MONITOR_PC in m68kconf.h. + * The CPU calls this callback with the new PC value every time the PC changes + * by a large value (currently set for changes by longwords). + * Default behavior: do nothing. + */ +void m68k_set_pc_changed_callback(struct m68ki_cpu_core_s *cpu, void (*callback)(struct m68ki_cpu_core_s *cpu, unsigned int new_pc)); + + +/* Set the callback for CPU function code changes. + * You must enable M68K_EMULATE_FC in m68kconf.h. + * The CPU calls this callback with the function code before every memory + * access to set the CPU's function code according to what kind of memory + * access it is (supervisor/user, program/data and such). + * Default behavior: do nothing. + */ +void m68k_set_fc_callback(struct m68ki_cpu_core_s *cpu, void (*callback)(struct m68ki_cpu_core_s *cpu, unsigned int new_fc)); + + +/* Set a callback for the instruction cycle of the CPU. + * You must enable M68K_INSTRUCTION_HOOK in m68kconf.h. + * The CPU calls this callback just before fetching the opcode in the + * instruction cycle. + * Default behavior: do nothing. + */ +void m68k_set_instr_hook_callback(struct m68ki_cpu_core_s *cpu, void (*callback)(struct m68ki_cpu_core_s *cpu)); + + + +/* ======================================================================== */ +/* ====================== FUNCTIONS TO ACCESS THE CPU ===================== */ +/* ======================================================================== */ + +/* Use this function to set the CPU type you want to emulate. + * Currently supported types are: M68K_CPU_TYPE_68000, M68K_CPU_TYPE_68010, + * M68K_CPU_TYPE_EC020, and M68K_CPU_TYPE_68020. + */ +void m68k_set_cpu_type(struct m68ki_cpu_core_s *cpu, unsigned int cpu_type); + +/* Do whatever initialisations the core requires. Should be called + * at least once at init time. + */ +struct m68ki_cpu_core_s *m68k_init(void); + +/* Pulse the RESET pin on the CPU. + * You *MUST* reset the CPU at least once to initialize the emulation + * Note: If you didn't call m68k_set_cpu_type() before resetting + * the CPU for the first time, the CPU will be set to + * M68K_CPU_TYPE_68000. + */ +void m68k_pulse_reset(struct m68ki_cpu_core_s *cpu); + +/* execute num_cycles worth of instructions. returns number of cycles used */ +int m68k_execute(struct m68ki_cpu_core_s *cpu, int num_cycles); + +/* These functions let you read/write/modify the number of cycles left to run + * while m68k_execute() is running. + * These are useful if the 68k accesses a memory-mapped port on another device + * that requires immediate processing by another CPU. + */ +int m68k_cycles_run(struct m68ki_cpu_core_s *cpu); /* Number of cycles run so far */ +int m68k_cycles_remaining(struct m68ki_cpu_core_s *cpu); /* Number of cycles left */ +void m68k_modify_timeslice(struct m68ki_cpu_core_s *cpu, int cycles); /* Modify cycles left */ +void m68k_end_timeslice(struct m68ki_cpu_core_s *cpu); /* End timeslice now */ + +/* Set the IPL0-IPL2 pins on the CPU (IRQ). + * A transition from < 7 to 7 will cause a non-maskable interrupt (NMI). + * Setting IRQ to 0 will clear an interrupt request. + */ +void m68k_set_irq(struct m68ki_cpu_core_s *cpu, unsigned int int_level); + + +/* Halt the CPU as if you pulsed the HALT pin. */ +void m68k_pulse_halt(struct m68ki_cpu_core_s *cpu); + + +#if 0 +/* Context switching to allow multiple CPUs */ + +/* Get the size of the cpu context in bytes */ +unsigned int m68k_context_size(struct m68ki_cpu_core_s *cpu); + +/* Get a cpu context */ +unsigned int m68k_get_context(struct m68ki_cpu_core_s *cpu, void* dst); + +/* set the current cpu context */ +void m68k_set_context(struct m68ki_cpu_core_s *cpu, void* dst); +#endif + +/* Register the CPU state information */ +void m68k_state_register(struct m68ki_cpu_core_s *cpu, const char *type); + + +/* Peek at the internals of a CPU context. This can either be a context + * retrieved using m68k_get_context() or the currently running context. + * If context is NULL, the currently running CPU context will be used. + */ +unsigned int m68k_get_reg(struct m68ki_cpu_core_s *cpu, void* context, m68k_register_t reg); + +/* Poke values into the internals of the currently running CPU context */ +void m68k_set_reg(struct m68ki_cpu_core_s *cpu, m68k_register_t reg, unsigned int value); + +/* Check if an instruction is valid for the specified CPU type */ +unsigned int m68k_is_valid_instruction(struct m68ki_cpu_core_s *cpu, unsigned int instruction, unsigned int cpu_type); + +/* Disassemble 1 instruction using the epecified CPU type at pc. Stores + * disassembly in str_buff and returns the size of the instruction in bytes. + */ +unsigned int m68k_disassemble(struct m68ki_cpu_core_s *cpu, char* str_buff, unsigned int pc, unsigned int cpu_type); + + +/* ======================================================================== */ +/* ============================= CONFIGURATION ============================ */ +/* ======================================================================== */ + +/* Import the configuration for this build */ +#include "m68kconf.h" + + + +/* ======================================================================== */ +/* ============================== END OF FILE ============================= */ +/* ======================================================================== */ + +#endif /* M68K__HEADER */ diff --git a/plugins/ao/eng_ssf/m68k_in.c b/plugins/ao/eng_ssf/m68k_in.c new file mode 100644 index 00000000..65e317ef --- /dev/null +++ b/plugins/ao/eng_ssf/m68k_in.c @@ -0,0 +1,10336 @@ +/* +must fix: + callm + chk +*/ +/* ======================================================================== */ +/* ========================= LICENSING & COPYRIGHT ======================== */ +/* ======================================================================== */ +/* + * MUSASHI + * Version 3.3 + * + * A portable Motorola M680x0 processor emulation engine. + * Copyright 1998-2001 Karl Stenerud. All rights reserved. + * + * This code may be freely used for non-commercial purposes as long as this + * copyright notice remains unaltered in the source code and any binary files + * containing this code in compiled form. + * + * All other lisencing terms must be negotiated with the author + * (Karl Stenerud). + * + * The latest version of this code can be obtained at: + * http://kstenerud.cjb.net + */ + +/* Special thanks to Bart Trzynadlowski for his insight into the + * undocumented features of this chip: + * + * http://dynarec.com/~bart/files/68knotes.txt + */ + + +/* Input file for m68kmake + * ----------------------- + * + * All sections begin with 80 X's in a row followed by an end-of-line + * sequence. + * After this, m68kmake will expect to find one of the following section + * identifiers: + * M68KMAKE_PROTOTYPE_HEADER - header for opcode handler prototypes + * M68KMAKE_PROTOTYPE_FOOTER - footer for opcode handler prototypes + * M68KMAKE_TABLE_HEADER - header for opcode handler jumptable + * M68KMAKE_TABLE_FOOTER - footer for opcode handler jumptable + * M68KMAKE_TABLE_BODY - the table itself + * M68KMAKE_OPCODE_HANDLER_HEADER - header for opcode handler implementation + * M68KMAKE_OPCODE_HANDLER_FOOTER - footer for opcode handler implementation + * M68KMAKE_OPCODE_HANDLER_BODY - body section for opcode handler implementation + * + * NOTE: M68KMAKE_OPCODE_HANDLER_BODY must be last in the file and + * M68KMAKE_TABLE_BODY must be second last in the file. + * + * The M68KMAKE_OPHANDLER_BODY section contains the opcode handler + * primitives themselves. Each opcode handler begins with: + * M68KMAKE_OP(A, B, C, D) + * + * where A is the opcode handler name, B is the size of the operation, + * C denotes any special processing mode, and D denotes a specific + * addressing mode. + * For C and D where nothing is specified, use "." + * + * Example: + * M68KMAKE_OP(abcd, 8, rr, .) abcd, size 8, register to register, default EA + * M68KMAKE_OP(abcd, 8, mm, ax7) abcd, size 8, memory to memory, register X is A7 + * M68KMAKE_OP(tst, 16, ., pcix) tst, size 16, PCIX addressing + * + * All opcode handler primitives end with a closing curly brace "}" at column 1 + * + * NOTE: Do not place a M68KMAKE_OP() directive inside the opcode handler, + * and do not put a closing curly brace at column 1 unless it is + * marking the end of the handler! + * + * Inside the handler, m68kmake will recognize M68KMAKE_GET_OPER_xx_xx, + * M68KMAKE_GET_EA_xx_xx, and M68KMAKE_CC directives, and create multiple + * opcode handlers to handle variations in the opcode handler. + * Note: M68KMAKE_CC will only be interpreted in condition code opcodes. + * As well, M68KMAKE_GET_EA_xx_xx and M68KMAKE_GET_OPER_xx_xx will only + * be interpreted on instructions where the corresponding table entry + * specifies multiple effective addressing modes. + * Example: + * clr 32 . . 0100001010...... A+-DXWL... U U U 12 6 4 + * + * This table entry says that the clr.l opcde has 7 variations (A+-DXWL). + * It is run in user or supervisor mode for all CPUs, and uses 12 cycles for + * 68000, 6 cycles for 68010, and 4 cycles for 68020. + */ + +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +M68KMAKE_PROTOTYPE_HEADER + +#ifndef M68KOPS__HEADER +#define M68KOPS__HEADER + +/* ======================================================================== */ +/* ============================ OPCODE HANDLERS =========================== */ +/* ======================================================================== */ + + + +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +M68KMAKE_PROTOTYPE_FOOTER + + +/* Build the opcode handler table */ +void m68ki_build_opcode_table(void); + +extern void (*m68ki_instruction_jump_table[0x10000])(void); /* opcode handler jump table */ +extern unsigned char m68ki_cycles[][0x10000]; + + +/* ======================================================================== */ +/* ============================== END OF FILE ============================= */ +/* ======================================================================== */ + +#endif /* M68KOPS__HEADER */ + + + +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +M68KMAKE_TABLE_HEADER + +/* ======================================================================== */ +/* ========================= OPCODE TABLE BUILDER ========================= */ +/* ======================================================================== */ + +#include "m68kops.h" + +#define NUM_CPU_TYPES 3 + +void (*m68ki_instruction_jump_table[0x10000])(void); /* opcode handler jump table */ +unsigned char m68ki_cycles[NUM_CPU_TYPES][0x10000]; /* Cycles used by CPU type */ + +/* This is used to generate the opcode handler jump table */ +typedef struct +{ + void (*opcode_handler)(void); /* handler function */ + unsigned int mask; /* mask on opcode */ + unsigned int match; /* what to match after masking */ + unsigned char cycles[NUM_CPU_TYPES]; /* cycles each cpu type takes */ +} opcode_handler_struct; + + +/* Opcode handler table */ +static opcode_handler_struct m68k_opcode_handler_table[] = +{ +/* function mask match 000 010 020 */ + + + +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +M68KMAKE_TABLE_FOOTER + + {0, 0, 0, {0, 0, 0}} +}; + + +/* Build the opcode handler jump table */ +void m68ki_build_opcode_table(void) +{ + opcode_handler_struct *ostruct; + int instr; + int i; + int j; + int k; + + for(i = 0; i < 0x10000; i++) + { + /* default to illegal */ + m68ki_instruction_jump_table[i] = m68k_op_illegal; + for(k=0;k<NUM_CPU_TYPES;k++) + m68ki_cycles[k][i] = 0; + } + + ostruct = m68k_opcode_handler_table; + while(ostruct->mask != 0xff00) + { + for(i = 0;i < 0x10000;i++) + { + if((i & ostruct->mask) == ostruct->match) + { + m68ki_instruction_jump_table[i] = ostruct->opcode_handler; + for(k=0;k<NUM_CPU_TYPES;k++) + m68ki_cycles[k][i] = ostruct->cycles[k]; + } + } + ostruct++; + } + while(ostruct->mask == 0xff00) + { + for(i = 0;i <= 0xff;i++) + { + m68ki_instruction_jump_table[ostruct->match | i] = ostruct->opcode_handler; + for(k=0;k<NUM_CPU_TYPES;k++) + m68ki_cycles[k][ostruct->match | i] = ostruct->cycles[k]; + } + ostruct++; + } + while(ostruct->mask == 0xf1f8) + { + for(i = 0;i < 8;i++) + { + for(j = 0;j < 8;j++) + { + instr = ostruct->match | (i << 9) | j; + m68ki_instruction_jump_table[instr] = ostruct->opcode_handler; + for(k=0;k<NUM_CPU_TYPES;k++) + m68ki_cycles[k][instr] = ostruct->cycles[k]; + if((instr & 0xf000) == 0xe000 && (!(instr & 0x20))) + m68ki_cycles[0][instr] = m68ki_cycles[1][instr] = ostruct->cycles[k] + ((((j-1)&7)+1)<<1); + } + } + ostruct++; + } + while(ostruct->mask == 0xfff0) + { + for(i = 0;i <= 0x0f;i++) + { + m68ki_instruction_jump_table[ostruct->match | i] = ostruct->opcode_handler; + for(k=0;k<NUM_CPU_TYPES;k++) + m68ki_cycles[k][ostruct->match | i] = ostruct->cycles[k]; + } + ostruct++; + } + while(ostruct->mask == 0xf1ff) + { + for(i = 0;i <= 0x07;i++) + { + m68ki_instruction_jump_table[ostruct->match | (i << 9)] = ostruct->opcode_handler; + for(k=0;k<NUM_CPU_TYPES;k++) + m68ki_cycles[k][ostruct->match | (i << 9)] = ostruct->cycles[k]; + } + ostruct++; + } + while(ostruct->mask == 0xfff8) + { + for(i = 0;i <= 0x07;i++) + { + m68ki_instruction_jump_table[ostruct->match | i] = ostruct->opcode_handler; + for(k=0;k<NUM_CPU_TYPES;k++) + m68ki_cycles[k][ostruct->match | i] = ostruct->cycles[k]; + } + ostruct++; + } + while(ostruct->mask == 0xffff) + { + m68ki_instruction_jump_table[ostruct->match] = ostruct->opcode_handler; + for(k=0;k<NUM_CPU_TYPES;k++) + m68ki_cycles[k][ostruct->match] = ostruct->cycles[k]; + ostruct++; + } +} + + +/* ======================================================================== */ +/* ============================== END OF FILE ============================= */ +/* ======================================================================== */ + + + +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +M68KMAKE_OPCODE_HANDLER_HEADER + +#include "m68kcpu.h" + +/* ======================================================================== */ +/* ========================= INSTRUCTION HANDLERS ========================= */ +/* ======================================================================== */ + + + +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +M68KMAKE_OPCODE_HANDLER_FOOTER + +/* ======================================================================== */ +/* ============================== END OF FILE ============================= */ +/* ======================================================================== */ + + + +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +M68KMAKE_TABLE_BODY + +The following table is arranged as follows: + +name: Opcode mnemonic + +size: Operation size + +spec proc: Special processing mode: + .: normal + s: static operand + r: register operand + rr: register to register + mm: memory to memory + er: effective address to register + re: register to effective address + dd: data register to data register + da: data register to address register + aa: address register to address register + cr: control register to register + rc: register to control register + toc: to condition code register + tos: to status register + tou: to user stack pointer + frc: from condition code register + frs: from status register + fru: from user stack pointer + * for move.x, the special processing mode is a specific + destination effective addressing mode. + +spec ea: Specific effective addressing mode: + .: normal + i: immediate + d: data register + a: address register + ai: address register indirect + pi: address register indirect with postincrement + pd: address register indirect with predecrement + di: address register indirect with displacement + ix: address register indirect with index + aw: absolute word address + al: absolute long address + pcdi: program counter relative with displacement + pcix: program counter relative with index + a7: register specified in instruction is A7 + ax7: register field X of instruction is A7 + ay7: register field Y of instruction is A7 + axy7: register fields X and Y of instruction are A7 + +bit pattern: Pattern to recognize this opcode. "." means don't care. + +allowed ea: List of allowed addressing modes: + .: not present + A: address register indirect + +: ARI (address register indirect) with postincrement + -: ARI with predecrement + D: ARI with displacement + X: ARI with index + W: absolute word address + L: absolute long address + d: program counter indirect with displacement + x: program counter indirect with index + I: immediate +mode: CPU operating mode for each cpu type. U = user or supervisor, + S = supervisor only, "." = opcode not present. + +cpu cycles: Base number of cycles required to execute this opcode on the + specified CPU type. + Use "." if CPU does not have this opcode. + + + + spec spec allowed ea mode cpu cycles +name size proc ea bit pattern A+-DXWLdxI 0 1 2 000 010 020 comments +====== ==== ==== ==== ================ ========== = = = === === === ============= +M68KMAKE_TABLE_START +1010 0 . . 1010............ .......... U U U 4 4 4 +1111 0 . . 1111............ .......... U U U 4 4 4 +abcd 8 rr . 1100...100000... .......... U U U 6 6 4 +abcd 8 mm ax7 1100111100001... .......... U U U 18 18 16 +abcd 8 mm ay7 1100...100001111 .......... U U U 18 18 16 +abcd 8 mm axy7 1100111100001111 .......... U U U 18 18 16 +abcd 8 mm . 1100...100001... .......... U U U 18 18 16 +add 8 er d 1101...000000... .......... U U U 4 4 2 +add 8 er . 1101...000...... A+-DXWLdxI U U U 4 4 2 +add 16 er d 1101...001000... .......... U U U 4 4 2 +add 16 er a 1101...001001... .......... U U U 4 4 2 +add 16 er . 1101...001...... A+-DXWLdxI U U U 4 4 2 +add 32 er d 1101...010000... .......... U U U 6 6 2 +add 32 er a 1101...010001... .......... U U U 6 6 2 +add 32 er . 1101...010...... A+-DXWLdxI U U U 6 6 2 +add 8 re . 1101...100...... A+-DXWL... U U U 8 8 4 +add 16 re . 1101...101...... A+-DXWL... U U U 8 8 4 +add 32 re . 1101...110...... A+-DXWL... U U U 12 12 4 +adda 16 . d 1101...011000... .......... U U U 8 8 2 +adda 16 . a 1101...011001... .......... U U U 8 8 2 +adda 16 . . 1101...011...... A+-DXWLdxI U U U 8 8 2 +adda 32 . d 1101...111000... .......... U U U 6 6 2 +adda 32 . a 1101...111001... .......... U U U 6 6 2 +adda 32 . . 1101...111...... A+-DXWLdxI U U U 6 6 2 +addi 8 . d 0000011000000... .......... U U U 8 8 2 +addi 8 . . 0000011000...... A+-DXWL... U U U 12 12 4 +addi 16 . d 0000011001000... .......... U U U 8 8 2 +addi 16 . . 0000011001...... A+-DXWL... U U U 12 12 4 +addi 32 . d 0000011010000... .......... U U U 16 14 2 +addi 32 . . 0000011010...... A+-DXWL... U U U 20 20 4 +addq 8 . d 0101...000000... .......... U U U 4 4 2 +addq 8 . . 0101...000...... A+-DXWL... U U U 8 8 4 +addq 16 . d 0101...001000... .......... U U U 4 4 2 +addq 16 . a 0101...001001... .......... U U U 4 4 2 +addq 16 . . 0101...001...... A+-DXWL... U U U 8 8 4 +addq 32 . d 0101...010000... .......... U U U 8 8 2 +addq 32 . a 0101...010001... .......... U U U 8 8 2 +addq 32 . . 0101...010...... A+-DXWL... U U U 12 12 4 +addx 8 rr . 1101...100000... .......... U U U 4 4 2 +addx 16 rr . 1101...101000... .......... U U U 4 4 2 +addx 32 rr . 1101...110000... .......... U U U 8 6 2 +addx 8 mm ax7 1101111100001... .......... U U U 18 18 12 +addx 8 mm ay7 1101...100001111 .......... U U U 18 18 12 +addx 8 mm axy7 1101111100001111 .......... U U U 18 18 12 +addx 8 mm . 1101...100001... .......... U U U 18 18 12 +addx 16 mm . 1101...101001... .......... U U U 18 18 12 +addx 32 mm . 1101...110001... .......... U U U 30 30 12 +and 8 er d 1100...000000... .......... U U U 4 4 2 +and 8 er . 1100...000...... A+-DXWLdxI U U U 4 4 2 +and 16 er d 1100...001000... .......... U U U 4 4 2 +and 16 er . 1100...001...... A+-DXWLdxI U U U 4 4 2 +and 32 er d 1100...010000... .......... U U U 6 6 2 +and 32 er . 1100...010...... A+-DXWLdxI U U U 6 6 2 +and 8 re . 1100...100...... A+-DXWL... U U U 8 8 4 +and 16 re . 1100...101...... A+-DXWL... U U U 8 8 4 +and 32 re . 1100...110...... A+-DXWL... U U U 12 12 4 +andi 16 toc . 0000001000111100 .......... U U U 20 16 12 +andi 16 tos . 0000001001111100 .......... S S S 20 16 12 +andi 8 . d 0000001000000... .......... U U U 8 8 2 +andi 8 . . 0000001000...... A+-DXWL... U U U 12 12 4 +andi 16 . d 0000001001000... .......... U U U 8 8 2 +andi 16 . . 0000001001...... A+-DXWL... U U U 12 12 4 +andi 32 . d 0000001010000... .......... U U U 14 14 2 +andi 32 . . 0000001010...... A+-DXWL... U U U 20 20 4 +asr 8 s . 1110...000000... .......... U U U 6 6 6 +asr 16 s . 1110...001000... .......... U U U 6 6 6 +asr 32 s . 1110...010000... .......... U U U 8 8 6 +asr 8 r . 1110...000100... .......... U U U 6 6 6 +asr 16 r . 1110...001100... .......... U U U 6 6 6 +asr 32 r . 1110...010100... .......... U U U 8 8 6 +asr 16 . . 1110000011...... A+-DXWL... U U U 8 8 5 +asl 8 s . 1110...100000... .......... U U U 6 6 8 +asl 16 s . 1110...101000... .......... U U U 6 6 8 +asl 32 s . 1110...110000... .......... U U U 8 8 8 +asl 8 r . 1110...100100... .......... U U U 6 6 8 +asl 16 r . 1110...101100... .......... U U U 6 6 8 +asl 32 r . 1110...110100... .......... U U U 8 8 8 +asl 16 . . 1110000111...... A+-DXWL... U U U 8 8 6 +bcc 8 . . 0110............ .......... U U U 8 8 6 +bcc 16 . . 0110....00000000 .......... U U U 10 10 6 +bcc 32 . . 0110....11111111 .......... . . U . . 6 +bchg 8 r . 0000...101...... A+-DXWL... U U U 8 8 4 +bchg 32 r d 0000...101000... .......... U U U 8 8 4 +bchg 8 s . 0000100001...... A+-DXWL... U U U 12 12 4 +bchg 32 s d 0000100001000... .......... U U U 12 12 4 +bclr 8 r . 0000...110...... A+-DXWL... U U U 8 10 4 +bclr 32 r d 0000...110000... .......... U U U 10 10 4 +bclr 8 s . 0000100010...... A+-DXWL... U U U 12 12 4 +bclr 32 s d 0000100010000... .......... U U U 14 14 4 +bfchg 32 . d 1110101011000... .......... . . U . . 12 timing not quite correct +bfchg 32 . . 1110101011...... A..DXWL... . . U . . 20 +bfclr 32 . d 1110110011000... .......... . . U . . 12 +bfclr 32 . . 1110110011...... A..DXWL... . . U . . 20 +bfexts 32 . d 1110101111000... .......... . . U . . 8 +bfexts 32 . . 1110101111...... A..DXWLdx. . . U . . 15 +bfextu 32 . d 1110100111000... .......... . . U . . 8 +bfextu 32 . . 1110100111...... A..DXWLdx. . . U . . 15 +bfffo 32 . d 1110110111000... .......... . . U . . 18 +bfffo 32 . . 1110110111...... A..DXWLdx. . . U . . 28 +bfins 32 . d 1110111111000... .......... . . U . . 10 +bfins 32 . . 1110111111...... A..DXWL... . . U . . 17 +bfset 32 . d 1110111011000... .......... . . U . . 12 +bfset 32 . . 1110111011...... A..DXWL... . . U . . 20 +bftst 32 . d 1110100011000... .......... . . U . . 6 +bftst 32 . . 1110100011...... A..DXWLdx. . . U . . 13 +bkpt 0 . . 0100100001001... .......... . U U . 10 10 +bra 8 . . 01100000........ .......... U U U 10 10 10 +bra 16 . . 0110000000000000 .......... U U U 10 10 10 +bra 32 . . 0110000011111111 .......... U U U . . 10 +bset 32 r d 0000...111000... .......... U U U 8 8 4 +bset 8 r . 0000...111...... A+-DXWL... U U U 8 8 4 +bset 8 s . 0000100011...... A+-DXWL... U U U 12 12 4 +bset 32 s d 0000100011000... .......... U U U 12 12 4 +bsr 8 . . 01100001........ .......... U U U 18 18 7 +bsr 16 . . 0110000100000000 .......... U U U 18 18 7 +bsr 32 . . 0110000111111111 .......... . . U . . 7 +btst 8 r . 0000...100...... A+-DXWLdxI U U U 4 4 4 +btst 32 r d 0000...100000... .......... U U U 6 6 4 +btst 8 s . 0000100000...... A+-DXWLdx. U U U 8 8 4 +btst 32 s d 0000100000000... .......... U U U 10 10 4 +callm 32 . . 0000011011...... A..DXWLdx. . . U . . 60 not properly emulated +cas 8 . . 0000101011...... A+-DXWL... . . U . . 12 +cas 16 . . 0000110011...... A+-DXWL... . . U . . 12 +cas 32 . . 0000111011...... A+-DXWL... . . U . . 12 +cas2 16 . . 0000110011111100 .......... . . U . . 12 +cas2 32 . . 0000111011111100 .......... . . U . . 12 +chk 16 . d 0100...110000... .......... U U U 10 8 8 +chk 16 . . 0100...110...... A+-DXWLdxI U U U 10 8 8 +chk 32 . d 0100...100000... .......... . . U . . 8 +chk 32 . . 0100...100...... A+-DXWLdxI . . U . . 8 +chk2cmp2 8 . pcdi 0000000011111010 .......... . . U . . 23 +chk2cmp2 8 . pcix 0000000011111011 .......... . . U . . 23 +chk2cmp2 8 . . 0000000011...... A..DXWL... . . U . . 18 +chk2cmp2 16 . pcdi 0000001011111010 .......... . . U . . 23 +chk2cmp2 16 . pcix 0000001011111011 .......... . . U . . 23 +chk2cmp2 16 . . 0000001011...... A..DXWL... . . U . . 18 +chk2cmp2 32 . pcdi 0000010011111010 .......... . . U . . 23 +chk2cmp2 32 . pcix 0000010011111011 .......... . . U . . 23 +chk2cmp2 32 . . 0000010011...... A..DXWL... . . U . . 18 +clr 8 . d 0100001000000... .......... U U U 4 4 2 +clr 8 . . 0100001000...... A+-DXWL... U U U 8 4 4 +clr 16 . d 0100001001000... .......... U U U 4 4 2 +clr 16 . . 0100001001...... A+-DXWL... U U U 8 4 4 +clr 32 . d 0100001010000... .......... U U U 6 6 2 +clr 32 . . 0100001010...... A+-DXWL... U U U 12 6 4 +cmp 8 . d 1011...000000... .......... U U U 4 4 2 +cmp 8 . . 1011...000...... A+-DXWLdxI U U U 4 4 2 +cmp 16 . d 1011...001000... .......... U U U 4 4 2 +cmp 16 . a 1011...001001... .......... U U U 4 4 2 +cmp 16 . . 1011...001...... A+-DXWLdxI U U U 4 4 2 +cmp 32 . d 1011...010000... .......... U U U 6 6 2 +cmp 32 . a 1011...010001... .......... U U U 6 6 2 +cmp 32 . . 1011...010...... A+-DXWLdxI U U U 6 6 2 +cmpa 16 . d 1011...011000... .......... U U U 6 6 4 +cmpa 16 . a 1011...011001... .......... U U U 6 6 4 +cmpa 16 . . 1011...011...... A+-DXWLdxI U U U 6 6 4 +cmpa 32 . d 1011...111000... .......... U U U 6 6 4 +cmpa 32 . a 1011...111001... .......... U U U 6 6 4 +cmpa 32 . . 1011...111...... A+-DXWLdxI U U U 6 6 4 +cmpi 8 . d 0000110000000... .......... U U U 8 8 2 +cmpi 8 . . 0000110000...... A+-DXWL... U U U 8 8 2 +cmpi 8 . pcdi 0000110000111010 .......... . . U . . 7 +cmpi 8 . pcix 0000110000111011 .......... . . U . . 9 +cmpi 16 . d 0000110001000... .......... U U U 8 8 2 +cmpi 16 . . 0000110001...... A+-DXWL... U U U 8 8 2 +cmpi 16 . pcdi 0000110001111010 .......... . . U . . 7 +cmpi 16 . pcix 0000110001111011 .......... . . U . . 9 +cmpi 32 . d 0000110010000... .......... U U U 14 12 2 +cmpi 32 . . 0000110010...... A+-DXWL... U U U 12 12 2 +cmpi 32 . pcdi 0000110010111010 .......... . . U . . 7 +cmpi 32 . pcix 0000110010111011 .......... . . U . . 9 +cmpm 8 . ax7 1011111100001... .......... U U U 12 12 9 +cmpm 8 . ay7 1011...100001111 .......... U U U 12 12 9 +cmpm 8 . axy7 1011111100001111 .......... U U U 12 12 9 +cmpm 8 . . 1011...100001... .......... U U U 12 12 9 +cmpm 16 . . 1011...101001... .......... U U U 12 12 9 +cmpm 32 . . 1011...110001... .......... U U U 20 20 9 +cpbcc 32 . . 1111...01....... .......... . . U . . 4 unemulated +cpdbcc 32 . . 1111...001001... .......... . . U . . 4 unemulated +cpgen 32 . . 1111...000...... .......... . . U . . 4 unemulated +cpscc 32 . . 1111...001...... .......... . . U . . 4 unemulated +cptrapcc 32 . . 1111...001111... .......... . . U . . 4 unemulated +dbt 16 . . 0101000011001... .......... U U U 12 12 6 +dbf 16 . . 0101000111001... .......... U U U 14 14 6 +dbcc 16 . . 0101....11001... .......... U U U 12 12 6 +divs 16 . d 1000...111000... .......... U U U 158 122 56 +divs 16 . . 1000...111...... A+-DXWLdxI U U U 158 122 56 +divu 16 . d 1000...011000... .......... U U U 140 108 44 +divu 16 . . 1000...011...... A+-DXWLdxI U U U 140 108 44 +divl 32 . d 0100110001000... .......... . . U . . 84 +divl 32 . . 0100110001...... A+-DXWLdxI . . U . . 84 +eor 8 . d 1011...100000... .......... U U U 4 4 2 +eor 8 . . 1011...100...... A+-DXWL... U U U 8 8 4 +eor 16 . d 1011...101000... .......... U U U 4 4 2 +eor 16 . . 1011...101...... A+-DXWL... U U U 8 8 4 +eor 32 . d 1011...110000... .......... U U U 8 6 2 +eor 32 . . 1011...110...... A+-DXWL... U U U 12 12 4 +eori 16 toc . 0000101000111100 .......... U U U 20 16 12 +eori 16 tos . 0000101001111100 .......... S S S 20 16 12 +eori 8 . d 0000101000000... .......... U U U 8 8 2 +eori 8 . . 0000101000...... A+-DXWL... U U U 12 12 4 +eori 16 . d 0000101001000... .......... U U U 8 8 2 +eori 16 . . 0000101001...... A+-DXWL... U U U 12 12 4 +eori 32 . d 0000101010000... .......... U U U 16 14 2 +eori 32 . . 0000101010...... A+-DXWL... U U U 20 20 4 +exg 32 dd . 1100...101000... .......... U U U 6 6 2 +exg 32 aa . 1100...101001... .......... U U U 6 6 2 +exg 32 da . 1100...110001... .......... U U U 6 6 2 +ext 16 . . 0100100010000... .......... U U U 4 4 4 +ext 32 . . 0100100011000... .......... U U U 4 4 4 +extb 32 . . 0100100111000... .......... . . U . . 4 +illegal 0 . . 0100101011111100 .......... U U U 4 4 4 +jmp 32 . . 0100111011...... A..DXWLdx. U U U 4 4 0 +jsr 32 . . 0100111010...... A..DXWLdx. U U U 12 12 0 +lea 32 . . 0100...111...... A..DXWLdx. U U U 0 0 2 +link 16 . a7 0100111001010111 .......... U U U 16 16 5 +link 16 . . 0100111001010... .......... U U U 16 16 5 +link 32 . a7 0100100000001111 .......... . . U . . 6 +link 32 . . 0100100000001... .......... . . U . . 6 +lsr 8 s . 1110...000001... .......... U U U 6 6 4 +lsr 16 s . 1110...001001... .......... U U U 6 6 4 +lsr 32 s . 1110...010001... .......... U U U 8 8 4 +lsr 8 r . 1110...000101... .......... U U U 6 6 6 +lsr 16 r . 1110...001101... .......... U U U 6 6 6 +lsr 32 r . 1110...010101... .......... U U U 8 8 6 +lsr 16 . . 1110001011...... A+-DXWL... U U U 8 8 5 +lsl 8 s . 1110...100001... .......... U U U 6 6 4 +lsl 16 s . 1110...101001... .......... U U U 6 6 4 +lsl 32 s . 1110...110001... .......... U U U 8 8 4 +lsl 8 r . 1110...100101... .......... U U U 6 6 6 +lsl 16 r . 1110...101101... .......... U U U 6 6 6 +lsl 32 r . 1110...110101... .......... U U U 8 8 6 +lsl 16 . . 1110001111...... A+-DXWL... U U U 8 8 5 +move 8 d d 0001...000000... .......... U U U 4 4 2 +move 8 d . 0001...000...... A+-DXWLdxI U U U 4 4 2 +move 8 ai d 0001...010000... .......... U U U 8 8 4 +move 8 ai . 0001...010...... A+-DXWLdxI U U U 8 8 4 +move 8 pi d 0001...011000... .......... U U U 8 8 4 +move 8 pi . 0001...011...... A+-DXWLdxI U U U 8 8 4 +move 8 pi7 d 0001111011000... .......... U U U 8 8 4 +move 8 pi7 . 0001111011...... A+-DXWLdxI U U U 8 8 4 +move 8 pd d 0001...100000... .......... U U U 8 8 5 +move 8 pd . 0001...100...... A+-DXWLdxI U U U 8 8 5 +move 8 pd7 d 0001111100000... .......... U U U 8 8 5 +move 8 pd7 . 0001111100...... A+-DXWLdxI U U U 8 8 5 +move 8 di d 0001...101000... .......... U U U 12 12 5 +move 8 di . 0001...101...... A+-DXWLdxI U U U 12 12 5 +move 8 ix d 0001...110000... .......... U U U 14 14 7 +move 8 ix . 0001...110...... A+-DXWLdxI U U U 14 14 7 +move 8 aw d 0001000111000... .......... U U U 12 12 4 +move 8 aw . 0001000111...... A+-DXWLdxI U U U 12 12 4 +move 8 al d 0001001111000... .......... U U U 16 16 6 +move 8 al . 0001001111...... A+-DXWLdxI U U U 16 16 6 +move 16 d d 0011...000000... .......... U U U 4 4 2 +move 16 d a 0011...000001... .......... U U U 4 4 2 +move 16 d . 0011...000...... A+-DXWLdxI U U U 4 4 2 +move 16 ai d 0011...010000... .......... U U U 8 8 4 +move 16 ai a 0011...010001... .......... U U U 8 8 4 +move 16 ai . 0011...010...... A+-DXWLdxI U U U 8 8 4 +move 16 pi d 0011...011000... .......... U U U 8 8 4 +move 16 pi a 0011...011001... .......... U U U 8 8 4 +move 16 pi . 0011...011...... A+-DXWLdxI U U U 8 8 4 +move 16 pd d 0011...100000... .......... U U U 8 8 5 +move 16 pd a 0011...100001... .......... U U U 8 8 5 +move 16 pd . 0011...100...... A+-DXWLdxI U U U 8 8 5 +move 16 di d 0011...101000... .......... U U U 12 12 5 +move 16 di a 0011...101001... .......... U U U 12 12 5 +move 16 di . 0011...101...... A+-DXWLdxI U U U 12 12 5 +move 16 ix d 0011...110000... .......... U U U 14 14 7 +move 16 ix a 0011...110001... .......... U U U 14 14 7 +move 16 ix . 0011...110...... A+-DXWLdxI U U U 14 14 7 +move 16 aw d 0011000111000... .......... U U U 12 12 4 +move 16 aw a 0011000111001... .......... U U U 12 12 4 +move 16 aw . 0011000111...... A+-DXWLdxI U U U 12 12 4 +move 16 al d 0011001111000... .......... U U U 16 16 6 +move 16 al a 0011001111001... .......... U U U 16 16 6 +move 16 al . 0011001111...... A+-DXWLdxI U U U 16 16 6 +move 32 d d 0010...000000... .......... U U U 4 4 2 +move 32 d a 0010...000001... .......... U U U 4 4 2 +move 32 d . 0010...000...... A+-DXWLdxI U U U 4 4 2 +move 32 ai d 0010...010000... .......... U U U 12 12 4 +move 32 ai a 0010...010001... .......... U U U 12 12 4 +move 32 ai . 0010...010...... A+-DXWLdxI U U U 12 12 4 +move 32 pi d 0010...011000... .......... U U U 12 12 4 +move 32 pi a 0010...011001... .......... U U U 12 12 4 +move 32 pi . 0010...011...... A+-DXWLdxI U U U 12 12 4 +move 32 pd d 0010...100000... .......... U U U 12 14 5 +move 32 pd a 0010...100001... .......... U U U 12 14 5 +move 32 pd . 0010...100...... A+-DXWLdxI U U U 12 14 5 +move 32 di d 0010...101000... .......... U U U 16 16 5 +move 32 di a 0010...101001... .......... U U U 16 16 5 +move 32 di . 0010...101...... A+-DXWLdxI U U U 16 16 5 +move 32 ix d 0010...110000... .......... U U U 18 18 7 +move 32 ix a 0010...110001... .......... U U U 18 18 7 +move 32 ix . 0010...110...... A+-DXWLdxI U U U 18 18 7 +move 32 aw d 0010000111000... .......... U U U 16 16 4 +move 32 aw a 0010000111001... .......... U U U 16 16 4 +move 32 aw . 0010000111...... A+-DXWLdxI U U U 16 16 4 +move 32 al d 0010001111000... .......... U U U 20 20 6 +move 32 al a 0010001111001... .......... U U U 20 20 6 +move 32 al . 0010001111...... A+-DXWLdxI U U U 20 20 6 +movea 16 . d 0011...001000... .......... U U U 4 4 2 +movea 16 . a 0011...001001... .......... U U U 4 4 2 +movea 16 . . 0011...001...... A+-DXWLdxI U U U 4 4 2 +movea 32 . d 0010...001000... .......... U U U 4 4 2 +movea 32 . a 0010...001001... .......... U U U 4 4 2 +movea 32 . . 0010...001...... A+-DXWLdxI U U U 4 4 2 +move 16 frc d 0100001011000... .......... . U U . 4 4 +move 16 frc . 0100001011...... A+-DXWL... . U U . 8 4 +move 16 toc d 0100010011000... .......... U U U 12 12 4 +move 16 toc . 0100010011...... A+-DXWLdxI U U U 12 12 4 +move 16 frs d 0100000011000... .......... U S S 6 4 8 U only for 000 +move 16 frs . 0100000011...... A+-DXWL... U S S 8 8 8 U only for 000 +move 16 tos d 0100011011000... .......... S S S 12 12 8 +move 16 tos . 0100011011...... A+-DXWLdxI S S S 12 12 8 +move 32 fru . 0100111001101... .......... S S S 4 6 2 +move 32 tou . 0100111001100... .......... S S S 4 6 2 +movec 32 cr . 0100111001111010 .......... . S S . 12 6 +movec 32 rc . 0100111001111011 .......... . S S . 10 12 +movem 16 re pd 0100100010100... .......... U U U 8 8 4 +movem 16 re . 0100100010...... A..DXWL... U U U 8 8 4 +movem 32 re pd 0100100011100... .......... U U U 8 8 4 +movem 32 re . 0100100011...... A..DXWL... U U U 8 8 4 +movem 16 er pi 0100110010011... .......... U U U 12 12 8 +movem 16 er pcdi 0100110010111010 .......... U U U 16 16 9 +movem 16 er pcix 0100110010111011 .......... U U U 18 18 11 +movem 16 er . 0100110010...... A..DXWL... U U U 12 12 8 +movem 32 er pi 0100110011011... .......... U U U 12 12 8 +movem 32 er pcdi 0100110011111010 .......... U U U 20 20 9 +movem 32 er pcix 0100110011111011 .......... U U U 22 22 11 +movem 32 er . 0100110011...... A..DXWL... U U U 12 12 8 +movep 16 er . 0000...100001... .......... U U U 16 16 12 +movep 32 er . 0000...101001... .......... U U U 24 24 18 +movep 16 re . 0000...110001... .......... U U U 16 16 11 +movep 32 re . 0000...111001... .......... U U U 24 24 17 +moveq 32 . . 0111...0........ .......... U U U 4 4 2 +moves 8 . . 0000111000...... A+-DXWL... . S S . 14 5 +moves 16 . . 0000111001...... A+-DXWL... . S S . 14 5 +moves 32 . . 0000111010...... A+-DXWL... . S S . 16 5 +muls 16 . d 1100...111000... .......... U U U 54 32 27 +muls 16 . . 1100...111...... A+-DXWLdxI U U U 54 32 27 +mulu 16 . d 1100...011000... .......... U U U 54 30 27 +mulu 16 . . 1100...011...... A+-DXWLdxI U U U 54 30 27 +mull 32 . d 0100110000000... .......... . . U . . 43 +mull 32 . . 0100110000...... A+-DXWLdxI . . U . . 43 +nbcd 8 . d 0100100000000... .......... U U U 6 6 6 +nbcd 8 . . 0100100000...... A+-DXWL... U U U 8 8 6 +neg 8 . d 0100010000000... .......... U U U 4 4 2 +neg 8 . . 0100010000...... A+-DXWL... U U U 8 8 4 +neg 16 . d 0100010001000... .......... U U U 4 4 2 +neg 16 . . 0100010001...... A+-DXWL... U U U 8 8 4 +neg 32 . d 0100010010000... .......... U U U 6 6 2 +neg 32 . . 0100010010...... A+-DXWL... U U U 12 12 4 +negx 8 . d 0100000000000... .......... U U U 4 4 2 +negx 8 . . 0100000000...... A+-DXWL... U U U 8 8 4 +negx 16 . d 0100000001000... .......... U U U 4 4 2 +negx 16 . . 0100000001...... A+-DXWL... U U U 8 8 4 +negx 32 . d 0100000010000... .......... U U U 6 6 2 +negx 32 . . 0100000010...... A+-DXWL... U U U 12 12 4 +nop 0 . . 0100111001110001 .......... U U U 4 4 2 +not 8 . d 0100011000000... .......... U U U 4 4 2 +not 8 . . 0100011000...... A+-DXWL... U U U 8 8 4 +not 16 . d 0100011001000... .......... U U U 4 4 2 +not 16 . . 0100011001...... A+-DXWL... U U U 8 8 4 +not 32 . d 0100011010000... .......... U U U 6 6 2 +not 32 . . 0100011010...... A+-DXWL... U U U 12 12 4 +or 8 er d 1000...000000... .......... U U U 4 4 2 +or 8 er . 1000...000...... A+-DXWLdxI U U U 4 4 2 +or 16 er d 1000...001000... .......... U U U 4 4 2 +or 16 er . 1000...001...... A+-DXWLdxI U U U 4 4 2 +or 32 er d 1000...010000... .......... U U U 6 6 2 +or 32 er . 1000...010...... A+-DXWLdxI U U U 6 6 2 +or 8 re . 1000...100...... A+-DXWL... U U U 8 8 4 +or 16 re . 1000...101...... A+-DXWL... U U U 8 8 4 +or 32 re . 1000...110...... A+-DXWL... U U U 12 12 4 +ori 16 toc . 0000000000111100 .......... U U U 20 16 12 +ori 16 tos . 0000000001111100 .......... S S S 20 16 12 +ori 8 . d 0000000000000... .......... U U U 8 8 2 +ori 8 . . 0000000000...... A+-DXWL... U U U 12 12 4 +ori 16 . d 0000000001000... .......... U U U 8 8 2 +ori 16 . . 0000000001...... A+-DXWL... U U U 12 12 4 +ori 32 . d 0000000010000... .......... U U U 16 14 2 +ori 32 . . 0000000010...... A+-DXWL... U U U 20 20 4 +pack 16 rr . 1000...101000... .......... . . U . . 6 +pack 16 mm ax7 1000111101001... .......... . . U . . 13 +pack 16 mm ay7 1000...101001111 .......... . . U . . 13 +pack 16 mm axy7 1000111101001111 .......... . . U . . 13 +pack 16 mm . 1000...101001... .......... . . U . . 13 +pea 32 . . 0100100001...... A..DXWLdx. U U U 6 6 5 +reset 0 . . 0100111001110000 .......... S S S 0 0 0 +ror 8 s . 1110...000011... .......... U U U 6 6 8 +ror 16 s . 1110...001011... .......... U U U 6 6 8 +ror 32 s . 1110...010011... .......... U U U 8 8 8 +ror 8 r . 1110...000111... .......... U U U 6 6 8 +ror 16 r . 1110...001111... .......... U U U 6 6 8 +ror 32 r . 1110...010111... .......... U U U 8 8 8 +ror 16 . . 1110011011...... A+-DXWL... U U U 8 8 7 +rol 8 s . 1110...100011... .......... U U U 6 6 8 +rol 16 s . 1110...101011... .......... U U U 6 6 8 +rol 32 s . 1110...110011... .......... U U U 8 8 8 +rol 8 r . 1110...100111... .......... U U U 6 6 8 +rol 16 r . 1110...101111... .......... U U U 6 6 8 +rol 32 r . 1110...110111... .......... U U U 8 8 8 +rol 16 . . 1110011111...... A+-DXWL... U U U 8 8 7 +roxr 8 s . 1110...000010... .......... U U U 6 6 12 +roxr 16 s . 1110...001010... .......... U U U 6 6 12 +roxr 32 s . 1110...010010... .......... U U U 8 8 12 +roxr 8 r . 1110...000110... .......... U U U 6 6 12 +roxr 16 r . 1110...001110... .......... U U U 6 6 12 +roxr 32 r . 1110...010110... .......... U U U 8 8 12 +roxr 16 . . 1110010011...... A+-DXWL... U U U 8 8 5 +roxl 8 s . 1110...100010... .......... U U U 6 6 12 +roxl 16 s . 1110...101010... .......... U U U 6 6 12 +roxl 32 s . 1110...110010... .......... U U U 8 8 12 +roxl 8 r . 1110...100110... .......... U U U 6 6 12 +roxl 16 r . 1110...101110... .......... U U U 6 6 12 +roxl 32 r . 1110...110110... .......... U U U 8 8 12 +roxl 16 . . 1110010111...... A+-DXWL... U U U 8 8 5 +rtd 32 . . 0100111001110100 .......... . U U . 16 10 +rte 32 . . 0100111001110011 .......... S S S 20 24 20 bus fault not emulated +rtm 32 . . 000001101100.... .......... . . U . . 19 not properly emulated +rtr 32 . . 0100111001110111 .......... U U U 20 20 14 +rts 32 . . 0100111001110101 .......... U U U 16 16 10 +sbcd 8 rr . 1000...100000... .......... U U U 6 6 4 +sbcd 8 mm ax7 1000111100001... .......... U U U 18 18 16 +sbcd 8 mm ay7 1000...100001111 .......... U U U 18 18 16 +sbcd 8 mm axy7 1000111100001111 .......... U U U 18 18 16 +sbcd 8 mm . 1000...100001... .......... U U U 18 18 16 +st 8 . d 0101000011000... .......... U U U 6 4 4 +st 8 . . 0101000011...... A+-DXWL... U U U 8 8 6 +sf 8 . d 0101000111000... .......... U U U 4 4 4 +sf 8 . . 0101000111...... A+-DXWL... U U U 8 8 6 +scc 8 . d 0101....11000... .......... U U U 4 4 4 +scc 8 . . 0101....11...... A+-DXWL... U U U 8 8 6 +stop 0 . . 0100111001110010 .......... S S S 4 4 8 +sub 8 er d 1001...000000... .......... U U U 4 4 2 +sub 8 er . 1001...000...... A+-DXWLdxI U U U 4 4 2 +sub 16 er d 1001...001000... .......... U U U 4 4 2 +sub 16 er a 1001...001001... .......... U U U 4 4 2 +sub 16 er . 1001...001...... A+-DXWLdxI U U U 4 4 2 +sub 32 er d 1001...010000... .......... U U U 6 6 2 +sub 32 er a 1001...010001... .......... U U U 6 6 2 +sub 32 er . 1001...010...... A+-DXWLdxI U U U 6 6 2 +sub 8 re . 1001...100...... A+-DXWL... U U U 8 8 4 +sub 16 re . 1001...101...... A+-DXWL... U U U 8 8 4 +sub 32 re . 1001...110...... A+-DXWL... U U U 12 12 4 +suba 16 . d 1001...011000... .......... U U U 8 8 2 +suba 16 . a 1001...011001... .......... U U U 8 8 2 +suba 16 . . 1001...011...... A+-DXWLdxI U U U 8 8 2 +suba 32 . d 1001...111000... .......... U U U 6 6 2 +suba 32 . a 1001...111001... .......... U U U 6 6 2 +suba 32 . . 1001...111...... A+-DXWLdxI U U U 6 6 2 +subi 8 . d 0000010000000... .......... U U U 8 8 2 +subi 8 . . 0000010000...... A+-DXWL... U U U 12 12 4 +subi 16 . d 0000010001000... .......... U U U 8 8 2 +subi 16 . . 0000010001...... A+-DXWL... U U U 12 12 4 +subi 32 . d 0000010010000... .......... U U U 16 14 2 +subi 32 . . 0000010010...... A+-DXWL... U U U 20 20 4 +subq 8 . d 0101...100000... .......... U U U 4 4 2 +subq 8 . . 0101...100...... A+-DXWL... U U U 8 8 4 +subq 16 . d 0101...101000... .......... U U U 4 4 2 +subq 16 . a 0101...101001... .......... U U U 8 4 2 +subq 16 . . 0101...101...... A+-DXWL... U U U 8 8 4 +subq 32 . d 0101...110000... .......... U U U 8 8 2 +subq 32 . a 0101...110001... .......... U U U 8 8 2 +subq 32 . . 0101...110...... A+-DXWL... U U U 12 12 4 +subx 8 rr . 1001...100000... .......... U U U 4 4 2 +subx 16 rr . 1001...101000... .......... U U U 4 4 2 +subx 32 rr . 1001...110000... .......... U U U 8 6 2 +subx 8 mm ax7 1001111100001... .......... U U U 18 18 12 +subx 8 mm ay7 1001...100001111 .......... U U U 18 18 12 +subx 8 mm axy7 1001111100001111 .......... U U U 18 18 12 +subx 8 mm . 1001...100001... .......... U U U 18 18 12 +subx 16 mm . 1001...101001... .......... U U U 18 18 12 +subx 32 mm . 1001...110001... .......... U U U 30 30 12 +swap 32 . . 0100100001000... .......... U U U 4 4 4 +tas 8 . d 0100101011000... .......... U U U 4 4 4 +tas 8 . . 0100101011...... A+-DXWL... U U U 14 14 12 +trap 0 . . 010011100100.... .......... U U U 4 4 4 +trapt 0 . . 0101000011111100 .......... . . U . . 4 +trapt 16 . . 0101000011111010 .......... . . U . . 6 +trapt 32 . . 0101000011111011 .......... . . U . . 8 +trapf 0 . . 0101000111111100 .......... . . U . . 4 +trapf 16 . . 0101000111111010 .......... . . U . . 6 +trapf 32 . . 0101000111111011 .......... . . U . . 8 +trapcc 0 . . 0101....11111100 .......... . . U . . 4 +trapcc 16 . . 0101....11111010 .......... . . U . . 6 +trapcc 32 . . 0101....11111011 .......... . . U . . 8 +trapv 0 . . 0100111001110110 .......... U U U 4 4 4 +tst 8 . d 0100101000000... .......... U U U 4 4 2 +tst 8 . . 0100101000...... A+-DXWL... U U U 4 4 2 +tst 8 . pcdi 0100101000111010 .......... . . U . . 7 +tst 8 . pcix 0100101000111011 .......... . . U . . 9 +tst 8 . i 0100101000111100 .......... . . U . . 6 +tst 16 . d 0100101001000... .......... U U U 4 4 2 +tst 16 . a 0100101001001... .......... . . U . . 2 +tst 16 . . 0100101001...... A+-DXWL... U U U 4 4 2 +tst 16 . pcdi 0100101001111010 .......... . . U . . 7 +tst 16 . pcix 0100101001111011 .......... . . U . . 9 +tst 16 . i 0100101001111100 .......... . . U . . 6 +tst 32 . d 0100101010000... .......... U U U 4 4 2 +tst 32 . a 0100101010001... .......... . . U . . 2 +tst 32 . . 0100101010...... A+-DXWL... U U U 4 4 2 +tst 32 . pcdi 0100101010111010 .......... . . U . . 7 +tst 32 . pcix 0100101010111011 .......... . . U . . 9 +tst 32 . i 0100101010111100 .......... . . U . . 6 +unlk 32 . a7 0100111001011111 .......... U U U 12 12 6 +unlk 32 . . 0100111001011... .......... U U U 12 12 6 +unpk 16 rr . 1000...110000... .......... . . U . . 8 +unpk 16 mm ax7 1000111110001... .......... . . U . . 13 +unpk 16 mm ay7 1000...110001111 .......... . . U . . 13 +unpk 16 mm axy7 1000111110001111 .......... . . U . . 13 +unpk 16 mm . 1000...110001... .......... . . U . . 13 + + + +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +M68KMAKE_OPCODE_HANDLER_BODY + +M68KMAKE_OP(1010, 0, ., .) +{ + m68ki_exception_1010(); +} + + +M68KMAKE_OP(1111, 0, ., .) +{ + m68ki_exception_1111(); +} + + +M68KMAKE_OP(abcd, 8, rr, .) +{ + uint* r_dst = &DX; + uint src = DY; + uint dst = *r_dst; + uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res += 6; + res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res -= 0xa0; + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; +} + + +M68KMAKE_OP(abcd, 8, mm, ax7) +{ + uint src = OPER_AY_PD_8(); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res += 6; + res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res -= 0xa0; + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(abcd, 8, mm, ay7) +{ + uint src = OPER_A7_PD_8(); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res += 6; + res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res -= 0xa0; + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(abcd, 8, mm, axy7) +{ + uint src = OPER_A7_PD_8(); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res += 6; + res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res -= 0xa0; + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(abcd, 8, mm, .) +{ + uint src = OPER_AY_PD_8(); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res += 6; + res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res -= 0xa0; + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(add, 8, er, d) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_8(DY); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(add, 8, er, .) +{ + uint* r_dst = &DX; + uint src = M68KMAKE_GET_OPER_AY_8; + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(add, 16, er, d) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_16(DY); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(add, 16, er, a) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_16(AY); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(add, 16, er, .) +{ + uint* r_dst = &DX; + uint src = M68KMAKE_GET_OPER_AY_16; + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(add, 32, er, d) +{ + uint* r_dst = &DX; + uint src = DY; + uint dst = *r_dst; + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(add, 32, er, a) +{ + uint* r_dst = &DX; + uint src = AY; + uint dst = *r_dst; + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(add, 32, er, .) +{ + uint* r_dst = &DX; + uint src = M68KMAKE_GET_OPER_AY_32; + uint dst = *r_dst; + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(add, 8, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint src = MASK_OUT_ABOVE_8(DX); + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +M68KMAKE_OP(add, 16, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = MASK_OUT_ABOVE_16(DX); + uint dst = m68ki_read_16(ea); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +M68KMAKE_OP(add, 32, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_32; + uint src = DX; + uint dst = m68ki_read_32(ea); + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +M68KMAKE_OP(adda, 16, ., d) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + MAKE_INT_16(DY)); +} + + +M68KMAKE_OP(adda, 16, ., a) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + MAKE_INT_16(AY)); +} + + +M68KMAKE_OP(adda, 16, ., .) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + MAKE_INT_16(M68KMAKE_GET_OPER_AY_16)); +} + + +M68KMAKE_OP(adda, 32, ., d) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + DY); +} + + +M68KMAKE_OP(adda, 32, ., a) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + AY); +} + + +M68KMAKE_OP(adda, 32, ., .) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + M68KMAKE_GET_OPER_AY_32); +} + + +M68KMAKE_OP(addi, 8, ., d) +{ + uint* r_dst = &DY; + uint src = OPER_I_8(); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(addi, 8, ., .) +{ + uint src = OPER_I_8(); + uint ea = M68KMAKE_GET_EA_AY_8; + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +M68KMAKE_OP(addi, 16, ., d) +{ + uint* r_dst = &DY; + uint src = OPER_I_16(); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(addi, 16, ., .) +{ + uint src = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_16; + uint dst = m68ki_read_16(ea); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +M68KMAKE_OP(addi, 32, ., d) +{ + uint* r_dst = &DY; + uint src = OPER_I_32(); + uint dst = *r_dst; + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(addi, 32, ., .) +{ + uint src = OPER_I_32(); + uint ea = M68KMAKE_GET_EA_AY_32; + uint dst = m68ki_read_32(ea); + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +M68KMAKE_OP(addq, 8, ., d) +{ + uint* r_dst = &DY; + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(addq, 8, ., .) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = M68KMAKE_GET_EA_AY_8; + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +M68KMAKE_OP(addq, 16, ., d) +{ + uint* r_dst = &DY; + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(addq, 16, ., a) +{ + uint* r_dst = &AY; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + (((REG_IR >> 9) - 1) & 7) + 1); +} + + +M68KMAKE_OP(addq, 16, ., .) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = M68KMAKE_GET_EA_AY_16; + uint dst = m68ki_read_16(ea); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +M68KMAKE_OP(addq, 32, ., d) +{ + uint* r_dst = &DY; + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint dst = *r_dst; + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(addq, 32, ., a) +{ + uint* r_dst = &AY; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + (((REG_IR >> 9) - 1) & 7) + 1); +} + + +M68KMAKE_OP(addq, 32, ., .) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = M68KMAKE_GET_EA_AY_32; + uint dst = m68ki_read_32(ea); + uint res = src + dst; + + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +M68KMAKE_OP(addx, 8, rr, .) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_8(DY); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; +} + + +M68KMAKE_OP(addx, 16, rr, .) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_16(DY); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + + res = MASK_OUT_ABOVE_16(res); + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; +} + + +M68KMAKE_OP(addx, 32, rr, .) +{ + uint* r_dst = &DX; + uint src = DY; + uint dst = *r_dst; + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + + res = MASK_OUT_ABOVE_32(res); + FLAG_Z |= res; + + *r_dst = res; +} + + +M68KMAKE_OP(addx, 8, mm, ax7) +{ + uint src = OPER_AY_PD_8(); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(addx, 8, mm, ay7) +{ + uint src = OPER_A7_PD_8(); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(addx, 8, mm, axy7) +{ + uint src = OPER_A7_PD_8(); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(addx, 8, mm, .) +{ + uint src = OPER_AY_PD_8(); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(addx, 16, mm, .) +{ + uint src = OPER_AY_PD_16(); + uint ea = EA_AX_PD_16(); + uint dst = m68ki_read_16(ea); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + + res = MASK_OUT_ABOVE_16(res); + FLAG_Z |= res; + + m68ki_write_16(ea, res); +} + + +M68KMAKE_OP(addx, 32, mm, .) +{ + uint src = OPER_AY_PD_32(); + uint ea = EA_AX_PD_32(); + uint dst = m68ki_read_32(ea); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + + res = MASK_OUT_ABOVE_32(res); + FLAG_Z |= res; + + m68ki_write_32(ea, res); +} + + +M68KMAKE_OP(and, 8, er, d) +{ + FLAG_Z = MASK_OUT_ABOVE_8(DX &= (DY | 0xffffff00)); + + FLAG_N = NFLAG_8(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(and, 8, er, .) +{ + FLAG_Z = MASK_OUT_ABOVE_8(DX &= (M68KMAKE_GET_OPER_AY_8 | 0xffffff00)); + + FLAG_N = NFLAG_8(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(and, 16, er, d) +{ + FLAG_Z = MASK_OUT_ABOVE_16(DX &= (DY | 0xffff0000)); + + FLAG_N = NFLAG_16(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(and, 16, er, .) +{ + FLAG_Z = MASK_OUT_ABOVE_16(DX &= (M68KMAKE_GET_OPER_AY_16 | 0xffff0000)); + + FLAG_N = NFLAG_16(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(and, 32, er, d) +{ + FLAG_Z = DX &= DY; + + FLAG_N = NFLAG_32(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(and, 32, er, .) +{ + FLAG_Z = DX &= M68KMAKE_GET_OPER_AY_32; + + FLAG_N = NFLAG_32(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(and, 8, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint res = DX & m68ki_read_8(ea); + + FLAG_N = NFLAG_8(res); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +M68KMAKE_OP(and, 16, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint res = DX & m68ki_read_16(ea); + + FLAG_N = NFLAG_16(res); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +M68KMAKE_OP(and, 32, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_32; + uint res = DX & m68ki_read_32(ea); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_32(ea, res); +} + + +M68KMAKE_OP(andi, 8, ., d) +{ + FLAG_Z = MASK_OUT_ABOVE_8(DY &= (OPER_I_8() | 0xffffff00)); + + FLAG_N = NFLAG_8(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(andi, 8, ., .) +{ + uint src = OPER_I_8(); + uint ea = M68KMAKE_GET_EA_AY_8; + uint res = src & m68ki_read_8(ea); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(andi, 16, ., d) +{ + FLAG_Z = MASK_OUT_ABOVE_16(DY &= (OPER_I_16() | 0xffff0000)); + + FLAG_N = NFLAG_16(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(andi, 16, ., .) +{ + uint src = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_16; + uint res = src & m68ki_read_16(ea); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_16(ea, res); +} + + +M68KMAKE_OP(andi, 32, ., d) +{ + FLAG_Z = DY &= (OPER_I_32()); + + FLAG_N = NFLAG_32(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(andi, 32, ., .) +{ + uint src = OPER_I_32(); + uint ea = M68KMAKE_GET_EA_AY_32; + uint res = src & m68ki_read_32(ea); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_32(ea, res); +} + + +M68KMAKE_OP(andi, 16, toc, .) +{ + m68ki_set_ccr(m68ki_get_ccr() & OPER_I_16()); +} + + +M68KMAKE_OP(andi, 16, tos, .) +{ + if(FLAG_S) + { + uint src = OPER_I_16(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_set_sr(m68ki_get_sr() & src); + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(asr, 8, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = src >> shift; + + if(GET_MSB_8(src)) + res |= m68ki_shift_8_table[shift]; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_X = FLAG_C = src << (9-shift); +} + + +M68KMAKE_OP(asr, 16, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = src >> shift; + + if(GET_MSB_16(src)) + res |= m68ki_shift_16_table[shift]; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_X = FLAG_C = src << (9-shift); +} + + +M68KMAKE_OP(asr, 32, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = *r_dst; + uint res = src >> shift; + + if(GET_MSB_32(src)) + res |= m68ki_shift_32_table[shift]; + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_X = FLAG_C = src << (9-shift); +} + + +M68KMAKE_OP(asr, 8, r, .) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = src >> shift; + + if(shift != 0) + { + USE_CYCLES(shift<<CYC_SHIFT); + + if(shift < 8) + { + if(GET_MSB_8(src)) + res |= m68ki_shift_8_table[shift]; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_X = FLAG_C = src << (9-shift); + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + if(GET_MSB_8(src)) + { + *r_dst |= 0xff; + FLAG_C = CFLAG_SET; + FLAG_X = XFLAG_SET; + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + return; + } + + *r_dst &= 0xffffff00; + FLAG_C = CFLAG_CLEAR; + FLAG_X = XFLAG_CLEAR; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_8(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(asr, 16, r, .) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = src >> shift; + + if(shift != 0) + { + USE_CYCLES(shift<<CYC_SHIFT); + + if(shift < 16) + { + if(GET_MSB_16(src)) + res |= m68ki_shift_16_table[shift]; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_C = FLAG_X = (src >> (shift - 1))<<8; + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + if(GET_MSB_16(src)) + { + *r_dst |= 0xffff; + FLAG_C = CFLAG_SET; + FLAG_X = XFLAG_SET; + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + return; + } + + *r_dst &= 0xffff0000; + FLAG_C = CFLAG_CLEAR; + FLAG_X = XFLAG_CLEAR; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_16(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(asr, 32, r, .) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = *r_dst; + uint res = src >> shift; + + if(shift != 0) + { + USE_CYCLES(shift<<CYC_SHIFT); + + if(shift < 32) + { + if(GET_MSB_32(src)) + res |= m68ki_shift_32_table[shift]; + + *r_dst = res; + + FLAG_C = FLAG_X = (src >> (shift - 1))<<8; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + if(GET_MSB_32(src)) + { + *r_dst = 0xffffffff; + FLAG_C = CFLAG_SET; + FLAG_X = XFLAG_SET; + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + return; + } + + *r_dst = 0; + FLAG_C = CFLAG_CLEAR; + FLAG_X = XFLAG_CLEAR; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_32(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(asr, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = m68ki_read_16(ea); + uint res = src >> 1; + + if(GET_MSB_16(src)) + res |= 0x8000; + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = FLAG_X = src << 8; +} + + +M68KMAKE_OP(asl, 8, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = MASK_OUT_ABOVE_8(src << shift); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_X = FLAG_C = src << shift; + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + src &= m68ki_shift_8_table[shift + 1]; + FLAG_V = (!(src == 0 || (src == m68ki_shift_8_table[shift + 1] && shift < 8)))<<7; +} + + +M68KMAKE_OP(asl, 16, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = MASK_OUT_ABOVE_16(src << shift); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_X = FLAG_C = src >> (8-shift); + src &= m68ki_shift_16_table[shift + 1]; + FLAG_V = (!(src == 0 || src == m68ki_shift_16_table[shift + 1]))<<7; +} + + +M68KMAKE_OP(asl, 32, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32(src << shift); + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_X = FLAG_C = src >> (24-shift); + src &= m68ki_shift_32_table[shift + 1]; + FLAG_V = (!(src == 0 || src == m68ki_shift_32_table[shift + 1]))<<7; +} + + +M68KMAKE_OP(asl, 8, r, .) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = MASK_OUT_ABOVE_8(src << shift); + + if(shift != 0) + { + USE_CYCLES(shift<<CYC_SHIFT); + + if(shift < 8) + { + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + FLAG_X = FLAG_C = src << shift; + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + src &= m68ki_shift_8_table[shift + 1]; + FLAG_V = (!(src == 0 || src == m68ki_shift_8_table[shift + 1]))<<7; + return; + } + + *r_dst &= 0xffffff00; + FLAG_X = FLAG_C = ((shift == 8 ? src & 1 : 0))<<8; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = (!(src == 0))<<7; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_8(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(asl, 16, r, .) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = MASK_OUT_ABOVE_16(src << shift); + + if(shift != 0) + { + USE_CYCLES(shift<<CYC_SHIFT); + + if(shift < 16) + { + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + FLAG_X = FLAG_C = (src << shift) >> 8; + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + src &= m68ki_shift_16_table[shift + 1]; + FLAG_V = (!(src == 0 || src == m68ki_shift_16_table[shift + 1]))<<7; + return; + } + + *r_dst &= 0xffff0000; + FLAG_X = FLAG_C = ((shift == 16 ? src & 1 : 0))<<8; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = (!(src == 0))<<7; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_16(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(asl, 32, r, .) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32(src << shift); + + if(shift != 0) + { + USE_CYCLES(shift<<CYC_SHIFT); + + if(shift < 32) + { + *r_dst = res; + FLAG_X = FLAG_C = (src >> (32 - shift)) << 8; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + src &= m68ki_shift_32_table[shift + 1]; + FLAG_V = (!(src == 0 || src == m68ki_shift_32_table[shift + 1]))<<7; + return; + } + + *r_dst = 0; + FLAG_X = FLAG_C = ((shift == 32 ? src & 1 : 0))<<8; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = (!(src == 0))<<7; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_32(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(asl, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = m68ki_read_16(ea); + uint res = MASK_OUT_ABOVE_16(src << 1); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_X = FLAG_C = src >> 7; + src &= 0xc000; + FLAG_V = (!(src == 0 || src == 0xc000))<<7; +} + + +M68KMAKE_OP(bcc, 8, ., .) +{ + if(M68KMAKE_CC) + { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR)); + return; + } + USE_CYCLES(CYC_BCC_NOTAKE_B); +} + + +M68KMAKE_OP(bcc, 16, ., .) +{ + if(M68KMAKE_CC) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(offset); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_BCC_NOTAKE_W); +} + + +M68KMAKE_OP(bcc, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(M68KMAKE_CC) + { + uint offset = OPER_I_32(); + REG_PC -= 4; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_32(offset); + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bchg, 32, r, d) +{ + uint* r_dst = &DY; + uint mask = 1 << (DX & 0x1f); + + FLAG_Z = *r_dst & mask; + *r_dst ^= mask; +} + + +M68KMAKE_OP(bchg, 8, r, .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src ^ mask); +} + + +M68KMAKE_OP(bchg, 32, s, d) +{ + uint* r_dst = &DY; + uint mask = 1 << (OPER_I_8() & 0x1f); + + FLAG_Z = *r_dst & mask; + *r_dst ^= mask; +} + + +M68KMAKE_OP(bchg, 8, s, .) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = M68KMAKE_GET_EA_AY_8; + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src ^ mask); +} + + +M68KMAKE_OP(bclr, 32, r, d) +{ + uint* r_dst = &DY; + uint mask = 1 << (DX & 0x1f); + + FLAG_Z = *r_dst & mask; + *r_dst &= ~mask; +} + + +M68KMAKE_OP(bclr, 8, r, .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src & ~mask); +} + + +M68KMAKE_OP(bclr, 32, s, d) +{ + uint* r_dst = &DY; + uint mask = 1 << (OPER_I_8() & 0x1f); + + FLAG_Z = *r_dst & mask; + *r_dst &= ~mask; +} + + +M68KMAKE_OP(bclr, 8, s, .) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = M68KMAKE_GET_EA_AY_8; + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src & ~mask); +} + + +M68KMAKE_OP(bfchg, 32, ., d) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint* data = &DY; + uint64 mask; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + offset &= 31; + width = ((width-1) & 31) + 1; + + mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask = ROR_32(mask, offset); + + FLAG_N = NFLAG_32(*data<<offset); + FLAG_Z = *data & mask; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + *data ^= mask; + + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfchg, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = M68KMAKE_GET_EA_AY_8; + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = NFLAG_32(data_long << offset); + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, data_long ^ mask_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, data_byte ^ mask_byte); + } + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfclr, 32, ., d) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint* data = &DY; + uint64 mask; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + + offset &= 31; + width = ((width-1) & 31) + 1; + + + mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask = ROR_32(mask, offset); + + FLAG_N = NFLAG_32(*data<<offset); + FLAG_Z = *data & mask; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + *data &= ~mask; + + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfclr, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = M68KMAKE_GET_EA_AY_8; + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = NFLAG_32(data_long << offset); + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, data_long & ~mask_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, data_byte & ~mask_byte); + } + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfexts, 32, ., d) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint64 data = DY; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + offset &= 31; + width = ((width-1) & 31) + 1; + + data = ROL_32(data, offset); + FLAG_N = NFLAG_32(data); + data = MAKE_INT_32(data) >> (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + REG_D[(word2>>12)&7] = data; + + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfexts, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint data; + uint ea = M68KMAKE_GET_EA_AY_8; + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + data = m68ki_read_32(ea); + + data = MASK_OUT_ABOVE_32(data<<offset); + + if((offset+width) > 32) + data |= (m68ki_read_8(ea+4) << offset) >> 8; + + FLAG_N = NFLAG_32(data); + data = MAKE_INT_32(data) >> (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + REG_D[(word2 >> 12) & 7] = data; + + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfextu, 32, ., d) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint64 data = DY; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + offset &= 31; + width = ((width-1) & 31) + 1; + + data = ROL_32(data, offset); + FLAG_N = NFLAG_32(data); + data >>= 32 - width; + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + REG_D[(word2>>12)&7] = data; + + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfextu, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint data; + uint ea = M68KMAKE_GET_EA_AY_8; + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + data = m68ki_read_32(ea); + data = MASK_OUT_ABOVE_32(data<<offset); + + if((offset+width) > 32) + data |= (m68ki_read_8(ea+4) << offset) >> 8; + + FLAG_N = NFLAG_32(data); + data >>= (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + REG_D[(word2 >> 12) & 7] = data; + + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfffo, 32, ., d) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint64 data = DY; + uint bit; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + offset &= 31; + width = ((width-1) & 31) + 1; + + data = ROL_32(data, offset); + FLAG_N = NFLAG_32(data); + data >>= 32 - width; + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + for(bit = 1<<(width-1);bit && !(data & bit);bit>>= 1) + offset++; + + REG_D[(word2>>12)&7] = offset; + + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfffo, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + sint local_offset; + uint width = word2; + uint data; + uint bit; + uint ea = M68KMAKE_GET_EA_AY_8; + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + local_offset = offset % 8; + if(local_offset < 0) + { + local_offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + data = m68ki_read_32(ea); + data = MASK_OUT_ABOVE_32(data<<local_offset); + + if((local_offset+width) > 32) + data |= (m68ki_read_8(ea+4) << local_offset) >> 8; + + FLAG_N = NFLAG_32(data); + data >>= (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + for(bit = 1<<(width-1);bit && !(data & bit);bit>>= 1) + offset++; + + REG_D[(word2>>12)&7] = offset; + + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfins, 32, ., d) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint* data = &DY; + uint64 mask; + uint64 insert = REG_D[(word2>>12)&7]; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + + offset &= 31; + width = ((width-1) & 31) + 1; + + + mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask = ROR_32(mask, offset); + + insert = MASK_OUT_ABOVE_32(insert << (32 - width)); + FLAG_N = NFLAG_32(insert); + FLAG_Z = insert; + insert = ROR_32(insert, offset); + + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + *data &= ~mask; + *data |= insert; + + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfins, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint insert_base = REG_D[(word2>>12)&7]; + uint insert_long; + uint insert_byte; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = M68KMAKE_GET_EA_AY_8; + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + insert_base = MASK_OUT_ABOVE_32(insert_base << (32 - width)); + FLAG_N = NFLAG_32(insert_base); + FLAG_Z = insert_base; + insert_long = insert_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, (data_long & ~mask_long) | insert_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + insert_byte = MASK_OUT_ABOVE_8(insert_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, (data_byte & ~mask_byte) | insert_byte); + } + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfset, 32, ., d) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint* data = &DY; + uint64 mask; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + + offset &= 31; + width = ((width-1) & 31) + 1; + + + mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask = ROR_32(mask, offset); + + FLAG_N = NFLAG_32(*data<<offset); + FLAG_Z = *data & mask; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + *data |= mask; + + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfset, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = M68KMAKE_GET_EA_AY_8; + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = NFLAG_32(data_long << offset); + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, data_long | mask_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, data_byte | mask_byte); + } + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bftst, 32, ., d) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint* data = &DY; + uint64 mask; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + + offset &= 31; + width = ((width-1) & 31) + 1; + + + mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask = ROR_32(mask, offset); + + FLAG_N = NFLAG_32(*data<<offset); + FLAG_Z = *data & mask; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bftst, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = M68KMAKE_GET_EA_AY_8; + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = ((data_long & (0x80000000 >> offset))<<offset)>>24; + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + } + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bkpt, 0, ., .) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + m68ki_bkpt_ack(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE) ? REG_IR & 7 : 0); /* auto-disable (see m68kcpu.h) */ + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bra, 8, ., .) +{ + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR)); + if(REG_PC == REG_PPC) + USE_ALL_CYCLES(); +} + + +M68KMAKE_OP(bra, 16, ., .) +{ + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(offset); + if(REG_PC == REG_PPC) + USE_ALL_CYCLES(); +} + + +M68KMAKE_OP(bra, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint offset = OPER_I_32(); + REG_PC -= 4; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_32(offset); + if(REG_PC == REG_PPC) + USE_ALL_CYCLES(); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bset, 32, r, d) +{ + uint* r_dst = &DY; + uint mask = 1 << (DX & 0x1f); + + FLAG_Z = *r_dst & mask; + *r_dst |= mask; +} + + +M68KMAKE_OP(bset, 8, r, .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src | mask); +} + + +M68KMAKE_OP(bset, 32, s, d) +{ + uint* r_dst = &DY; + uint mask = 1 << (OPER_I_8() & 0x1f); + + FLAG_Z = *r_dst & mask; + *r_dst |= mask; +} + + +M68KMAKE_OP(bset, 8, s, .) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = M68KMAKE_GET_EA_AY_8; + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src | mask); +} + + +M68KMAKE_OP(bsr, 8, ., .) +{ + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_push_32(REG_PC); + m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR)); +} + + +M68KMAKE_OP(bsr, 16, ., .) +{ + uint offset = OPER_I_16(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_push_32(REG_PC); + REG_PC -= 2; + m68ki_branch_16(offset); +} + + +M68KMAKE_OP(bsr, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint offset = OPER_I_32(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_push_32(REG_PC); + REG_PC -= 4; + m68ki_branch_32(offset); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(btst, 32, r, d) +{ + FLAG_Z = DY & (1 << (DX & 0x1f)); +} + + +M68KMAKE_OP(btst, 8, r, .) +{ + FLAG_Z = M68KMAKE_GET_OPER_AY_8 & (1 << (DX & 7)); +} + + +M68KMAKE_OP(btst, 32, s, d) +{ + FLAG_Z = DY & (1 << (OPER_I_8() & 0x1f)); +} + + +M68KMAKE_OP(btst, 8, s, .) +{ + uint bit = OPER_I_8() & 7; + + FLAG_Z = M68KMAKE_GET_OPER_AY_8 & (1 << bit); +} + + +M68KMAKE_OP(callm, 32, ., .) +{ + /* note: watch out for pcrelative modes */ + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + { + uint ea = M68KMAKE_GET_EA_AY_32; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + REG_PC += 2; +(void)ea; /* just to avoid an 'unused variable' warning */ + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cas, 8, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_8; + uint dest = m68ki_read_8(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - MASK_OUT_ABOVE_8(*compare); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(*compare, dest, res); + FLAG_C = CFLAG_8(res); + + if(COND_NE()) + *compare = MASK_OUT_BELOW_8(*compare) | dest; + else + { + USE_CYCLES(3); + m68ki_write_8(ea, MASK_OUT_ABOVE_8(REG_D[(word2 >> 6) & 7])); + } + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cas, 16, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_16; + uint dest = m68ki_read_16(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - MASK_OUT_ABOVE_16(*compare); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(*compare, dest, res); + FLAG_C = CFLAG_16(res); + + if(COND_NE()) + *compare = MASK_OUT_BELOW_16(*compare) | dest; + else + { + USE_CYCLES(3); + m68ki_write_16(ea, MASK_OUT_ABOVE_16(REG_D[(word2 >> 6) & 7])); + } + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cas, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_32; + uint dest = m68ki_read_32(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - *compare; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(*compare, dest, res); + FLAG_C = CFLAG_SUB_32(*compare, dest, res); + + if(COND_NE()) + *compare = dest; + else + { + USE_CYCLES(3); + m68ki_write_32(ea, REG_D[(word2 >> 6) & 7]); + } + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cas2, 16, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_32(); + uint* compare1 = ®_D[(word2 >> 16) & 7]; + uint ea1 = REG_DA[(word2 >> 28) & 15]; + uint dest1 = m68ki_read_16(ea1); + uint res1 = dest1 - MASK_OUT_ABOVE_16(*compare1); + uint* compare2 = ®_D[word2 & 7]; + uint ea2 = REG_DA[(word2 >> 12) & 15]; + uint dest2 = m68ki_read_16(ea2); + uint res2; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_16(res1); + FLAG_Z = MASK_OUT_ABOVE_16(res1); + FLAG_V = VFLAG_SUB_16(*compare1, dest1, res1); + FLAG_C = CFLAG_16(res1); + + if(COND_EQ()) + { + res2 = dest2 - MASK_OUT_ABOVE_16(*compare2); + + FLAG_N = NFLAG_16(res2); + FLAG_Z = MASK_OUT_ABOVE_16(res2); + FLAG_V = VFLAG_SUB_16(*compare2, dest2, res2); + FLAG_C = CFLAG_16(res2); + + if(COND_EQ()) + { + USE_CYCLES(3); + m68ki_write_16(ea1, REG_D[(word2 >> 22) & 7]); + m68ki_write_16(ea2, REG_D[(word2 >> 6) & 7]); + return; + } + } + *compare1 = BIT_1F(word2) ? MAKE_INT_16(dest1) : MASK_OUT_BELOW_16(*compare1) | dest1; + *compare2 = BIT_F(word2) ? MAKE_INT_16(dest2) : MASK_OUT_BELOW_16(*compare2) | dest2; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cas2, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_32(); + uint* compare1 = ®_D[(word2 >> 16) & 7]; + uint ea1 = REG_DA[(word2 >> 28) & 15]; + uint dest1 = m68ki_read_32(ea1); + uint res1 = dest1 - *compare1; + uint* compare2 = ®_D[word2 & 7]; + uint ea2 = REG_DA[(word2 >> 12) & 15]; + uint dest2 = m68ki_read_32(ea2); + uint res2; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_32(res1); + FLAG_Z = MASK_OUT_ABOVE_32(res1); + FLAG_V = VFLAG_SUB_32(*compare1, dest1, res1); + FLAG_C = CFLAG_SUB_32(*compare1, dest1, res1); + + if(COND_EQ()) + { + res2 = dest2 - *compare2; + + FLAG_N = NFLAG_32(res2); + FLAG_Z = MASK_OUT_ABOVE_32(res2); + FLAG_V = VFLAG_SUB_32(*compare2, dest2, res2); + FLAG_C = CFLAG_SUB_32(*compare2, dest2, res2); + + if(COND_EQ()) + { + USE_CYCLES(3); + m68ki_write_32(ea1, REG_D[(word2 >> 22) & 7]); + m68ki_write_32(ea2, REG_D[(word2 >> 6) & 7]); + return; + } + } + *compare1 = dest1; + *compare2 = dest2; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk, 16, ., d) +{ + sint src = MAKE_INT_16(DX); + sint bound = MAKE_INT_16(DY); + + FLAG_Z = ZFLAG_16(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(EXCEPTION_CHK); +} + + +M68KMAKE_OP(chk, 16, ., .) +{ + sint src = MAKE_INT_16(DX); + sint bound = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16); + + FLAG_Z = ZFLAG_16(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(EXCEPTION_CHK); +} + + +M68KMAKE_OP(chk, 32, ., d) +{ + logerror("%08x: Chk 32d\n",activecpu_get_pc()); + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + sint src = MAKE_INT_32(DX); + sint bound = MAKE_INT_32(DY); + + FLAG_Z = ZFLAG_32(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk, 32, ., .) +{ + logerror("%08x: Chk 32\n",activecpu_get_pc()); + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + sint src = MAKE_INT_32(DX); + sint bound = MAKE_INT_32(M68KMAKE_GET_OPER_AY_32); + + FLAG_Z = ZFLAG_32(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk2cmp2, 8, ., pcdi) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]&0xff; + uint ea = EA_PCDI_8(); + uint lower_bound = m68ki_read_pcrel_8(ea); + uint upper_bound = m68ki_read_pcrel_8(ea + 1); + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_8(compare) - MAKE_INT_8(lower_bound); + else + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + + FLAG_C = upper_bound - compare; + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk2cmp2, 8, ., pcix) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]&0xff; + uint ea = EA_PCIX_8(); + uint lower_bound = m68ki_read_pcrel_8(ea); + uint upper_bound = m68ki_read_pcrel_8(ea + 1); + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_8(compare) - MAKE_INT_8(lower_bound); + else + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + + FLAG_C = upper_bound - compare; + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk2cmp2, 8, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]&0xff; + uint ea = M68KMAKE_GET_EA_AY_8; + uint lower_bound = m68ki_read_8(ea); + uint upper_bound = m68ki_read_8(ea + 1); + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_8(compare) - MAKE_INT_8(lower_bound); + else + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + + FLAG_C = upper_bound - compare; + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk2cmp2, 16, ., pcdi) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]&0xffff; + uint ea = EA_PCDI_16(); + uint lower_bound = m68ki_read_pcrel_16(ea); + uint upper_bound = m68ki_read_pcrel_16(ea + 2); + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_16(compare) - MAKE_INT_16(lower_bound); + else + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + FLAG_C = CFLAG_16(FLAG_C); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_16(upper_bound) - MAKE_INT_16(compare); + else + FLAG_C = upper_bound - compare; + FLAG_C = CFLAG_16(FLAG_C); + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk2cmp2, 16, ., pcix) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]&0xffff; + uint ea = EA_PCIX_16(); + uint lower_bound = m68ki_read_pcrel_16(ea); + uint upper_bound = m68ki_read_pcrel_16(ea + 2); + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_16(compare) - MAKE_INT_16(lower_bound); + else + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + FLAG_C = CFLAG_16(FLAG_C); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_16(upper_bound) - MAKE_INT_16(compare); + else + FLAG_C = upper_bound - compare; + FLAG_C = CFLAG_16(FLAG_C); + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk2cmp2, 16, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]&0xffff; + uint ea = M68KMAKE_GET_EA_AY_16; + uint lower_bound = m68ki_read_16(ea); + uint upper_bound = m68ki_read_16(ea + 2); + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_16(compare) - MAKE_INT_16(lower_bound); + else + FLAG_C = compare - lower_bound; + + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + FLAG_C = CFLAG_16(FLAG_C); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_16(upper_bound) - MAKE_INT_16(compare); + else + FLAG_C = upper_bound - compare; + + FLAG_C = CFLAG_16(FLAG_C); + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk2cmp2, 32, ., pcdi) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]; + uint ea = EA_PCDI_32(); + uint lower_bound = m68ki_read_pcrel_32(ea); + uint upper_bound = m68ki_read_pcrel_32(ea + 4); + + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + FLAG_C = CFLAG_SUB_32(lower_bound, compare, FLAG_C); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + + FLAG_C = upper_bound - compare; + FLAG_C = CFLAG_SUB_32(compare, upper_bound, FLAG_C); + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk2cmp2, 32, ., pcix) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]; + uint ea = EA_PCIX_32(); + uint lower_bound = m68ki_read_pcrel_32(ea); + uint upper_bound = m68ki_read_pcrel_32(ea + 4); + + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + FLAG_C = CFLAG_SUB_32(lower_bound, compare, FLAG_C); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + + FLAG_C = upper_bound - compare; + FLAG_C = CFLAG_SUB_32(compare, upper_bound, FLAG_C); + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk2cmp2, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]; + uint ea = M68KMAKE_GET_EA_AY_32; + uint lower_bound = m68ki_read_32(ea); + uint upper_bound = m68ki_read_32(ea + 4); + + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + FLAG_C = CFLAG_SUB_32(lower_bound, compare, FLAG_C); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + + FLAG_C = upper_bound - compare; + FLAG_C = CFLAG_SUB_32(compare, upper_bound, FLAG_C); + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(clr, 8, ., d) +{ + DY &= 0xffffff00; + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +M68KMAKE_OP(clr, 8, ., .) +{ + m68ki_write_8(M68KMAKE_GET_EA_AY_8, 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +M68KMAKE_OP(clr, 16, ., d) +{ + DY &= 0xffff0000; + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +M68KMAKE_OP(clr, 16, ., .) +{ + m68ki_write_16(M68KMAKE_GET_EA_AY_16, 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +M68KMAKE_OP(clr, 32, ., d) +{ + DY = 0; + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +M68KMAKE_OP(clr, 32, ., .) +{ + m68ki_write_32(M68KMAKE_GET_EA_AY_32, 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +M68KMAKE_OP(cmp, 8, ., d) +{ + uint src = MASK_OUT_ABOVE_8(DY); + uint dst = MASK_OUT_ABOVE_8(DX); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +M68KMAKE_OP(cmp, 8, ., .) +{ + uint src = M68KMAKE_GET_OPER_AY_8; + uint dst = MASK_OUT_ABOVE_8(DX); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +M68KMAKE_OP(cmp, 16, ., d) +{ + uint src = MASK_OUT_ABOVE_16(DY); + uint dst = MASK_OUT_ABOVE_16(DX); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +M68KMAKE_OP(cmp, 16, ., a) +{ + uint src = MASK_OUT_ABOVE_16(AY); + uint dst = MASK_OUT_ABOVE_16(DX); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +M68KMAKE_OP(cmp, 16, ., .) +{ + uint src = M68KMAKE_GET_OPER_AY_16; + uint dst = MASK_OUT_ABOVE_16(DX); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +M68KMAKE_OP(cmp, 32, ., d) +{ + uint src = DY; + uint dst = DX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmp, 32, ., a) +{ + uint src = AY; + uint dst = DX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmp, 32, ., .) +{ + uint src = M68KMAKE_GET_OPER_AY_32; + uint dst = DX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmpa, 16, ., d) +{ + uint src = MAKE_INT_16(DY); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmpa, 16, ., a) +{ + uint src = MAKE_INT_16(AY); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmpa, 16, ., .) +{ + uint src = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmpa, 32, ., d) +{ + uint src = DY; + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmpa, 32, ., a) +{ + uint src = AY; + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmpa, 32, ., .) +{ + uint src = M68KMAKE_GET_OPER_AY_32; + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmpi, 8, ., d) +{ + uint src = OPER_I_8(); + uint dst = MASK_OUT_ABOVE_8(DY); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +M68KMAKE_OP(cmpi, 8, ., .) +{ + uint src = OPER_I_8(); + uint dst = M68KMAKE_GET_OPER_AY_8; + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +M68KMAKE_OP(cmpi, 8, ., pcdi) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint src = OPER_I_8(); + uint dst = OPER_PCDI_8(); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cmpi, 8, ., pcix) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint src = OPER_I_8(); + uint dst = OPER_PCIX_8(); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cmpi, 16, ., d) +{ + uint src = OPER_I_16(); + uint dst = MASK_OUT_ABOVE_16(DY); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +M68KMAKE_OP(cmpi, 16, ., .) +{ + uint src = OPER_I_16(); + uint dst = M68KMAKE_GET_OPER_AY_16; + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +M68KMAKE_OP(cmpi, 16, ., pcdi) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint src = OPER_I_16(); + uint dst = OPER_PCDI_16(); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cmpi, 16, ., pcix) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint src = OPER_I_16(); + uint dst = OPER_PCIX_16(); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cmpi, 32, ., d) +{ + uint src = OPER_I_32(); + uint dst = DY; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmpi, 32, ., .) +{ + uint src = OPER_I_32(); + uint dst = M68KMAKE_GET_OPER_AY_32; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmpi, 32, ., pcdi) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint src = OPER_I_32(); + uint dst = OPER_PCDI_32(); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cmpi, 32, ., pcix) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint src = OPER_I_32(); + uint dst = OPER_PCIX_32(); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cmpm, 8, ., ax7) +{ + uint src = OPER_AY_PI_8(); + uint dst = OPER_A7_PI_8(); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +M68KMAKE_OP(cmpm, 8, ., ay7) +{ + uint src = OPER_A7_PI_8(); + uint dst = OPER_AX_PI_8(); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +M68KMAKE_OP(cmpm, 8, ., axy7) +{ + uint src = OPER_A7_PI_8(); + uint dst = OPER_A7_PI_8(); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +M68KMAKE_OP(cmpm, 8, ., .) +{ + uint src = OPER_AY_PI_8(); + uint dst = OPER_AX_PI_8(); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +M68KMAKE_OP(cmpm, 16, ., .) +{ + uint src = OPER_AY_PI_16(); + uint dst = OPER_AX_PI_16(); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +M68KMAKE_OP(cmpm, 32, ., .) +{ + uint src = OPER_AY_PI_32(); + uint dst = OPER_AX_PI_32(); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cpbcc, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_1111(); +} + + +M68KMAKE_OP(cpdbcc, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_1111(); +} + + +M68KMAKE_OP(cpgen, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_1111(); +} + + +M68KMAKE_OP(cpscc, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_1111(); +} + + +M68KMAKE_OP(cptrapcc, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_1111(); +} + + +M68KMAKE_OP(dbt, 16, ., .) +{ + REG_PC += 2; +} + + +M68KMAKE_OP(dbf, 16, ., .) +{ + uint* r_dst = &DY; + uint res = MASK_OUT_ABOVE_16(*r_dst - 1); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + if(res != 0xffff) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(offset); + return; + } + REG_PC += 2; +} + + +M68KMAKE_OP(dbcc, 16, ., .) +{ + if(M68KMAKE_NOT_CC) + { + uint* r_dst = &DY; + uint res = MASK_OUT_ABOVE_16(*r_dst - 1); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + if(res != 0xffff) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(offset); + USE_CYCLES(CYC_DBCC_F_NOEXP); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_DBCC_F_EXP); + return; + } + REG_PC += 2; +} + + +M68KMAKE_OP(divs, 16, ., d) +{ + uint* r_dst = &DX; + sint src = MAKE_INT_16(DY); + sint quotient; + sint remainder; + + if(src != 0) + { + if((uint32)*r_dst == 0x80000000 && src == -1) + { + FLAG_Z = 0; + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = 0; + return; + } + + quotient = MAKE_INT_32(*r_dst) / src; + remainder = MAKE_INT_32(*r_dst) % src; + + if(quotient == MAKE_INT_16(quotient)) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); +} + + +M68KMAKE_OP(divs, 16, ., .) +{ + uint* r_dst = &DX; + sint src = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16); + sint quotient; + sint remainder; + + if(src != 0) + { + if((uint32)*r_dst == 0x80000000 && src == -1) + { + FLAG_Z = 0; + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = 0; + return; + } + + quotient = MAKE_INT_32(*r_dst) / src; + remainder = MAKE_INT_32(*r_dst) % src; + + if(quotient == MAKE_INT_16(quotient)) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); +} + + +M68KMAKE_OP(divu, 16, ., d) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_16(DY); + + if(src != 0) + { + uint quotient = *r_dst / src; + uint remainder = *r_dst % src; + + if(quotient < 0x10000) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); +} + + +M68KMAKE_OP(divu, 16, ., .) +{ + uint* r_dst = &DX; + uint src = M68KMAKE_GET_OPER_AY_16; + + if(src != 0) + { + uint quotient = *r_dst / src; + uint remainder = *r_dst % src; + + if(quotient < 0x10000) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); +} + + +M68KMAKE_OP(divl, 32, ., d) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 divisor = DY; + uint64 dividend = 0; + uint64 quotient = 0; + uint64 remainder = 0; + + if(divisor != 0) + { + if(BIT_A(word2)) /* 64 bit */ + { + dividend = REG_D[word2 & 7]; + dividend <<= 32; + dividend |= REG_D[(word2 >> 12) & 7]; + + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)dividend / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)dividend % (sint64)((sint32)divisor)); + if((sint64)quotient != (sint64)((sint32)quotient)) + { + FLAG_V = VFLAG_SET; + return; + } + } + else /* unsigned */ + { + quotient = dividend / divisor; + if(quotient > 0xffffffff) + { + FLAG_V = VFLAG_SET; + return; + } + remainder = dividend % divisor; + } + } + else /* 32 bit */ + { + dividend = REG_D[(word2 >> 12) & 7]; + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)((sint32)dividend) / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)((sint32)dividend) % (sint64)((sint32)divisor)); + } + else /* unsigned */ + { + quotient = dividend / divisor; + remainder = dividend % divisor; + } + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint divisor = DY; + uint dividend_hi = REG_D[word2 & 7]; + uint dividend_lo = REG_D[(word2 >> 12) & 7]; + uint quotient = 0; + uint remainder = 0; + uint dividend_neg = 0; + uint divisor_neg = 0; + sint i; + uint overflow; + + if(divisor != 0) + { + /* quad / long : long quotient, long remainder */ + if(BIT_A(word2)) + { + if(BIT_B(word2)) /* signed */ + { + /* special case in signed divide */ + if(dividend_hi == 0 && dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + REG_D[word2 & 7] = 0; + REG_D[(word2 >> 12) & 7] = 0x80000000; + + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + if(GET_MSB_32(dividend_hi)) + { + dividend_neg = 1; + dividend_hi = (uint)MASK_OUT_ABOVE_32((-(sint)dividend_hi) - (dividend_lo != 0)); + dividend_lo = (uint)MASK_OUT_ABOVE_32(-(sint)dividend_lo); + } + if(GET_MSB_32(divisor)) + { + divisor_neg = 1; + divisor = (uint)MASK_OUT_ABOVE_32(-(sint)divisor); + + } + } + + /* if the upper long is greater than the divisor, we're overflowing. */ + if(dividend_hi >= divisor) + { + FLAG_V = VFLAG_SET; + return; + } + + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + remainder = (remainder << 1) + ((dividend_hi >> i) & 1); + if(remainder >= divisor) + { + remainder -= divisor; + quotient++; + } + } + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + overflow = GET_MSB_32(remainder); + remainder = (remainder << 1) + ((dividend_lo >> i) & 1); + if(remainder >= divisor || overflow) + { + remainder -= divisor; + quotient++; + } + } + + if(BIT_B(word2)) /* signed */ + { + if(quotient > 0x7fffffff) + { + FLAG_V = VFLAG_SET; + return; + } + if(dividend_neg) + { + remainder = (uint)MASK_OUT_ABOVE_32(-(sint)remainder); + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + if(divisor_neg) + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + + /* long / long: long quotient, maybe long remainder */ + if(BIT_B(word2)) /* signed */ + { + /* Special case in divide */ + if(dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + REG_D[(word2 >> 12) & 7] = 0x80000000; + REG_D[word2 & 7] = 0; + return; + } + REG_D[word2 & 7] = MAKE_INT_32(dividend_lo) % MAKE_INT_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MAKE_INT_32(dividend_lo) / MAKE_INT_32(divisor); + } + else + { + REG_D[word2 & 7] = MASK_OUT_ABOVE_32(dividend_lo) % MASK_OUT_ABOVE_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(dividend_lo) / MASK_OUT_ABOVE_32(divisor); + } + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(); + +#endif +} + + +M68KMAKE_OP(divl, 32, ., .) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 divisor = M68KMAKE_GET_OPER_AY_32; + uint64 dividend = 0; + uint64 quotient = 0; + uint64 remainder = 0; + + if(divisor != 0) + { + if(BIT_A(word2)) /* 64 bit */ + { + dividend = REG_D[word2 & 7]; + dividend <<= 32; + dividend |= REG_D[(word2 >> 12) & 7]; + + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)dividend / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)dividend % (sint64)((sint32)divisor)); + if((sint64)quotient != (sint64)((sint32)quotient)) + { + FLAG_V = VFLAG_SET; + return; + } + } + else /* unsigned */ + { + quotient = dividend / divisor; + if(quotient > 0xffffffff) + { + FLAG_V = VFLAG_SET; + return; + } + remainder = dividend % divisor; + } + } + else /* 32 bit */ + { + dividend = REG_D[(word2 >> 12) & 7]; + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)((sint32)dividend) / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)((sint32)dividend) % (sint64)((sint32)divisor)); + } + else /* unsigned */ + { + quotient = dividend / divisor; + remainder = dividend % divisor; + } + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint divisor = M68KMAKE_GET_OPER_AY_32; + uint dividend_hi = REG_D[word2 & 7]; + uint dividend_lo = REG_D[(word2 >> 12) & 7]; + uint quotient = 0; + uint remainder = 0; + uint dividend_neg = 0; + uint divisor_neg = 0; + sint i; + uint overflow; + + if(divisor != 0) + { + /* quad / long : long quotient, long remainder */ + if(BIT_A(word2)) + { + if(BIT_B(word2)) /* signed */ + { + /* special case in signed divide */ + if(dividend_hi == 0 && dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + REG_D[word2 & 7] = 0; + REG_D[(word2 >> 12) & 7] = 0x80000000; + + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + if(GET_MSB_32(dividend_hi)) + { + dividend_neg = 1; + dividend_hi = (uint)MASK_OUT_ABOVE_32((-(sint)dividend_hi) - (dividend_lo != 0)); + dividend_lo = (uint)MASK_OUT_ABOVE_32(-(sint)dividend_lo); + } + if(GET_MSB_32(divisor)) + { + divisor_neg = 1; + divisor = (uint)MASK_OUT_ABOVE_32(-(sint)divisor); + + } + } + + /* if the upper long is greater than the divisor, we're overflowing. */ + if(dividend_hi >= divisor) + { + FLAG_V = VFLAG_SET; + return; + } + + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + remainder = (remainder << 1) + ((dividend_hi >> i) & 1); + if(remainder >= divisor) + { + remainder -= divisor; + quotient++; + } + } + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + overflow = GET_MSB_32(remainder); + remainder = (remainder << 1) + ((dividend_lo >> i) & 1); + if(remainder >= divisor || overflow) + { + remainder -= divisor; + quotient++; + } + } + + if(BIT_B(word2)) /* signed */ + { + if(quotient > 0x7fffffff) + { + FLAG_V = VFLAG_SET; + return; + } + if(dividend_neg) + { + remainder = (uint)MASK_OUT_ABOVE_32(-(sint)remainder); + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + if(divisor_neg) + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + + /* long / long: long quotient, maybe long remainder */ + if(BIT_B(word2)) /* signed */ + { + /* Special case in divide */ + if(dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + REG_D[(word2 >> 12) & 7] = 0x80000000; + REG_D[word2 & 7] = 0; + return; + } + REG_D[word2 & 7] = MAKE_INT_32(dividend_lo) % MAKE_INT_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MAKE_INT_32(dividend_lo) / MAKE_INT_32(divisor); + } + else + { + REG_D[word2 & 7] = MASK_OUT_ABOVE_32(dividend_lo) % MASK_OUT_ABOVE_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(dividend_lo) / MASK_OUT_ABOVE_32(divisor); + } + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(); + +#endif +} + + +M68KMAKE_OP(eor, 8, ., d) +{ + uint res = MASK_OUT_ABOVE_8(DY ^= MASK_OUT_ABOVE_8(DX)); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eor, 8, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint res = MASK_OUT_ABOVE_8(DX ^ m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eor, 16, ., d) +{ + uint res = MASK_OUT_ABOVE_16(DY ^= MASK_OUT_ABOVE_16(DX)); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eor, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint res = MASK_OUT_ABOVE_16(DX ^ m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eor, 32, ., d) +{ + uint res = DY ^= DX; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eor, 32, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_32; + uint res = DX ^ m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eori, 8, ., d) +{ + uint res = MASK_OUT_ABOVE_8(DY ^= OPER_I_8()); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eori, 8, ., .) +{ + uint src = OPER_I_8(); + uint ea = M68KMAKE_GET_EA_AY_8; + uint res = src ^ m68ki_read_8(ea); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eori, 16, ., d) +{ + uint res = MASK_OUT_ABOVE_16(DY ^= OPER_I_16()); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eori, 16, ., .) +{ + uint src = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_16; + uint res = src ^ m68ki_read_16(ea); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eori, 32, ., d) +{ + uint res = DY ^= OPER_I_32(); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eori, 32, ., .) +{ + uint src = OPER_I_32(); + uint ea = M68KMAKE_GET_EA_AY_32; + uint res = src ^ m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eori, 16, toc, .) +{ + m68ki_set_ccr(m68ki_get_ccr() ^ OPER_I_16()); +} + + +M68KMAKE_OP(eori, 16, tos, .) +{ + if(FLAG_S) + { + uint src = OPER_I_16(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_set_sr(m68ki_get_sr() ^ src); + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(exg, 32, dd, .) +{ + uint* reg_a = &DX; + uint* reg_b = &DY; + uint tmp = *reg_a; + *reg_a = *reg_b; + *reg_b = tmp; +} + + +M68KMAKE_OP(exg, 32, aa, .) +{ + uint* reg_a = &AX; + uint* reg_b = &AY; + uint tmp = *reg_a; + *reg_a = *reg_b; + *reg_b = tmp; +} + + +M68KMAKE_OP(exg, 32, da, .) +{ + uint* reg_a = &DX; + uint* reg_b = &AY; + uint tmp = *reg_a; + *reg_a = *reg_b; + *reg_b = tmp; +} + + +M68KMAKE_OP(ext, 16, ., .) +{ + uint* r_dst = &DY; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | MASK_OUT_ABOVE_8(*r_dst) | (GET_MSB_8(*r_dst) ? 0xff00 : 0); + + FLAG_N = NFLAG_16(*r_dst); + FLAG_Z = MASK_OUT_ABOVE_16(*r_dst); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(ext, 32, ., .) +{ + uint* r_dst = &DY; + + *r_dst = MASK_OUT_ABOVE_16(*r_dst) | (GET_MSB_16(*r_dst) ? 0xffff0000 : 0); + + FLAG_N = NFLAG_32(*r_dst); + FLAG_Z = *r_dst; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(extb, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint* r_dst = &DY; + + *r_dst = MASK_OUT_ABOVE_8(*r_dst) | (GET_MSB_8(*r_dst) ? 0xffffff00 : 0); + + FLAG_N = NFLAG_32(*r_dst); + FLAG_Z = *r_dst; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(illegal, 0, ., .) +{ + m68ki_exception_illegal(); +} + +M68KMAKE_OP(jmp, 32, ., .) +{ + m68ki_jump(M68KMAKE_GET_EA_AY_32); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(REG_PC == REG_PPC) + USE_ALL_CYCLES(); +} + + +M68KMAKE_OP(jsr, 32, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_32; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_push_32(REG_PC); + m68ki_jump(ea); +} + + +M68KMAKE_OP(lea, 32, ., .) +{ + AX = M68KMAKE_GET_EA_AY_32; +} + + +M68KMAKE_OP(link, 16, ., a7) +{ + REG_A[7] -= 4; + m68ki_write_32(REG_A[7], REG_A[7]); + REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + MAKE_INT_16(OPER_I_16())); +} + + +M68KMAKE_OP(link, 16, ., .) +{ + uint* r_dst = &AY; + + m68ki_push_32(*r_dst); + *r_dst = REG_A[7]; + REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + MAKE_INT_16(OPER_I_16())); +} + + +M68KMAKE_OP(link, 32, ., a7) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_A[7] -= 4; + m68ki_write_32(REG_A[7], REG_A[7]); + REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + OPER_I_32()); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(link, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint* r_dst = &AY; + + m68ki_push_32(*r_dst); + *r_dst = REG_A[7]; + REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + OPER_I_32()); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(lsr, 8, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = src >> shift; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_CLEAR; + FLAG_Z = res; + FLAG_X = FLAG_C = src << (9-shift); + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(lsr, 16, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = src >> shift; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_CLEAR; + FLAG_Z = res; + FLAG_X = FLAG_C = src << (9-shift); + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(lsr, 32, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = *r_dst; + uint res = src >> shift; + + *r_dst = res; + + FLAG_N = NFLAG_CLEAR; + FLAG_Z = res; + FLAG_X = FLAG_C = src << (9-shift); + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(lsr, 8, r, .) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = src >> shift; + + if(shift != 0) + { + USE_CYCLES(shift<<CYC_SHIFT); + + if(shift <= 8) + { + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + FLAG_X = FLAG_C = src << (9-shift); + FLAG_N = NFLAG_CLEAR; + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + *r_dst &= 0xffffff00; + FLAG_X = XFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_8(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(lsr, 16, r, .) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = src >> shift; + + if(shift != 0) + { + USE_CYCLES(shift<<CYC_SHIFT); + + if(shift <= 16) + { + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + FLAG_C = FLAG_X = (src >> (shift - 1))<<8; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + *r_dst &= 0xffff0000; + FLAG_X = XFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_16(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(lsr, 32, r, .) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = *r_dst; + uint res = src >> shift; + + if(shift != 0) + { + USE_CYCLES(shift<<CYC_SHIFT); + + if(shift < 32) + { + *r_dst = res; + FLAG_C = FLAG_X = (src >> (shift - 1))<<8; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + *r_dst = 0; + FLAG_X = FLAG_C = (shift == 32 ? GET_MSB_32(src)>>23 : 0); + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_32(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(lsr, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = m68ki_read_16(ea); + uint res = src >> 1; + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_CLEAR; + FLAG_Z = res; + FLAG_C = FLAG_X = src << 8; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(lsl, 8, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = MASK_OUT_ABOVE_8(src << shift); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_X = FLAG_C = src << shift; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(lsl, 16, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = MASK_OUT_ABOVE_16(src << shift); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_X = FLAG_C = src >> (8-shift); + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(lsl, 32, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32(src << shift); + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_X = FLAG_C = src >> (24-shift); + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(lsl, 8, r, .) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = MASK_OUT_ABOVE_8(src << shift); + + if(shift != 0) + { + USE_CYCLES(shift<<CYC_SHIFT); + + if(shift <= 8) + { + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + FLAG_X = FLAG_C = src << shift; + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + *r_dst &= 0xffffff00; + FLAG_X = XFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_8(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(lsl, 16, r, .) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = MASK_OUT_ABOVE_16(src << shift); + + if(shift != 0) + { + USE_CYCLES(shift<<CYC_SHIFT); + + if(shift <= 16) + { + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + FLAG_X = FLAG_C = (src << shift) >> 8; + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + *r_dst &= 0xffff0000; + FLAG_X = XFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_16(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(lsl, 32, r, .) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32(src << shift); + + if(shift != 0) + { + USE_CYCLES(shift<<CYC_SHIFT); + + if(shift < 32) + { + *r_dst = res; + FLAG_X = FLAG_C = (src >> (32 - shift)) << 8; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + *r_dst = 0; + FLAG_X = FLAG_C = ((shift == 32 ? src & 1 : 0))<<8; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_32(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(lsl, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = m68ki_read_16(ea); + uint res = MASK_OUT_ABOVE_16(src << 1); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_X = FLAG_C = src >> 7; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, d, d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, d, .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, ai, d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_AX_AI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, ai, .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + uint ea = EA_AX_AI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, pi7, d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_A7_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, pi, d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_AX_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, pi7, .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + uint ea = EA_A7_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, pi, .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + uint ea = EA_AX_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, pd7, d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_A7_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, pd, d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_AX_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, pd7, .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + uint ea = EA_A7_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, pd, .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + uint ea = EA_AX_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, di, d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_AX_DI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, di, .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + uint ea = EA_AX_DI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, ix, d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_AX_IX_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, ix, .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + uint ea = EA_AX_IX_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, aw, d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_AW_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, aw, .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + uint ea = EA_AW_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, al, d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_AL_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, al, .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + uint ea = EA_AL_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, d, d) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, d, a) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, d, .) +{ + uint res = M68KMAKE_GET_OPER_AY_16; + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, ai, d) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint ea = EA_AX_AI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, ai, a) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint ea = EA_AX_AI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, ai, .) +{ + uint res = M68KMAKE_GET_OPER_AY_16; + uint ea = EA_AX_AI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, pi, d) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint ea = EA_AX_PI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, pi, a) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint ea = EA_AX_PI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, pi, .) +{ + uint res = M68KMAKE_GET_OPER_AY_16; + uint ea = EA_AX_PI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, pd, d) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint ea = EA_AX_PD_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, pd, a) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint ea = EA_AX_PD_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, pd, .) +{ + uint res = M68KMAKE_GET_OPER_AY_16; + uint ea = EA_AX_PD_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, di, d) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint ea = EA_AX_DI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, di, a) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint ea = EA_AX_DI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, di, .) +{ + uint res = M68KMAKE_GET_OPER_AY_16; + uint ea = EA_AX_DI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, ix, d) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint ea = EA_AX_IX_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, ix, a) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint ea = EA_AX_IX_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, ix, .) +{ + uint res = M68KMAKE_GET_OPER_AY_16; + uint ea = EA_AX_IX_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, aw, d) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint ea = EA_AW_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, aw, a) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint ea = EA_AW_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, aw, .) +{ + uint res = M68KMAKE_GET_OPER_AY_16; + uint ea = EA_AW_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, al, d) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint ea = EA_AL_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, al, a) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint ea = EA_AL_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, al, .) +{ + uint res = M68KMAKE_GET_OPER_AY_16; + uint ea = EA_AL_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, d, d) +{ + uint res = DY; + uint* r_dst = &DX; + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, d, a) +{ + uint res = AY; + uint* r_dst = &DX; + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, d, .) +{ + uint res = M68KMAKE_GET_OPER_AY_32; + uint* r_dst = &DX; + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, ai, d) +{ + uint res = DY; + uint ea = EA_AX_AI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, ai, a) +{ + uint res = AY; + uint ea = EA_AX_AI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, ai, .) +{ + uint res = M68KMAKE_GET_OPER_AY_32; + uint ea = EA_AX_AI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, pi, d) +{ + uint res = DY; + uint ea = EA_AX_PI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, pi, a) +{ + uint res = AY; + uint ea = EA_AX_PI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, pi, .) +{ + uint res = M68KMAKE_GET_OPER_AY_32; + uint ea = EA_AX_PI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, pd, d) +{ + uint res = DY; + uint ea = EA_AX_PD_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, pd, a) +{ + uint res = AY; + uint ea = EA_AX_PD_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, pd, .) +{ + uint res = M68KMAKE_GET_OPER_AY_32; + uint ea = EA_AX_PD_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, di, d) +{ + uint res = DY; + uint ea = EA_AX_DI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, di, a) +{ + uint res = AY; + uint ea = EA_AX_DI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, di, .) +{ + uint res = M68KMAKE_GET_OPER_AY_32; + uint ea = EA_AX_DI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, ix, d) +{ + uint res = DY; + uint ea = EA_AX_IX_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, ix, a) +{ + uint res = AY; + uint ea = EA_AX_IX_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, ix, .) +{ + uint res = M68KMAKE_GET_OPER_AY_32; + uint ea = EA_AX_IX_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, aw, d) +{ + uint res = DY; + uint ea = EA_AW_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, aw, a) +{ + uint res = AY; + uint ea = EA_AW_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, aw, .) +{ + uint res = M68KMAKE_GET_OPER_AY_32; + uint ea = EA_AW_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, al, d) +{ + uint res = DY; + uint ea = EA_AL_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, al, a) +{ + uint res = AY; + uint ea = EA_AL_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, al, .) +{ + uint res = M68KMAKE_GET_OPER_AY_32; + uint ea = EA_AL_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(movea, 16, ., d) +{ + AX = MAKE_INT_16(DY); +} + + +M68KMAKE_OP(movea, 16, ., a) +{ + AX = MAKE_INT_16(AY); +} + + +M68KMAKE_OP(movea, 16, ., .) +{ + AX = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16); +} + + +M68KMAKE_OP(movea, 32, ., d) +{ + AX = DY; +} + + +M68KMAKE_OP(movea, 32, ., a) +{ + AX = AY; +} + + +M68KMAKE_OP(movea, 32, ., .) +{ + AX = M68KMAKE_GET_OPER_AY_32; +} + + +M68KMAKE_OP(move, 16, frc, d) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + DY = MASK_OUT_BELOW_16(DY) | m68ki_get_ccr(); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(move, 16, frc, .) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + m68ki_write_16(M68KMAKE_GET_EA_AY_16, m68ki_get_ccr()); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(move, 16, toc, d) +{ + m68ki_set_ccr(DY); +} + + +M68KMAKE_OP(move, 16, toc, .) +{ + m68ki_set_ccr(M68KMAKE_GET_OPER_AY_16); +} + + +M68KMAKE_OP(move, 16, frs, d) +{ + if(CPU_TYPE_IS_000(CPU_TYPE) || FLAG_S) /* NS990408 */ + { + DY = MASK_OUT_BELOW_16(DY) | m68ki_get_sr(); + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(move, 16, frs, .) +{ + if(CPU_TYPE_IS_000(CPU_TYPE) || FLAG_S) /* NS990408 */ + { + uint ea = M68KMAKE_GET_EA_AY_16; + m68ki_write_16(ea, m68ki_get_sr()); + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(move, 16, tos, d) +{ + if(FLAG_S) + { + m68ki_set_sr(DY); + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(move, 16, tos, .) +{ + if(FLAG_S) + { + uint new_sr = M68KMAKE_GET_OPER_AY_16; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_set_sr(new_sr); + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(move, 32, fru, .) +{ + if(FLAG_S) + { + AY = REG_USP; + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(move, 32, tou, .) +{ + if(FLAG_S) + { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + REG_USP = AY; + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(movec, 32, cr, .) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + switch (word2 & 0xfff) + { + case 0x000: /* SFC */ + REG_DA[(word2 >> 12) & 15] = REG_SFC; + return; + case 0x001: /* DFC */ + REG_DA[(word2 >> 12) & 15] = REG_DFC; + return; + case 0x002: /* CACR */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_DA[(word2 >> 12) & 15] = REG_CACR; + return; + } + return; + case 0x800: /* USP */ + REG_DA[(word2 >> 12) & 15] = REG_USP; + return; + case 0x801: /* VBR */ + REG_DA[(word2 >> 12) & 15] = REG_VBR; + return; + case 0x802: /* CAAR */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_DA[(word2 >> 12) & 15] = REG_CAAR; + return; + } + m68ki_exception_illegal(); + break; + case 0x803: /* MSP */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_DA[(word2 >> 12) & 15] = FLAG_M ? REG_SP : REG_MSP; + return; + } + m68ki_exception_illegal(); + return; + case 0x804: /* ISP */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_DA[(word2 >> 12) & 15] = FLAG_M ? REG_ISP : REG_SP; + return; + } + m68ki_exception_illegal(); + return; + default: + m68ki_exception_illegal(); + return; + } + } + m68ki_exception_privilege_violation(); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(movec, 32, rc, .) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + switch (word2 & 0xfff) + { + case 0x000: /* SFC */ + REG_SFC = REG_DA[(word2 >> 12) & 15] & 7; + return; + case 0x001: /* DFC */ + REG_DFC = REG_DA[(word2 >> 12) & 15] & 7; + return; + case 0x002: /* CACR */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_CACR = REG_DA[(word2 >> 12) & 15]; + return; + } + m68ki_exception_illegal(); + return; + case 0x800: /* USP */ + REG_USP = REG_DA[(word2 >> 12) & 15]; + return; + case 0x801: /* VBR */ + REG_VBR = REG_DA[(word2 >> 12) & 15]; + return; + case 0x802: /* CAAR */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_CAAR = REG_DA[(word2 >> 12) & 15]; + return; + } + m68ki_exception_illegal(); + return; + case 0x803: /* MSP */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* we are in supervisor mode so just check for M flag */ + if(!FLAG_M) + { + REG_MSP = REG_DA[(word2 >> 12) & 15]; + return; + } + REG_SP = REG_DA[(word2 >> 12) & 15]; + return; + } + m68ki_exception_illegal(); + return; + case 0x804: /* ISP */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(!FLAG_M) + { + REG_SP = REG_DA[(word2 >> 12) & 15]; + return; + } + REG_ISP = REG_DA[(word2 >> 12) & 15]; + return; + } + m68ki_exception_illegal(); + return; + default: + m68ki_exception_illegal(); + return; + } + } + m68ki_exception_privilege_violation(); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(movem, 16, re, pd) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = AY; + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + ea -= 2; + m68ki_write_16(ea, MASK_OUT_ABOVE_16(REG_DA[15-i])); + count++; + } + AY = ea; + + USE_CYCLES(count<<CYC_MOVEM_W); +} + + +M68KMAKE_OP(movem, 16, re, .) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_16; + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + m68ki_write_16(ea, MASK_OUT_ABOVE_16(REG_DA[i])); + ea += 2; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_W); +} + + +M68KMAKE_OP(movem, 32, re, pd) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = AY; + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + ea -= 4; + m68ki_write_32(ea, REG_DA[15-i]); + count++; + } + AY = ea; + + USE_CYCLES(count<<CYC_MOVEM_L); +} + + +M68KMAKE_OP(movem, 32, re, .) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_32; + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + m68ki_write_32(ea, REG_DA[i]); + ea += 4; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_L); +} + + +M68KMAKE_OP(movem, 16, er, pi) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = AY; + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + REG_DA[i] = MAKE_INT_16(MASK_OUT_ABOVE_16(m68ki_read_16(ea))); + ea += 2; + count++; + } + AY = ea; + + USE_CYCLES(count<<CYC_MOVEM_W); +} + + +M68KMAKE_OP(movem, 16, er, pcdi) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = EA_PCDI_16(); + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + REG_DA[i] = MAKE_INT_16(MASK_OUT_ABOVE_16(m68ki_read_pcrel_16(ea))); + ea += 2; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_W); +} + + +M68KMAKE_OP(movem, 16, er, pcix) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = EA_PCIX_16(); + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + REG_DA[i] = MAKE_INT_16(MASK_OUT_ABOVE_16(m68ki_read_pcrel_16(ea))); + ea += 2; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_W); +} + + +M68KMAKE_OP(movem, 16, er, .) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_16; + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + REG_DA[i] = MAKE_INT_16(MASK_OUT_ABOVE_16(m68ki_read_16(ea))); + ea += 2; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_W); +} + + +M68KMAKE_OP(movem, 32, er, pi) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = AY; + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + REG_DA[i] = m68ki_read_32(ea); + ea += 4; + count++; + } + AY = ea; + + USE_CYCLES(count<<CYC_MOVEM_L); +} + + +M68KMAKE_OP(movem, 32, er, pcdi) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = EA_PCDI_32(); + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + REG_DA[i] = m68ki_read_pcrel_32(ea); + ea += 4; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_L); +} + + +M68KMAKE_OP(movem, 32, er, pcix) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = EA_PCIX_32(); + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + REG_DA[i] = m68ki_read_pcrel_32(ea); + ea += 4; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_L); +} + + +M68KMAKE_OP(movem, 32, er, .) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_32; + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + REG_DA[i] = m68ki_read_32(ea); + ea += 4; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_L); +} + + +M68KMAKE_OP(movep, 16, re, .) +{ + uint ea = EA_AY_DI_16(); + uint src = DX; + + m68ki_write_8(ea, MASK_OUT_ABOVE_8(src >> 8)); + m68ki_write_8(ea += 2, MASK_OUT_ABOVE_8(src)); +} + + +M68KMAKE_OP(movep, 32, re, .) +{ + uint ea = EA_AY_DI_32(); + uint src = DX; + + m68ki_write_8(ea, MASK_OUT_ABOVE_8(src >> 24)); + m68ki_write_8(ea += 2, MASK_OUT_ABOVE_8(src >> 16)); + m68ki_write_8(ea += 2, MASK_OUT_ABOVE_8(src >> 8)); + m68ki_write_8(ea += 2, MASK_OUT_ABOVE_8(src)); +} + + +M68KMAKE_OP(movep, 16, er, .) +{ + uint ea = EA_AY_DI_16(); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | ((m68ki_read_8(ea) << 8) + m68ki_read_8(ea + 2)); +} + + +M68KMAKE_OP(movep, 32, er, .) +{ + uint ea = EA_AY_DI_32(); + + DX = (m68ki_read_8(ea) << 24) + (m68ki_read_8(ea + 2) << 16) + + (m68ki_read_8(ea + 4) << 8) + m68ki_read_8(ea + 6); +} + + +M68KMAKE_OP(moves, 8, ., .) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_8; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_8_fc(ea, REG_DFC, MASK_OUT_ABOVE_8(REG_DA[(word2 >> 12) & 15])); + return; + } + if(BIT_F(word2)) /* Memory to address register */ + { + REG_A[(word2 >> 12) & 7] = MAKE_INT_8(m68ki_read_8_fc(ea, REG_SFC)); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to data register */ + REG_D[(word2 >> 12) & 7] = MASK_OUT_BELOW_8(REG_D[(word2 >> 12) & 7]) | m68ki_read_8_fc(ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(moves, 16, ., .) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_16; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_16_fc(ea, REG_DFC, MASK_OUT_ABOVE_16(REG_DA[(word2 >> 12) & 15])); + return; + } + if(BIT_F(word2)) /* Memory to address register */ + { + REG_A[(word2 >> 12) & 7] = MAKE_INT_16(m68ki_read_16_fc(ea, REG_SFC)); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to data register */ + REG_D[(word2 >> 12) & 7] = MASK_OUT_BELOW_16(REG_D[(word2 >> 12) & 7]) | m68ki_read_16_fc(ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(moves, 32, ., .) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_32; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_32_fc(ea, REG_DFC, REG_DA[(word2 >> 12) & 15]); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to register */ + REG_DA[(word2 >> 12) & 15] = m68ki_read_32_fc(ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(moveq, 32, ., .) +{ + uint res = DX = MAKE_INT_8(MASK_OUT_ABOVE_8(REG_IR)); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(muls, 16, ., d) +{ + uint* r_dst = &DX; + uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(DY) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(muls, 16, ., .) +{ + uint* r_dst = &DX; + uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(M68KMAKE_GET_OPER_AY_16) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(mulu, 16, ., d) +{ + uint* r_dst = &DX; + uint res = MASK_OUT_ABOVE_16(DY) * MASK_OUT_ABOVE_16(*r_dst); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(mulu, 16, ., .) +{ + uint* r_dst = &DX; + uint res = M68KMAKE_GET_OPER_AY_16 * MASK_OUT_ABOVE_16(*r_dst); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(mull, 32, ., d) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 src = DY; + uint64 dst = REG_D[(word2 >> 12) & 7]; + uint64 res; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + res = (sint64)((sint32)src) * (sint64)((sint32)dst); + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = ((sint64)res != (sint32)res)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + + res = src * dst; + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = (res > 0xffffffff)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + m68ki_exception_illegal(); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint src = DY; + uint dst = REG_D[(word2 >> 12) & 7]; + uint neg = GET_MSB_32(src ^ dst); + uint src1; + uint src2; + uint dst1; + uint dst2; + uint r1; + uint r2; + uint r3; + uint r4; + uint lo; + uint hi; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + if(GET_MSB_32(src)) + src = (uint)MASK_OUT_ABOVE_32(-(sint)src); + if(GET_MSB_32(dst)) + dst = (uint)MASK_OUT_ABOVE_32(-(sint)dst); + } + + src1 = MASK_OUT_ABOVE_16(src); + src2 = src>>16; + dst1 = MASK_OUT_ABOVE_16(dst); + dst2 = dst>>16; + + + r1 = src1 * dst1; + r2 = src1 * dst2; + r3 = src2 * dst1; + r4 = src2 * dst2; + + lo = r1 + (MASK_OUT_ABOVE_16(r2)<<16) + (MASK_OUT_ABOVE_16(r3)<<16); + hi = r4 + (r2>>16) + (r3>>16) + (((r1>>16) + MASK_OUT_ABOVE_16(r2) + MASK_OUT_ABOVE_16(r3)) >> 16); + + if(BIT_B(word2) && neg) + { + hi = (uint)MASK_OUT_ABOVE_32((-(sint)hi) - (lo != 0)); + lo = (uint)MASK_OUT_ABOVE_32(-(sint)lo); + } + + if(BIT_A(word2)) + { + REG_D[word2 & 7] = hi; + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(hi); + FLAG_Z = hi | lo; + FLAG_V = VFLAG_CLEAR; + return; + } + + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(lo); + FLAG_Z = lo; + if(BIT_B(word2)) + FLAG_V = (!((GET_MSB_32(lo) && hi == 0xffffffff) || (!GET_MSB_32(lo) && !hi)))<<7; + else + FLAG_V = (hi != 0) << 7; + return; + } + m68ki_exception_illegal(); + +#endif +} + + +M68KMAKE_OP(mull, 32, ., .) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 src = M68KMAKE_GET_OPER_AY_32; + uint64 dst = REG_D[(word2 >> 12) & 7]; + uint64 res; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + res = (sint64)((sint32)src) * (sint64)((sint32)dst); + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = ((sint64)res != (sint32)res)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + + res = src * dst; + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = (res > 0xffffffff)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + m68ki_exception_illegal(); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint src = M68KMAKE_GET_OPER_AY_32; + uint dst = REG_D[(word2 >> 12) & 7]; + uint neg = GET_MSB_32(src ^ dst); + uint src1; + uint src2; + uint dst1; + uint dst2; + uint r1; + uint r2; + uint r3; + uint r4; + uint lo; + uint hi; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + if(GET_MSB_32(src)) + src = (uint)MASK_OUT_ABOVE_32(-(sint)src); + if(GET_MSB_32(dst)) + dst = (uint)MASK_OUT_ABOVE_32(-(sint)dst); + } + + src1 = MASK_OUT_ABOVE_16(src); + src2 = src>>16; + dst1 = MASK_OUT_ABOVE_16(dst); + dst2 = dst>>16; + + + r1 = src1 * dst1; + r2 = src1 * dst2; + r3 = src2 * dst1; + r4 = src2 * dst2; + + lo = r1 + (MASK_OUT_ABOVE_16(r2)<<16) + (MASK_OUT_ABOVE_16(r3)<<16); + hi = r4 + (r2>>16) + (r3>>16) + (((r1>>16) + MASK_OUT_ABOVE_16(r2) + MASK_OUT_ABOVE_16(r3)) >> 16); + + if(BIT_B(word2) && neg) + { + hi = (uint)MASK_OUT_ABOVE_32((-(sint)hi) - (lo != 0)); + lo = (uint)MASK_OUT_ABOVE_32(-(sint)lo); + } + + if(BIT_A(word2)) + { + REG_D[word2 & 7] = hi; + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(hi); + FLAG_Z = hi | lo; + FLAG_V = VFLAG_CLEAR; + return; + } + + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(lo); + FLAG_Z = lo; + if(BIT_B(word2)) + FLAG_V = (!((GET_MSB_32(lo) && hi == 0xffffffff) || (!GET_MSB_32(lo) && !hi)))<<7; + else + FLAG_V = (hi != 0) << 7; + return; + } + m68ki_exception_illegal(); + +#endif +} + + +M68KMAKE_OP(nbcd, 8, ., d) +{ + uint* r_dst = &DY; + uint dst = *r_dst; + uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1()); + + if(res != 0x9a) + { + FLAG_V = ~res; /* Undefined V behavior */ + + if((res & 0x0f) == 0xa) + res = (res & 0xf0) + 0x10; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_Z |= res; + FLAG_C = CFLAG_SET; + FLAG_X = XFLAG_SET; + } + else + { + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_X = XFLAG_CLEAR; + } + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ +} + + +M68KMAKE_OP(nbcd, 8, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint dst = m68ki_read_8(ea); + uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1()); + + if(res != 0x9a) + { + FLAG_V = ~res; /* Undefined V behavior */ + + if((res & 0x0f) == 0xa) + res = (res & 0xf0) + 0x10; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + + m68ki_write_8(ea, MASK_OUT_ABOVE_8(res)); + + FLAG_Z |= res; + FLAG_C = CFLAG_SET; + FLAG_X = XFLAG_SET; + } + else + { + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_X = XFLAG_CLEAR; + } + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ +} + + +M68KMAKE_OP(neg, 8, ., d) +{ + uint* r_dst = &DY; + uint res = 0 - MASK_OUT_ABOVE_8(*r_dst); + + FLAG_N = NFLAG_8(res); + FLAG_C = FLAG_X = CFLAG_8(res); + FLAG_V = *r_dst & res; + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(neg, 8, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint src = m68ki_read_8(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_8(res); + FLAG_C = FLAG_X = CFLAG_8(res); + FLAG_V = src & res; + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +M68KMAKE_OP(neg, 16, ., d) +{ + uint* r_dst = &DY; + uint res = 0 - MASK_OUT_ABOVE_16(*r_dst); + + FLAG_N = NFLAG_16(res); + FLAG_C = FLAG_X = CFLAG_16(res); + FLAG_V = (*r_dst & res)>>8; + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(neg, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = m68ki_read_16(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_16(res); + FLAG_C = FLAG_X = CFLAG_16(res); + FLAG_V = (src & res)>>8; + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +M68KMAKE_OP(neg, 32, ., d) +{ + uint* r_dst = &DY; + uint res = 0 - *r_dst; + + FLAG_N = NFLAG_32(res); + FLAG_C = FLAG_X = CFLAG_SUB_32(*r_dst, 0, res); + FLAG_V = (*r_dst & res)>>24; + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(neg, 32, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_32; + uint src = m68ki_read_32(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_32(res); + FLAG_C = FLAG_X = CFLAG_SUB_32(src, 0, res); + FLAG_V = (src & res)>>24; + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +M68KMAKE_OP(negx, 8, ., d) +{ + uint* r_dst = &DY; + uint res = 0 - MASK_OUT_ABOVE_8(*r_dst) - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = *r_dst & res; + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; +} + + +M68KMAKE_OP(negx, 8, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint src = m68ki_read_8(ea); + uint res = 0 - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = src & res; + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(negx, 16, ., d) +{ + uint* r_dst = &DY; + uint res = 0 - MASK_OUT_ABOVE_16(*r_dst) - XFLAG_AS_1(); + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = (*r_dst & res)>>8; + + res = MASK_OUT_ABOVE_16(res); + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; +} + + +M68KMAKE_OP(negx, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = m68ki_read_16(ea); + uint res = 0 - MASK_OUT_ABOVE_16(src) - XFLAG_AS_1(); + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = (src & res)>>8; + + res = MASK_OUT_ABOVE_16(res); + FLAG_Z |= res; + + m68ki_write_16(ea, res); +} + + +M68KMAKE_OP(negx, 32, ., d) +{ + uint* r_dst = &DY; + uint res = 0 - MASK_OUT_ABOVE_32(*r_dst) - XFLAG_AS_1(); + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(*r_dst, 0, res); + FLAG_V = (*r_dst & res)>>24; + + res = MASK_OUT_ABOVE_32(res); + FLAG_Z |= res; + + *r_dst = res; +} + + +M68KMAKE_OP(negx, 32, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_32; + uint src = m68ki_read_32(ea); + uint res = 0 - MASK_OUT_ABOVE_32(src) - XFLAG_AS_1(); + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, 0, res); + FLAG_V = (src & res)>>24; + + res = MASK_OUT_ABOVE_32(res); + FLAG_Z |= res; + + m68ki_write_32(ea, res); +} + + +M68KMAKE_OP(nop, 0, ., .) +{ + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ +} + + +M68KMAKE_OP(not, 8, ., d) +{ + uint* r_dst = &DY; + uint res = MASK_OUT_ABOVE_8(~*r_dst); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(not, 8, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint res = MASK_OUT_ABOVE_8(~m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(not, 16, ., d) +{ + uint* r_dst = &DY; + uint res = MASK_OUT_ABOVE_16(~*r_dst); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(not, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint res = MASK_OUT_ABOVE_16(~m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(not, 32, ., d) +{ + uint* r_dst = &DY; + uint res = *r_dst = MASK_OUT_ABOVE_32(~*r_dst); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(not, 32, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_32; + uint res = MASK_OUT_ABOVE_32(~m68ki_read_32(ea)); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(or, 8, er, d) +{ + uint res = MASK_OUT_ABOVE_8((DX |= MASK_OUT_ABOVE_8(DY))); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(or, 8, er, .) +{ + uint res = MASK_OUT_ABOVE_8((DX |= M68KMAKE_GET_OPER_AY_8)); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(or, 16, er, d) +{ + uint res = MASK_OUT_ABOVE_16((DX |= MASK_OUT_ABOVE_16(DY))); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(or, 16, er, .) +{ + uint res = MASK_OUT_ABOVE_16((DX |= M68KMAKE_GET_OPER_AY_16)); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(or, 32, er, d) +{ + uint res = DX |= DY; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(or, 32, er, .) +{ + uint res = DX |= M68KMAKE_GET_OPER_AY_32; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(or, 8, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint res = MASK_OUT_ABOVE_8(DX | m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(or, 16, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint res = MASK_OUT_ABOVE_16(DX | m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(or, 32, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_32; + uint res = DX | m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ori, 8, ., d) +{ + uint res = MASK_OUT_ABOVE_8((DY |= OPER_I_8())); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ori, 8, ., .) +{ + uint src = OPER_I_8(); + uint ea = M68KMAKE_GET_EA_AY_8; + uint res = MASK_OUT_ABOVE_8(src | m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ori, 16, ., d) +{ + uint res = MASK_OUT_ABOVE_16(DY |= OPER_I_16()); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ori, 16, ., .) +{ + uint src = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_16; + uint res = MASK_OUT_ABOVE_16(src | m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ori, 32, ., d) +{ + uint res = DY |= OPER_I_32(); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ori, 32, ., .) +{ + uint src = OPER_I_32(); + uint ea = M68KMAKE_GET_EA_AY_32; + uint res = src | m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ori, 16, toc, .) +{ + m68ki_set_ccr(m68ki_get_ccr() | OPER_I_16()); +} + + +M68KMAKE_OP(ori, 16, tos, .) +{ + if(FLAG_S) + { + uint src = OPER_I_16(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_set_sr(m68ki_get_sr() | src); + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(pack, 16, rr, .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: DX and DY are reversed in Motorola's docs */ + uint src = DY + OPER_I_16(); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | ((src >> 4) & 0x00f0) | (src & 0x000f); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(pack, 16, mm, ax7) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: AX and AY are reversed in Motorola's docs */ + uint ea_src = EA_AY_PD_8(); + uint src = m68ki_read_8(ea_src); + ea_src = EA_AY_PD_8(); + src = ((src << 8) | m68ki_read_8(ea_src)) + OPER_I_16(); + + m68ki_write_8(EA_A7_PD_8(), ((src >> 4) & 0x00f0) | (src & 0x000f)); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(pack, 16, mm, ay7) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: AX and AY are reversed in Motorola's docs */ + uint ea_src = EA_A7_PD_8(); + uint src = m68ki_read_8(ea_src); + ea_src = EA_A7_PD_8(); + src = ((src << 8) | m68ki_read_8(ea_src)) + OPER_I_16(); + + m68ki_write_8(EA_AX_PD_8(), ((src >> 4) & 0x00f0) | (src & 0x000f)); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(pack, 16, mm, axy7) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint ea_src = EA_A7_PD_8(); + uint src = m68ki_read_8(ea_src); + ea_src = EA_A7_PD_8(); + src = ((src << 8) | m68ki_read_8(ea_src)) + OPER_I_16(); + + m68ki_write_8(EA_A7_PD_8(), ((src >> 4) & 0x00f0) | (src & 0x000f)); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(pack, 16, mm, .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: AX and AY are reversed in Motorola's docs */ + uint ea_src = EA_AY_PD_8(); + uint src = m68ki_read_8(ea_src); + ea_src = EA_AY_PD_8(); + src = ((src << 8) | m68ki_read_8(ea_src)) + OPER_I_16(); + + m68ki_write_8(EA_AX_PD_8(), ((src >> 4) & 0x00f0) | (src & 0x000f)); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(pea, 32, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_32; + + m68ki_push_32(ea); +} + + +M68KMAKE_OP(reset, 0, ., .) +{ + if(FLAG_S) + { + m68ki_output_reset(); /* auto-disable (see m68kcpu.h) */ + USE_CYCLES(CYC_RESET); + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(ror, 8, s, .) +{ + uint* r_dst = &DY; + uint orig_shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint shift = orig_shift & 7; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = ROR_8(src, shift); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = src << (9-orig_shift); + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ror, 16, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = ROR_16(src, shift); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = src << (9-shift); + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ror, 32, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint64 src = *r_dst; + uint res = ROR_32(src, shift); + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = src << (9-shift); + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ror, 8, r, .) +{ + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + uint shift = orig_shift & 7; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = ROR_8(src, shift); + + if(orig_shift != 0) + { + USE_CYCLES(orig_shift<<CYC_SHIFT); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + FLAG_C = src << (8-((shift-1)&7)); + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_8(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ror, 16, r, .) +{ + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + uint shift = orig_shift & 15; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = ROR_16(src, shift); + + if(orig_shift != 0) + { + USE_CYCLES(orig_shift<<CYC_SHIFT); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + FLAG_C = (src >> ((shift - 1) & 15)) << 8; + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_16(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ror, 32, r, .) +{ + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + uint shift = orig_shift & 31; + uint64 src = *r_dst; + uint res = ROR_32(src, shift); + + if(orig_shift != 0) + { + USE_CYCLES(orig_shift<<CYC_SHIFT); + + *r_dst = res; + FLAG_C = (src >> ((shift - 1) & 31)) << 8; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_32(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ror, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = m68ki_read_16(ea); + uint res = ROR_16(src, 1); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = src << 8; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(rol, 8, s, .) +{ + uint* r_dst = &DY; + uint orig_shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint shift = orig_shift & 7; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = ROL_8(src, shift); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = src << orig_shift; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(rol, 16, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = ROL_16(src, shift); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = src >> (8-shift); + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(rol, 32, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint64 src = *r_dst; + uint res = ROL_32(src, shift); + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = src >> (24-shift); + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(rol, 8, r, .) +{ + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + uint shift = orig_shift & 7; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = ROL_8(src, shift); + + if(orig_shift != 0) + { + USE_CYCLES(orig_shift<<CYC_SHIFT); + + if(shift != 0) + { + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + FLAG_C = src << shift; + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + FLAG_C = (src & 1)<<8; + FLAG_N = NFLAG_8(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_8(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(rol, 16, r, .) +{ + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + uint shift = orig_shift & 15; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = MASK_OUT_ABOVE_16(ROL_16(src, shift)); + + if(orig_shift != 0) + { + USE_CYCLES(orig_shift<<CYC_SHIFT); + + if(shift != 0) + { + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + FLAG_C = (src << shift) >> 8; + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + FLAG_C = (src & 1)<<8; + FLAG_N = NFLAG_16(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_16(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(rol, 32, r, .) +{ + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + uint shift = orig_shift & 31; + uint64 src = *r_dst; + uint res = ROL_32(src, shift); + + if(orig_shift != 0) + { + USE_CYCLES(orig_shift<<CYC_SHIFT); + + *r_dst = res; + + FLAG_C = (src >> (32 - shift)) << 8; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_32(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(rol, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = m68ki_read_16(ea); + uint res = MASK_OUT_ABOVE_16(ROL_16(src, 1)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = src >> 7; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(roxr, 8, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = ROR_9(src | (XFLAG_AS_1() << 8), shift); + + FLAG_C = FLAG_X = res; + res = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(roxr, 16, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = ROR_17(src | (XFLAG_AS_1() << 16), shift); + + FLAG_C = FLAG_X = res >> 8; + res = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(roxr, 32, s, .) +{ +#if M68K_USE_64_BIT + + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint64 src = *r_dst; + uint64 res = src | (((uint64)XFLAG_AS_1()) << 32); + + res = ROR_33_64(res, shift); + + FLAG_C = FLAG_X = res >> 24; + res = MASK_OUT_ABOVE_32(res); + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + +#else + + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32((ROR_33(src, shift) & ~(1 << (32 - shift))) | (XFLAG_AS_1() << (32 - shift))); + uint new_x_flag = src & (1 << (shift - 1)); + + *r_dst = res; + + FLAG_C = FLAG_X = (new_x_flag != 0)<<8; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + +#endif +} + + +M68KMAKE_OP(roxr, 8, r, .) +{ + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + + if(orig_shift != 0) + { + uint shift = orig_shift % 9; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = ROR_9(src | (XFLAG_AS_1() << 8), shift); + + USE_CYCLES(orig_shift<<CYC_SHIFT); + + FLAG_C = FLAG_X = res; + res = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = FLAG_X; + FLAG_N = NFLAG_8(*r_dst); + FLAG_Z = MASK_OUT_ABOVE_8(*r_dst); + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(roxr, 16, r, .) +{ + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + + if(orig_shift != 0) + { + uint shift = orig_shift % 17; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = ROR_17(src | (XFLAG_AS_1() << 16), shift); + + USE_CYCLES(orig_shift<<CYC_SHIFT); + + FLAG_C = FLAG_X = res >> 8; + res = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = FLAG_X; + FLAG_N = NFLAG_16(*r_dst); + FLAG_Z = MASK_OUT_ABOVE_16(*r_dst); + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(roxr, 32, r, .) +{ +#if M68K_USE_64_BIT + + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + + if(orig_shift != 0) + { + uint shift = orig_shift % 33; + uint64 src = *r_dst; + uint64 res = src | (((uint64)XFLAG_AS_1()) << 32); + + res = ROR_33_64(res, shift); + + USE_CYCLES(orig_shift<<CYC_SHIFT); + + FLAG_C = FLAG_X = res >> 24; + res = MASK_OUT_ABOVE_32(res); + + *r_dst = res; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = FLAG_X; + FLAG_N = NFLAG_32(*r_dst); + FLAG_Z = *r_dst; + FLAG_V = VFLAG_CLEAR; + +#else + + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + uint shift = orig_shift % 33; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32((ROR_33(src, shift) & ~(1 << (32 - shift))) | (XFLAG_AS_1() << (32 - shift))); + uint new_x_flag = src & (1 << (shift - 1)); + + if(orig_shift != 0) + USE_CYCLES(orig_shift<<CYC_SHIFT); + + if(shift != 0) + { + *r_dst = res; + FLAG_X = (new_x_flag != 0)<<8; + } + else + res = src; + FLAG_C = FLAG_X; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + +#endif +} + + +M68KMAKE_OP(roxr, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = m68ki_read_16(ea); + uint res = ROR_17(src | (XFLAG_AS_1() << 16), 1); + + FLAG_C = FLAG_X = res >> 8; + res = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(roxl, 8, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = ROL_9(src | (XFLAG_AS_1() << 8), shift); + + FLAG_C = FLAG_X = res; + res = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(roxl, 16, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = ROL_17(src | (XFLAG_AS_1() << 16), shift); + + FLAG_C = FLAG_X = res >> 8; + res = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(roxl, 32, s, .) +{ +#if M68K_USE_64_BIT + + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint64 src = *r_dst; + uint64 res = src | (((uint64)XFLAG_AS_1()) << 32); + + res = ROL_33_64(res, shift); + + FLAG_C = FLAG_X = res >> 24; + res = MASK_OUT_ABOVE_32(res); + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + +#else + + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32((ROL_33(src, shift) & ~(1 << (shift - 1))) | (XFLAG_AS_1() << (shift - 1))); + uint new_x_flag = src & (1 << (32 - shift)); + + *r_dst = res; + + FLAG_C = FLAG_X = (new_x_flag != 0)<<8; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + +#endif +} + + +M68KMAKE_OP(roxl, 8, r, .) +{ + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + + + if(orig_shift != 0) + { + uint shift = orig_shift % 9; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = ROL_9(src | (XFLAG_AS_1() << 8), shift); + + USE_CYCLES(orig_shift<<CYC_SHIFT); + + FLAG_C = FLAG_X = res; + res = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = FLAG_X; + FLAG_N = NFLAG_8(*r_dst); + FLAG_Z = MASK_OUT_ABOVE_8(*r_dst); + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(roxl, 16, r, .) +{ + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + + if(orig_shift != 0) + { + uint shift = orig_shift % 17; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = ROL_17(src | (XFLAG_AS_1() << 16), shift); + + USE_CYCLES(orig_shift<<CYC_SHIFT); + + FLAG_C = FLAG_X = res >> 8; + res = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = FLAG_X; + FLAG_N = NFLAG_16(*r_dst); + FLAG_Z = MASK_OUT_ABOVE_16(*r_dst); + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(roxl, 32, r, .) +{ +#if M68K_USE_64_BIT + + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + + if(orig_shift != 0) + { + uint shift = orig_shift % 33; + uint64 src = *r_dst; + uint64 res = src | (((uint64)XFLAG_AS_1()) << 32); + + res = ROL_33_64(res, shift); + + USE_CYCLES(orig_shift<<CYC_SHIFT); + + FLAG_C = FLAG_X = res >> 24; + res = MASK_OUT_ABOVE_32(res); + + *r_dst = res; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = FLAG_X; + FLAG_N = NFLAG_32(*r_dst); + FLAG_Z = *r_dst; + FLAG_V = VFLAG_CLEAR; + +#else + + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + uint shift = orig_shift % 33; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32((ROL_33(src, shift) & ~(1 << (shift - 1))) | (XFLAG_AS_1() << (shift - 1))); + uint new_x_flag = src & (1 << (32 - shift)); + + if(orig_shift != 0) + USE_CYCLES(orig_shift<<CYC_SHIFT); + + if(shift != 0) + { + *r_dst = res; + FLAG_X = (new_x_flag != 0)<<8; + } + else + res = src; + FLAG_C = FLAG_X; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + +#endif +} + + +M68KMAKE_OP(roxl, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = m68ki_read_16(ea); + uint res = ROL_17(src | (XFLAG_AS_1() << 16), 1); + + FLAG_C = FLAG_X = res >> 8; + res = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(rtd, 32, ., .) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + uint new_pc = m68ki_pull_32(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + MAKE_INT_16(OPER_I_16())); + m68ki_jump(new_pc); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(rte, 32, ., .) +{ + if(FLAG_S) + { + uint new_sr; + uint new_pc; + uint format_word; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + + if(CPU_TYPE_IS_000(CPU_TYPE)) + { + new_sr = m68ki_pull_16(); + new_pc = m68ki_pull_32(); + m68ki_jump(new_pc); + m68ki_set_sr(new_sr); + return; + } + + if(CPU_TYPE_IS_010(CPU_TYPE)) + { + format_word = m68ki_read_16(REG_A[7]+6) >> 12; + if(format_word == 0) + { + new_sr = m68ki_pull_16(); + new_pc = m68ki_pull_32(); + m68ki_fake_pull_16(); /* format word */ + m68ki_jump(new_pc); + m68ki_set_sr(new_sr); + return; + } + /* Not handling bus fault (9) */ + m68ki_exception_format_error(); + return; + } + + /* Otherwise it's 020 */ +rte_loop: + format_word = m68ki_read_16(REG_A[7]+6) >> 12; + switch(format_word) + { + case 0: /* Normal */ + new_sr = m68ki_pull_16(); + new_pc = m68ki_pull_32(); + m68ki_fake_pull_16(); /* format word */ + m68ki_jump(new_pc); + m68ki_set_sr(new_sr); + return; + case 1: /* Throwaway */ + new_sr = m68ki_pull_16(); + m68ki_fake_pull_32(); /* program counter */ + m68ki_fake_pull_16(); /* format word */ + m68ki_set_sr_noint(new_sr); + goto rte_loop; + case 2: /* Trap */ + new_sr = m68ki_pull_16(); + new_pc = m68ki_pull_32(); + m68ki_fake_pull_16(); /* format word */ + m68ki_fake_pull_32(); /* address */ + m68ki_jump(new_pc); + m68ki_set_sr(new_sr); + return; + } + /* Not handling long or short bus fault */ + m68ki_exception_format_error(); + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(rtm, 32, ., .) +{ + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(rtr, 32, ., .) +{ + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_set_ccr(m68ki_pull_16()); + m68ki_jump(m68ki_pull_32()); +} + + +M68KMAKE_OP(rts, 32, ., .) +{ + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_jump(m68ki_pull_32()); +} + + +M68KMAKE_OP(sbcd, 8, rr, .) +{ + uint* r_dst = &DX; + uint src = DY; + uint dst = *r_dst; + uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res -= 6; + res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res += 0xa0; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; +} + + +M68KMAKE_OP(sbcd, 8, mm, ax7) +{ + uint src = OPER_AY_PD_8(); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res -= 6; + res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res += 0xa0; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(sbcd, 8, mm, ay7) +{ + uint src = OPER_A7_PD_8(); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res -= 6; + res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res += 0xa0; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(sbcd, 8, mm, axy7) +{ + uint src = OPER_A7_PD_8(); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res -= 6; + res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res += 0xa0; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(sbcd, 8, mm, .) +{ + uint src = OPER_AY_PD_8(); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res -= 6; + res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res += 0xa0; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(st, 8, ., d) +{ + DY |= 0xff; +} + + +M68KMAKE_OP(st, 8, ., .) +{ + m68ki_write_8(M68KMAKE_GET_EA_AY_8, 0xff); +} + + +M68KMAKE_OP(sf, 8, ., d) +{ + DY &= 0xffffff00; +} + + +M68KMAKE_OP(sf, 8, ., .) +{ + m68ki_write_8(M68KMAKE_GET_EA_AY_8, 0); +} + + +M68KMAKE_OP(scc, 8, ., d) +{ + if(M68KMAKE_CC) + { + DY |= 0xff; + return; + } + DY &= 0xffffff00; +} + + +M68KMAKE_OP(scc, 8, ., .) +{ + m68ki_write_8(M68KMAKE_GET_EA_AY_8, M68KMAKE_CC ? 0xff : 0); +} + + +M68KMAKE_OP(stop, 0, ., .) +{ + if(FLAG_S) + { + uint new_sr = OPER_I_16(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + CPU_STOPPED |= STOP_LEVEL_STOP; + m68ki_set_sr(new_sr); + m68ki_remaining_cycles = 0; + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(sub, 8, er, d) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_8(DY); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(sub, 8, er, .) +{ + uint* r_dst = &DX; + uint src = M68KMAKE_GET_OPER_AY_8; + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(sub, 16, er, d) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_16(DY); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(sub, 16, er, a) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_16(AY); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(sub, 16, er, .) +{ + uint* r_dst = &DX; + uint src = M68KMAKE_GET_OPER_AY_16; + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(sub, 32, er, d) +{ + uint* r_dst = &DX; + uint src = DY; + uint dst = *r_dst; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(sub, 32, er, a) +{ + uint* r_dst = &DX; + uint src = AY; + uint dst = *r_dst; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(sub, 32, er, .) +{ + uint* r_dst = &DX; + uint src = M68KMAKE_GET_OPER_AY_32; + uint dst = *r_dst; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(sub, 8, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint src = MASK_OUT_ABOVE_8(DX); + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +M68KMAKE_OP(sub, 16, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = MASK_OUT_ABOVE_16(DX); + uint dst = m68ki_read_16(ea); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + m68ki_write_16(ea, FLAG_Z); +} + + +M68KMAKE_OP(sub, 32, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_32; + uint src = DX; + uint dst = m68ki_read_32(ea); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + m68ki_write_32(ea, FLAG_Z); +} + + +M68KMAKE_OP(suba, 16, ., d) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - MAKE_INT_16(DY)); +} + + +M68KMAKE_OP(suba, 16, ., a) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - MAKE_INT_16(AY)); +} + + +M68KMAKE_OP(suba, 16, ., .) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - MAKE_INT_16(M68KMAKE_GET_OPER_AY_16)); +} + + +M68KMAKE_OP(suba, 32, ., d) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - DY); +} + + +M68KMAKE_OP(suba, 32, ., a) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - AY); +} + + +M68KMAKE_OP(suba, 32, ., .) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - M68KMAKE_GET_OPER_AY_32); +} + + +M68KMAKE_OP(subi, 8, ., d) +{ + uint* r_dst = &DY; + uint src = OPER_I_8(); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(subi, 8, ., .) +{ + uint src = OPER_I_8(); + uint ea = M68KMAKE_GET_EA_AY_8; + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +M68KMAKE_OP(subi, 16, ., d) +{ + uint* r_dst = &DY; + uint src = OPER_I_16(); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(subi, 16, ., .) +{ + uint src = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_16; + uint dst = m68ki_read_16(ea); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + m68ki_write_16(ea, FLAG_Z); +} + + +M68KMAKE_OP(subi, 32, ., d) +{ + uint* r_dst = &DY; + uint src = OPER_I_32(); + uint dst = *r_dst; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(subi, 32, ., .) +{ + uint src = OPER_I_32(); + uint ea = M68KMAKE_GET_EA_AY_32; + uint dst = m68ki_read_32(ea); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + m68ki_write_32(ea, FLAG_Z); +} + + +M68KMAKE_OP(subq, 8, ., d) +{ + uint* r_dst = &DY; + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(subq, 8, ., .) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = M68KMAKE_GET_EA_AY_8; + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +M68KMAKE_OP(subq, 16, ., d) +{ + uint* r_dst = &DY; + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(subq, 16, ., a) +{ + uint* r_dst = &AY; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - ((((REG_IR >> 9) - 1) & 7) + 1)); +} + + +M68KMAKE_OP(subq, 16, ., .) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = M68KMAKE_GET_EA_AY_16; + uint dst = m68ki_read_16(ea); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + m68ki_write_16(ea, FLAG_Z); +} + + +M68KMAKE_OP(subq, 32, ., d) +{ + uint* r_dst = &DY; + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint dst = *r_dst; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(subq, 32, ., a) +{ + uint* r_dst = &AY; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - ((((REG_IR >> 9) - 1) & 7) + 1)); +} + + +M68KMAKE_OP(subq, 32, ., .) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = M68KMAKE_GET_EA_AY_32; + uint dst = m68ki_read_32(ea); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + m68ki_write_32(ea, FLAG_Z); +} + + +M68KMAKE_OP(subx, 8, rr, .) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_8(DY); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; +} + + +M68KMAKE_OP(subx, 16, rr, .) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_16(DY); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + res = MASK_OUT_ABOVE_16(res); + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; +} + + +M68KMAKE_OP(subx, 32, rr, .) +{ + uint* r_dst = &DX; + uint src = DY; + uint dst = *r_dst; + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + res = MASK_OUT_ABOVE_32(res); + FLAG_Z |= res; + + *r_dst = res; +} + + +M68KMAKE_OP(subx, 8, mm, ax7) +{ + uint src = OPER_AY_PD_8(); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(subx, 8, mm, ay7) +{ + uint src = OPER_A7_PD_8(); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(subx, 8, mm, axy7) +{ + uint src = OPER_A7_PD_8(); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(subx, 8, mm, .) +{ + uint src = OPER_AY_PD_8(); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(subx, 16, mm, .) +{ + uint src = OPER_AY_PD_16(); + uint ea = EA_AX_PD_16(); + uint dst = m68ki_read_16(ea); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + res = MASK_OUT_ABOVE_16(res); + FLAG_Z |= res; + + m68ki_write_16(ea, res); +} + + +M68KMAKE_OP(subx, 32, mm, .) +{ + uint src = OPER_AY_PD_32(); + uint ea = EA_AX_PD_32(); + uint dst = m68ki_read_32(ea); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + res = MASK_OUT_ABOVE_32(res); + FLAG_Z |= res; + + m68ki_write_32(ea, res); +} + + +M68KMAKE_OP(swap, 32, ., .) +{ + uint* r_dst = &DY; + + FLAG_Z = MASK_OUT_ABOVE_32(*r_dst<<16); + *r_dst = (*r_dst>>16) | FLAG_Z; + + FLAG_Z = *r_dst; + FLAG_N = NFLAG_32(*r_dst); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(tas, 8, ., d) +{ + uint* r_dst = &DY; + + FLAG_Z = MASK_OUT_ABOVE_8(*r_dst); + FLAG_N = NFLAG_8(*r_dst); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst |= 0x80; +} + + +M68KMAKE_OP(tas, 8, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint dst = m68ki_read_8(ea); + + FLAG_Z = dst; + FLAG_N = NFLAG_8(dst); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + m68ki_write_8(ea, dst | 0x80); +} + + +M68KMAKE_OP(trap, 0, ., .) +{ + /* Trap#n stacks exception frame type 0 */ + m68ki_exception_trapN(EXCEPTION_TRAP_BASE + (REG_IR & 0xf)); /* HJB 990403 */ +} + + +M68KMAKE_OP(trapt, 0, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(trapt, 16, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(trapt, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(trapf, 0, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(trapf, 16, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_PC += 2; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(trapf, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_PC += 4; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(trapcc, 0, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(M68KMAKE_CC) + m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(trapcc, 16, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(M68KMAKE_CC) + { + m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 2; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(trapcc, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(M68KMAKE_CC) + { + m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(trapv, 0, ., .) +{ + if(COND_VC()) + { + return; + } + m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ +} + + +M68KMAKE_OP(tst, 8, ., d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(tst, 8, ., .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(tst, 8, ., pcdi) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_PCDI_8(); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(tst, 8, ., pcix) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_PCIX_8(); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(tst, 8, ., i) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_I_8(); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(tst, 16, ., d) +{ + uint res = MASK_OUT_ABOVE_16(DY); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(tst, 16, ., a) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = MAKE_INT_16(AY); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(tst, 16, ., .) +{ + uint res = M68KMAKE_GET_OPER_AY_16; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(tst, 16, ., pcdi) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_PCDI_16(); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(tst, 16, ., pcix) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_PCIX_16(); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(tst, 16, ., i) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_I_16(); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(tst, 32, ., d) +{ + uint res = DY; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(tst, 32, ., a) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = AY; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(tst, 32, ., .) +{ + uint res = M68KMAKE_GET_OPER_AY_32; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(tst, 32, ., pcdi) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_PCDI_32(); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(tst, 32, ., pcix) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_PCIX_32(); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(tst, 32, ., i) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_I_32(); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(unlk, 32, ., a7) +{ + REG_A[7] = m68ki_read_32(REG_A[7]); +} + + +M68KMAKE_OP(unlk, 32, ., .) +{ + uint* r_dst = &AY; + + REG_A[7] = *r_dst; + *r_dst = m68ki_pull_32(); +} + + +M68KMAKE_OP(unpk, 16, rr, .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: DX and DY are reversed in Motorola's docs */ + uint src = DY; + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | (((((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16()) & 0xffff); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(unpk, 16, mm, ax7) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: AX and AY are reversed in Motorola's docs */ + uint src = OPER_AY_PD_8(); + uint ea_dst; + + src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(); + ea_dst = EA_A7_PD_8(); + m68ki_write_8(ea_dst, (src >> 8) & 0xff); + ea_dst = EA_A7_PD_8(); + m68ki_write_8(ea_dst, src & 0xff); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(unpk, 16, mm, ay7) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: AX and AY are reversed in Motorola's docs */ + uint src = OPER_A7_PD_8(); + uint ea_dst; + + src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(); + ea_dst = EA_AX_PD_8(); + m68ki_write_8(ea_dst, (src >> 8) & 0xff); + ea_dst = EA_AX_PD_8(); + m68ki_write_8(ea_dst, src & 0xff); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(unpk, 16, mm, axy7) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint src = OPER_A7_PD_8(); + uint ea_dst; + + src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(); + ea_dst = EA_A7_PD_8(); + m68ki_write_8(ea_dst, (src >> 8) & 0xff); + ea_dst = EA_A7_PD_8(); + m68ki_write_8(ea_dst, src & 0xff); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(unpk, 16, mm, .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: AX and AY are reversed in Motorola's docs */ + uint src = OPER_AY_PD_8(); + uint ea_dst; + + src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(); + ea_dst = EA_AX_PD_8(); + m68ki_write_8(ea_dst, (src >> 8) & 0xff); + ea_dst = EA_AX_PD_8(); + m68ki_write_8(ea_dst, src & 0xff); + return; + } + m68ki_exception_illegal(); +} + + + +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +M68KMAKE_END diff --git a/plugins/ao/eng_ssf/m68kconf.h b/plugins/ao/eng_ssf/m68kconf.h new file mode 100644 index 00000000..74c2dd22 --- /dev/null +++ b/plugins/ao/eng_ssf/m68kconf.h @@ -0,0 +1,181 @@ +/* ======================================================================== */ +/* ========================= LICENSING & COPYRIGHT ======================== */ +/* ======================================================================== */ +/* + * MUSASHI + * Version 3.3 + * + * A portable Motorola M680x0 processor emulation engine. + * Copyright 1998-2001 Karl Stenerud. All rights reserved. + * + * This code may be freely used for non-commercial purposes as long as this + * copyright notice remains unaltered in the source code and any binary files + * containing this code in compiled form. + * + * All other lisencing terms must be negotiated with the author + * (Karl Stenerud). + * + * The latest version of this code can be obtained at: + * http://kstenerud.cjb.net + */ + + + +#ifndef M68KCONF__HEADER +#define M68KCONF__HEADER + + +/* Configuration switches. + * Use OPT_SPECIFY_HANDLER for configuration options that allow callbacks. + * OPT_SPECIFY_HANDLER causes the core to link directly to the function + * or macro you specify, rather than using callback functions whose pointer + * must be passed in using m68k_set_xxx_callback(). + */ +#define OPT_OFF 0 +#define OPT_ON 1 +#define OPT_SPECIFY_HANDLER 2 + + +/* ======================================================================== */ +/* ============================== MAME STUFF ============================== */ +/* ======================================================================== */ + +/* If you're compiling this for MAME, only change M68K_COMPILE_FOR_MAME + * to OPT_ON and use m68kmame.h to configure the 68k core. + */ +#ifndef M68K_COMPILE_FOR_MAME +#define M68K_COMPILE_FOR_MAME OPT_OFF +#endif /* M68K_COMPILE_FOR_MAME */ + +#if M68K_COMPILE_FOR_MAME == OPT_ON +#include "m68kmame.h" +#else + + + +/* ======================================================================== */ +/* ============================= CONFIGURATION ============================ */ +/* ======================================================================== */ + +/* Turn ON if you want to use the following M68K variants */ +#define M68K_EMULATE_010 OPT_OFF +#define M68K_EMULATE_EC020 OPT_OFF +#define M68K_EMULATE_020 OPT_OFF + + +/* If ON, the CPU will call m68k_read_immediate_xx() for immediate addressing + * and m68k_read_pcrelative_xx() for PC-relative addressing. + * If off, all read requests from the CPU will be redirected to m68k_read_xx() + */ +#define M68K_SEPARATE_READS OPT_OFF + +/* If ON, the CPU will call m68k_write_32_pd() when it executes move.l with a + * predecrement destination EA mode instead of m68k_write_32(). + * To simulate real 68k behavior, m68k_write_32_pd() must first write the high + * word to [address+2], and then write the low word to [address]. + */ +#define M68K_SIMULATE_PD_WRITES OPT_OFF + +/* If ON, CPU will call the interrupt acknowledge callback when it services an + * interrupt. + * If off, all interrupts will be autovectored and all interrupt requests will + * auto-clear when the interrupt is serviced. + */ +#define M68K_EMULATE_INT_ACK OPT_ON +#define M68K_INT_ACK_CALLBACK(A) your_int_ack_handler_function(A) + + +/* If ON, CPU will call the breakpoint acknowledge callback when it encounters + * a breakpoint instruction and it is running a 68010+. + */ +#define M68K_EMULATE_BKPT_ACK OPT_OFF +#define M68K_BKPT_ACK_CALLBACK() your_bkpt_ack_handler_function() + + +/* If ON, the CPU will monitor the trace flags and take trace exceptions + */ +#define M68K_EMULATE_TRACE OPT_OFF + + +/* If ON, CPU will call the output reset callback when it encounters a reset + * instruction. + */ +#define M68K_EMULATE_RESET OPT_OFF +#define M68K_RESET_CALLBACK() your_reset_handler_function() + + +/* If ON, CPU will call the set fc callback on every memory access to + * differentiate between user/supervisor, program/data access like a real + * 68000 would. This should be enabled and the callback should be set if you + * want to properly emulate the m68010 or higher. (moves uses function codes + * to read/write data from different address spaces) + */ +#define M68K_EMULATE_FC OPT_OFF +#define M68K_SET_FC_CALLBACK(A) your_set_fc_handler_function(A) + + +/* If ON, CPU will call the pc changed callback when it changes the PC by a + * large value. This allows host programs to be nicer when it comes to + * fetching immediate data and instructions on a banked memory system. + */ +#define M68K_MONITOR_PC OPT_OFF +#define M68K_SET_PC_CALLBACK(A) your_pc_changed_handler_function(A) + + +/* If ON, CPU will call the instruction hook callback before every + * instruction. + */ +#define M68K_INSTRUCTION_HOOK OPT_OFF +#define M68K_INSTRUCTION_CALLBACK() your_instruction_hook_function() + + +/* If ON, the CPU will emulate the 4-byte prefetch queue of a real 68000 */ +#define M68K_EMULATE_PREFETCH OPT_ON + + +/* If ON, the CPU will generate address error exceptions if it tries to + * access a word or longword at an odd address. + * NOTE: Do not enable this! It is not working! + */ +#define M68K_EMULATE_ADDRESS_ERROR OPT_OFF + + +/* Turn ON to enable logging of illegal instruction calls. + * M68K_LOG_FILEHANDLE must be #defined to a stdio file stream. + * Turn on M68K_LOG_1010_1111 to log all 1010 and 1111 calls. + */ +#define M68K_LOG_ENABLE OPT_OFF +#define M68K_LOG_1010_1111 OPT_OFF +#define M68K_LOG_FILEHANDLE some_file_handle + + +/* ----------------------------- COMPATIBILITY ---------------------------- */ + +/* The following options set optimizations that violate the current ANSI + * standard, but will be compliant under the forthcoming C9X standard. + */ + + +/* If ON, the enulation core will use 64-bit integers to speed up some + * operations. +*/ +#define M68K_USE_64_BIT OPT_OFF + + +/* Set to your compiler's static inline keyword to enable it, or + * set it to blank to disable it. + * If you define INLINE in the makefile, it will override this value. + * NOTE: not enabling inline functions will SEVERELY slow down emulation. + */ +#ifndef INLINE +#define INLINE static __inline__ +#endif /* INLINE */ + +#endif /* M68K_COMPILE_FOR_MAME */ + + +/* ======================================================================== */ +/* ============================== END OF FILE ============================= */ +/* ======================================================================== */ + +#endif /* M68KCONF__HEADER */ diff --git a/plugins/ao/eng_ssf/m68kcpu.c b/plugins/ao/eng_ssf/m68kcpu.c new file mode 100644 index 00000000..9624ea5c --- /dev/null +++ b/plugins/ao/eng_ssf/m68kcpu.c @@ -0,0 +1,861 @@ +/* ======================================================================== */ +/* ========================= LICENSING & COPYRIGHT ======================== */ +/* ======================================================================== */ + +#if 0 +static const char* copyright_notice = +"MUSASHI\n" +"Version 3.3 (2001-01-29)\n" +"A portable Motorola M680x0 processor emulation engine.\n" +"Copyright 1998-2001 Karl Stenerud. All rights reserved.\n" +"\n" +"This code may be freely used for non-commercial purpooses as long as this\n" +"copyright notice remains unaltered in the source code and any binary files\n" +"containing this code in compiled form.\n" +"\n" +"All other lisencing terms must be negotiated with the author\n" +"(Karl Stenerud).\n" +"\n" +"The latest version of this code can be obtained at:\n" +"http://kstenerud.cjb.net\n" +; +#endif + + +/* ======================================================================== */ +/* ================================= NOTES ================================ */ +/* ======================================================================== */ + + + +/* ======================================================================== */ +/* ================================ INCLUDES ============================== */ +/* ======================================================================== */ + +#include <stdlib.h> +#include <string.h> +#include "m68kops.h" +#include "m68kcpu.h" + +#pragma GCC optimize("O0") + +/* ======================================================================== */ +/* ================================= DATA ================================= */ +/* ======================================================================== */ + +#ifdef M68K_LOG_ENABLE +char* m68ki_cpu_names[9] = +{ + "Invalid CPU", + "M68000", + "M68010", + "Invalid CPU", + "M68EC020" + "Invalid CPU", + "Invalid CPU", + "Invalid CPU", + "M68020" +}; +#endif /* M68K_LOG_ENABLE */ + +/* Used by shift & rotate instructions */ +uint8 m68ki_shift_8_table[65] = +{ + 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff +}; +uint16 m68ki_shift_16_table[65] = +{ + 0x0000, 0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00, + 0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff +}; +uint m68ki_shift_32_table[65] = +{ + 0x00000000, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000, + 0xfc000000, 0xfe000000, 0xff000000, 0xff800000, 0xffc00000, 0xffe00000, + 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, 0xffff8000, + 0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00, + 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8, + 0xfffffffc, 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff +}; + + +/* Number of clock cycles to use for exception processing. + * I used 4 for any vectors that are undocumented for processing times. + */ +uint8 m68ki_exception_cycle_table[3][256] = +{ + { /* 000 */ + 4, /* 0: Reset - Initial Stack Pointer */ + 4, /* 1: Reset - Initial Program Counter */ + 50, /* 2: Bus Error (unemulated) */ + 50, /* 3: Address Error (unemulated) */ + 34, /* 4: Illegal Instruction */ + 38, /* 5: Divide by Zero -- ASG: changed from 42 */ + 40, /* 6: CHK -- ASG: chanaged from 44 */ + 34, /* 7: TRAPV */ + 34, /* 8: Privilege Violation */ + 34, /* 9: Trace */ + 4, /* 10: 1010 */ + 4, /* 11: 1111 */ + 4, /* 12: RESERVED */ + 4, /* 13: Coprocessor Protocol Violation (unemulated) */ + 4, /* 14: Format Error */ + 44, /* 15: Uninitialized Interrupt */ + 4, /* 16: RESERVED */ + 4, /* 17: RESERVED */ + 4, /* 18: RESERVED */ + 4, /* 19: RESERVED */ + 4, /* 20: RESERVED */ + 4, /* 21: RESERVED */ + 4, /* 22: RESERVED */ + 4, /* 23: RESERVED */ + 44, /* 24: Spurious Interrupt */ + 44, /* 25: Level 1 Interrupt Autovector */ + 44, /* 26: Level 2 Interrupt Autovector */ + 44, /* 27: Level 3 Interrupt Autovector */ + 44, /* 28: Level 4 Interrupt Autovector */ + 44, /* 29: Level 5 Interrupt Autovector */ + 44, /* 30: Level 6 Interrupt Autovector */ + 44, /* 31: Level 7 Interrupt Autovector */ + 34, /* 32: TRAP #0 -- ASG: chanaged from 38 */ + 34, /* 33: TRAP #1 */ + 34, /* 34: TRAP #2 */ + 34, /* 35: TRAP #3 */ + 34, /* 36: TRAP #4 */ + 34, /* 37: TRAP #5 */ + 34, /* 38: TRAP #6 */ + 34, /* 39: TRAP #7 */ + 34, /* 40: TRAP #8 */ + 34, /* 41: TRAP #9 */ + 34, /* 42: TRAP #10 */ + 34, /* 43: TRAP #11 */ + 34, /* 44: TRAP #12 */ + 34, /* 45: TRAP #13 */ + 34, /* 46: TRAP #14 */ + 34, /* 47: TRAP #15 */ + 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */ + 4, /* 49: FP Inexact Result (unemulated) */ + 4, /* 50: FP Divide by Zero (unemulated) */ + 4, /* 51: FP Underflow (unemulated) */ + 4, /* 52: FP Operand Error (unemulated) */ + 4, /* 53: FP Overflow (unemulated) */ + 4, /* 54: FP Signaling NAN (unemulated) */ + 4, /* 55: FP Unimplemented Data Type (unemulated) */ + 4, /* 56: MMU Configuration Error (unemulated) */ + 4, /* 57: MMU Illegal Operation Error (unemulated) */ + 4, /* 58: MMU Access Level Violation Error (unemulated) */ + 4, /* 59: RESERVED */ + 4, /* 60: RESERVED */ + 4, /* 61: RESERVED */ + 4, /* 62: RESERVED */ + 4, /* 63: RESERVED */ + /* 64-255: User Defined */ + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 + }, + { /* 010 */ + 4, /* 0: Reset - Initial Stack Pointer */ + 4, /* 1: Reset - Initial Program Counter */ + 126, /* 2: Bus Error (unemulated) */ + 126, /* 3: Address Error (unemulated) */ + 38, /* 4: Illegal Instruction */ + 44, /* 5: Divide by Zero */ + 44, /* 6: CHK */ + 34, /* 7: TRAPV */ + 38, /* 8: Privilege Violation */ + 38, /* 9: Trace */ + 4, /* 10: 1010 */ + 4, /* 11: 1111 */ + 4, /* 12: RESERVED */ + 4, /* 13: Coprocessor Protocol Violation (unemulated) */ + 4, /* 14: Format Error */ + 44, /* 15: Uninitialized Interrupt */ + 4, /* 16: RESERVED */ + 4, /* 17: RESERVED */ + 4, /* 18: RESERVED */ + 4, /* 19: RESERVED */ + 4, /* 20: RESERVED */ + 4, /* 21: RESERVED */ + 4, /* 22: RESERVED */ + 4, /* 23: RESERVED */ + 46, /* 24: Spurious Interrupt */ + 46, /* 25: Level 1 Interrupt Autovector */ + 46, /* 26: Level 2 Interrupt Autovector */ + 46, /* 27: Level 3 Interrupt Autovector */ + 46, /* 28: Level 4 Interrupt Autovector */ + 46, /* 29: Level 5 Interrupt Autovector */ + 46, /* 30: Level 6 Interrupt Autovector */ + 46, /* 31: Level 7 Interrupt Autovector */ + 38, /* 32: TRAP #0 */ + 38, /* 33: TRAP #1 */ + 38, /* 34: TRAP #2 */ + 38, /* 35: TRAP #3 */ + 38, /* 36: TRAP #4 */ + 38, /* 37: TRAP #5 */ + 38, /* 38: TRAP #6 */ + 38, /* 39: TRAP #7 */ + 38, /* 40: TRAP #8 */ + 38, /* 41: TRAP #9 */ + 38, /* 42: TRAP #10 */ + 38, /* 43: TRAP #11 */ + 38, /* 44: TRAP #12 */ + 38, /* 45: TRAP #13 */ + 38, /* 46: TRAP #14 */ + 38, /* 47: TRAP #15 */ + 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */ + 4, /* 49: FP Inexact Result (unemulated) */ + 4, /* 50: FP Divide by Zero (unemulated) */ + 4, /* 51: FP Underflow (unemulated) */ + 4, /* 52: FP Operand Error (unemulated) */ + 4, /* 53: FP Overflow (unemulated) */ + 4, /* 54: FP Signaling NAN (unemulated) */ + 4, /* 55: FP Unimplemented Data Type (unemulated) */ + 4, /* 56: MMU Configuration Error (unemulated) */ + 4, /* 57: MMU Illegal Operation Error (unemulated) */ + 4, /* 58: MMU Access Level Violation Error (unemulated) */ + 4, /* 59: RESERVED */ + 4, /* 60: RESERVED */ + 4, /* 61: RESERVED */ + 4, /* 62: RESERVED */ + 4, /* 63: RESERVED */ + /* 64-255: User Defined */ + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 + }, + { /* 020 */ + 4, /* 0: Reset - Initial Stack Pointer */ + 4, /* 1: Reset - Initial Program Counter */ + 50, /* 2: Bus Error (unemulated) */ + 50, /* 3: Address Error (unemulated) */ + 20, /* 4: Illegal Instruction */ + 38, /* 5: Divide by Zero */ + 40, /* 6: CHK */ + 20, /* 7: TRAPV */ + 34, /* 8: Privilege Violation */ + 25, /* 9: Trace */ + 20, /* 10: 1010 */ + 20, /* 11: 1111 */ + 4, /* 12: RESERVED */ + 4, /* 13: Coprocessor Protocol Violation (unemulated) */ + 4, /* 14: Format Error */ + 30, /* 15: Uninitialized Interrupt */ + 4, /* 16: RESERVED */ + 4, /* 17: RESERVED */ + 4, /* 18: RESERVED */ + 4, /* 19: RESERVED */ + 4, /* 20: RESERVED */ + 4, /* 21: RESERVED */ + 4, /* 22: RESERVED */ + 4, /* 23: RESERVED */ + 30, /* 24: Spurious Interrupt */ + 30, /* 25: Level 1 Interrupt Autovector */ + 30, /* 26: Level 2 Interrupt Autovector */ + 30, /* 27: Level 3 Interrupt Autovector */ + 30, /* 28: Level 4 Interrupt Autovector */ + 30, /* 29: Level 5 Interrupt Autovector */ + 30, /* 30: Level 6 Interrupt Autovector */ + 30, /* 31: Level 7 Interrupt Autovector */ + 20, /* 32: TRAP #0 */ + 20, /* 33: TRAP #1 */ + 20, /* 34: TRAP #2 */ + 20, /* 35: TRAP #3 */ + 20, /* 36: TRAP #4 */ + 20, /* 37: TRAP #5 */ + 20, /* 38: TRAP #6 */ + 20, /* 39: TRAP #7 */ + 20, /* 40: TRAP #8 */ + 20, /* 41: TRAP #9 */ + 20, /* 42: TRAP #10 */ + 20, /* 43: TRAP #11 */ + 20, /* 44: TRAP #12 */ + 20, /* 45: TRAP #13 */ + 20, /* 46: TRAP #14 */ + 20, /* 47: TRAP #15 */ + 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */ + 4, /* 49: FP Inexact Result (unemulated) */ + 4, /* 50: FP Divide by Zero (unemulated) */ + 4, /* 51: FP Underflow (unemulated) */ + 4, /* 52: FP Operand Error (unemulated) */ + 4, /* 53: FP Overflow (unemulated) */ + 4, /* 54: FP Signaling NAN (unemulated) */ + 4, /* 55: FP Unimplemented Data Type (unemulated) */ + 4, /* 56: MMU Configuration Error (unemulated) */ + 4, /* 57: MMU Illegal Operation Error (unemulated) */ + 4, /* 58: MMU Access Level Violation Error (unemulated) */ + 4, /* 59: RESERVED */ + 4, /* 60: RESERVED */ + 4, /* 61: RESERVED */ + 4, /* 62: RESERVED */ + 4, /* 63: RESERVED */ + /* 64-255: User Defined */ + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 + } +}; + +uint8 m68ki_ea_idx_cycle_table[64] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, /* ..01.000 no memory indirect, base NULL */ + 5, /* ..01..01 memory indirect, base NULL, outer NULL */ + 7, /* ..01..10 memory indirect, base NULL, outer 16 */ + 7, /* ..01..11 memory indirect, base NULL, outer 32 */ + 0, 5, 7, 7, 0, 5, 7, 7, 0, 5, 7, 7, + 2, /* ..10.000 no memory indirect, base 16 */ + 7, /* ..10..01 memory indirect, base 16, outer NULL */ + 9, /* ..10..10 memory indirect, base 16, outer 16 */ + 9, /* ..10..11 memory indirect, base 16, outer 32 */ + 0, 7, 9, 9, 0, 7, 9, 9, 0, 7, 9, 9, + 6, /* ..11.000 no memory indirect, base 32 */ + 11, /* ..11..01 memory indirect, base 32, outer NULL */ + 13, /* ..11..10 memory indirect, base 32, outer 16 */ + 13, /* ..11..11 memory indirect, base 32, outer 32 */ + 0, 11, 13, 13, 0, 11, 13, 13, 0, 11, 13, 13 +}; + + + +/* ======================================================================== */ +/* =============================== CALLBACKS ============================== */ +/* ======================================================================== */ + +/* Default callbacks used if the callback hasn't been set yet, or if the + * callback is set to NULL + */ + +/* Interrupt acknowledge */ +static int default_int_ack_callback(m68ki_cpu_core *cpu, int int_level) +{ + cpu->default_int_ack_callback_data = int_level; + CPU_INT_LEVEL = 0; + return M68K_INT_ACK_AUTOVECTOR; +} + +/* Breakpoint acknowledge */ +static void default_bkpt_ack_callback(m68ki_cpu_core *cpu, unsigned int data) +{ + cpu->default_bkpt_ack_callback_data = data; +} + +/* Called when a reset instruction is executed */ +static void default_reset_instr_callback(m68ki_cpu_core *cpu) +{ +} + +/* Called when the program counter changed by a large value */ +static void default_pc_changed_callback(m68ki_cpu_core *cpu, unsigned int new_pc) +{ + cpu->default_pc_changed_callback_data = new_pc; +} + +/* Called every time there's bus activity (read/write to/from memory */ +static void default_set_fc_callback(m68ki_cpu_core *cpu, unsigned int new_fc) +{ + cpu->default_set_fc_callback_data = new_fc; +} + +/* Called every instruction cycle prior to execution */ +static void default_instr_hook_callback(m68ki_cpu_core *cpu) +{ +} + + + +/* ======================================================================== */ +/* ================================= API ================================== */ +/* ======================================================================== */ + +/* Access the internals of the CPU */ +unsigned int m68k_get_reg(m68ki_cpu_core *_cpu, void* context, m68k_register_t regnum) +{ + m68ki_cpu_core* cpu = context != NULL ?(m68ki_cpu_core*)context : _cpu; + + switch(regnum) + { + case M68K_REG_D0: return cpu->dar[0]; + case M68K_REG_D1: return cpu->dar[1]; + case M68K_REG_D2: return cpu->dar[2]; + case M68K_REG_D3: return cpu->dar[3]; + case M68K_REG_D4: return cpu->dar[4]; + case M68K_REG_D5: return cpu->dar[5]; + case M68K_REG_D6: return cpu->dar[6]; + case M68K_REG_D7: return cpu->dar[7]; + case M68K_REG_A0: return cpu->dar[8]; + case M68K_REG_A1: return cpu->dar[9]; + case M68K_REG_A2: return cpu->dar[10]; + case M68K_REG_A3: return cpu->dar[11]; + case M68K_REG_A4: return cpu->dar[12]; + case M68K_REG_A5: return cpu->dar[13]; + case M68K_REG_A6: return cpu->dar[14]; + case M68K_REG_A7: return cpu->dar[15]; + case M68K_REG_PC: return MASK_OUT_ABOVE_32(cpu->pc); + case M68K_REG_SR: return cpu->t1_flag | + cpu->t0_flag | + (cpu->s_flag << 11) | + (cpu->m_flag << 11) | + cpu->int_mask | + ((cpu->x_flag & XFLAG_SET) >> 4) | + ((cpu->n_flag & NFLAG_SET) >> 4) | + ((!cpu->not_z_flag) << 2) | + ((cpu->v_flag & VFLAG_SET) >> 6) | + ((cpu->c_flag & CFLAG_SET) >> 8); + case M68K_REG_SP: return cpu->dar[15]; + case M68K_REG_USP: return cpu->s_flag ? cpu->sp[0] : cpu->dar[15]; + case M68K_REG_ISP: return cpu->s_flag && !cpu->m_flag ? cpu->dar[15] : cpu->sp[4]; + case M68K_REG_MSP: return cpu->s_flag && cpu->m_flag ? cpu->dar[15] : cpu->sp[6]; + case M68K_REG_SFC: return cpu->sfc; + case M68K_REG_DFC: return cpu->dfc; + case M68K_REG_VBR: return cpu->vbr; + case M68K_REG_CACR: return cpu->cacr; + case M68K_REG_CAAR: return cpu->caar; + case M68K_REG_PREF_ADDR: return cpu->pref_addr; + case M68K_REG_PREF_DATA: return cpu->pref_data; + case M68K_REG_PPC: return MASK_OUT_ABOVE_32(cpu->ppc); + case M68K_REG_IR: return cpu->ir; + case M68K_REG_CPU_TYPE: + switch(cpu->cpu_type) + { + case CPU_TYPE_000: return (unsigned int)M68K_CPU_TYPE_68000; + case CPU_TYPE_010: return (unsigned int)M68K_CPU_TYPE_68010; + case CPU_TYPE_EC020: return (unsigned int)M68K_CPU_TYPE_68EC020; + case CPU_TYPE_020: return (unsigned int)M68K_CPU_TYPE_68020; + } + return M68K_CPU_TYPE_INVALID; + default: return 0; + } + return 0; +} + +void m68k_set_reg(m68ki_cpu_core *cpu, m68k_register_t regnum, unsigned int value) +{ + switch(regnum) + { + case M68K_REG_D0: REG_D[0] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_D1: REG_D[1] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_D2: REG_D[2] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_D3: REG_D[3] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_D4: REG_D[4] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_D5: REG_D[5] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_D6: REG_D[6] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_D7: REG_D[7] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_A0: REG_A[0] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_A1: REG_A[1] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_A2: REG_A[2] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_A3: REG_A[3] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_A4: REG_A[4] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_A5: REG_A[5] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_A6: REG_A[6] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_A7: REG_A[7] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_PC: m68ki_jump(cpu, MASK_OUT_ABOVE_32(value)); return; + case M68K_REG_SR: m68ki_set_sr(cpu, value); return; + case M68K_REG_SP: REG_SP = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_USP: if(FLAG_S) + REG_USP = MASK_OUT_ABOVE_32(value); + else + REG_SP = MASK_OUT_ABOVE_32(value); + return; + case M68K_REG_ISP: if(FLAG_S && !FLAG_M) + REG_SP = MASK_OUT_ABOVE_32(value); + else + REG_ISP = MASK_OUT_ABOVE_32(value); + return; + case M68K_REG_MSP: if(FLAG_S && FLAG_M) + REG_SP = MASK_OUT_ABOVE_32(value); + else + REG_MSP = MASK_OUT_ABOVE_32(value); + return; + case M68K_REG_VBR: REG_VBR = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_SFC: REG_SFC = value & 7; return; + case M68K_REG_DFC: REG_DFC = value & 7; return; + case M68K_REG_CACR: REG_CACR = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_CAAR: REG_CAAR = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_PPC: REG_PPC = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_IR: REG_IR = MASK_OUT_ABOVE_16(value); return; + case M68K_REG_CPU_TYPE: m68k_set_cpu_type(cpu, value); return; + default: return; + } +} + +/* Set the callbacks */ +void m68k_set_int_ack_callback(m68ki_cpu_core *cpu, int (*callback)(m68ki_cpu_core *cpu, int int_level)) +{ + CALLBACK_INT_ACK = callback ? callback : default_int_ack_callback; +} + +void m68k_set_bkpt_ack_callback(m68ki_cpu_core *cpu, void (*callback)(m68ki_cpu_core *cpu, unsigned int data)) +{ + CALLBACK_BKPT_ACK = callback ? callback : default_bkpt_ack_callback; +} + +void m68k_set_reset_instr_callback(m68ki_cpu_core *cpu, void (*callback)(m68ki_cpu_core *cpu)) +{ + CALLBACK_RESET_INSTR = callback ? callback : default_reset_instr_callback; +} + +void m68k_set_pc_changed_callback(m68ki_cpu_core *cpu, void (*callback)(m68ki_cpu_core *cpu, unsigned int new_pc)) +{ + CALLBACK_PC_CHANGED = callback ? callback : default_pc_changed_callback; +} + +void m68k_set_fc_callback(m68ki_cpu_core *cpu, void (*callback)(m68ki_cpu_core *cpu, unsigned int new_fc)) +{ + CALLBACK_SET_FC = callback ? callback : default_set_fc_callback; +} + +void m68k_set_instr_hook_callback(m68ki_cpu_core *cpu, void (*callback)(m68ki_cpu_core *cpu)) +{ + CALLBACK_INSTR_HOOK = callback ? callback : default_instr_hook_callback; +} + +#include <stdio.h> +/* Set the CPU type. */ +void m68k_set_cpu_type(m68ki_cpu_core *cpu, unsigned int cpu_type) +{ + switch(cpu_type) + { + case M68K_CPU_TYPE_68000: + CPU_TYPE = CPU_TYPE_000; + CPU_ADDRESS_MASK = 0x00ffffff; + CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */ + CYC_INSTRUCTION = m68ki_cycles[0]; + CYC_EXCEPTION = m68ki_exception_cycle_table[0]; + CYC_BCC_NOTAKE_B = -2; + CYC_BCC_NOTAKE_W = 2; + CYC_DBCC_F_NOEXP = -2; + CYC_DBCC_F_EXP = 2; + CYC_SCC_R_FALSE = 2; + CYC_MOVEM_W = 2; + CYC_MOVEM_L = 3; + CYC_SHIFT = 1; + CYC_RESET = 132; + return; + case M68K_CPU_TYPE_68010: + CPU_TYPE = CPU_TYPE_010; + CPU_ADDRESS_MASK = 0x00ffffff; + CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */ + CYC_INSTRUCTION = m68ki_cycles[1]; + CYC_EXCEPTION = m68ki_exception_cycle_table[1]; + CYC_BCC_NOTAKE_B = -4; + CYC_BCC_NOTAKE_W = 0; + CYC_DBCC_F_NOEXP = 0; + CYC_DBCC_F_EXP = 6; + CYC_SCC_R_FALSE = 0; + CYC_MOVEM_W = 2; + CYC_MOVEM_L = 3; + CYC_SHIFT = 1; + CYC_RESET = 130; + return; + case M68K_CPU_TYPE_68EC020: + CPU_TYPE = CPU_TYPE_EC020; + CPU_ADDRESS_MASK = 0x00ffffff; + CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ + CYC_INSTRUCTION = m68ki_cycles[2]; + CYC_EXCEPTION = m68ki_exception_cycle_table[2]; + CYC_BCC_NOTAKE_B = -2; + CYC_BCC_NOTAKE_W = 0; + CYC_DBCC_F_NOEXP = 0; + CYC_DBCC_F_EXP = 4; + CYC_SCC_R_FALSE = 0; + CYC_MOVEM_W = 2; + CYC_MOVEM_L = 2; + CYC_SHIFT = 0; + CYC_RESET = 518; + return; + case M68K_CPU_TYPE_68020: + CPU_TYPE = CPU_TYPE_020; + CPU_ADDRESS_MASK = 0xffffffff; + CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ + CYC_INSTRUCTION = m68ki_cycles[2]; + CYC_EXCEPTION = m68ki_exception_cycle_table[2]; + CYC_BCC_NOTAKE_B = -2; + CYC_BCC_NOTAKE_W = 0; + CYC_DBCC_F_NOEXP = 0; + CYC_DBCC_F_EXP = 4; + CYC_SCC_R_FALSE = 0; + CYC_MOVEM_W = 2; + CYC_MOVEM_L = 2; + CYC_SHIFT = 0; + CYC_RESET = 518; + return; + } +} + +/* Execute some instructions until we use up num_cycles clock cycles */ +/* ASG: removed per-instruction interrupt checks */ +int m68k_execute(m68ki_cpu_core *cpu, int num_cycles) +{ + /* Make sure we're not stopped */ + if(!CPU_STOPPED) + { + /* Set our pool of clock cycles available */ + SET_CYCLES(num_cycles); + cpu->m68ki_initial_cycles = num_cycles; + + /* ASG: update cycles */ + USE_CYCLES(CPU_INT_CYCLES); + CPU_INT_CYCLES = 0; + + /* Return point if we had an address error */ + m68ki_set_address_error_trap(); /* auto-disable (see m68kcpu.h) */ + + /* Main loop. Keep going until we run out of clock cycles */ + do + { + /* Set tracing accodring to T1. (T0 is done inside instruction) */ + m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */ + + /* Set the address space for reads */ + m68ki_use_data_space(); /* auto-disable (see m68kcpu.h) */ + + /* Call external hook to peek at CPU */ + m68ki_instr_hook(); /* auto-disable (see m68kcpu.h) */ + +// if (REG_PC == m68k_trap0) printf("at trap0 (crash), prev_pc = %x\n", REG_PPC); + + /* Record previous program counter */ + REG_PPC = REG_PC; + + /* Read an instruction and call its handler */ + REG_IR = m68ki_read_imm_16(cpu); + m68ki_instruction_jump_table[REG_IR](cpu); + USE_CYCLES(CYC_INSTRUCTION[REG_IR]); + + /* Trace m68k_exception, if necessary */ + m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */ + } while(GET_CYCLES() > 0); + + /* set previous PC to current PC for the next entry into the loop */ + REG_PPC = REG_PC; + + /* ASG: update cycles */ + USE_CYCLES(CPU_INT_CYCLES); + CPU_INT_CYCLES = 0; + + /* return how many clocks we used */ + return cpu->m68ki_initial_cycles - GET_CYCLES(); + } + + /* We get here if the CPU is stopped or halted */ + SET_CYCLES(0); + CPU_INT_CYCLES = 0; + + return num_cycles; +} + + +int m68k_cycles_run(m68ki_cpu_core *cpu) +{ + return cpu->m68ki_initial_cycles - GET_CYCLES(); +} + +int m68k_cycles_remaining(m68ki_cpu_core *cpu) +{ + return GET_CYCLES(); +} + +/* Change the timeslice */ +void m68k_modify_timeslice(m68ki_cpu_core *cpu, int cycles) +{ + cpu->m68ki_initial_cycles += cycles; + ADD_CYCLES(cycles); +} + + +void m68k_end_timeslice(m68ki_cpu_core *cpu) +{ + cpu->m68ki_initial_cycles = GET_CYCLES(); + SET_CYCLES(0); +} + + +/* ASG: rewrote so that the int_level is a mask of the IPL0/IPL1/IPL2 bits */ +/* KS: Modified so that IPL* bits match with mask positions in the SR + * and cleaned out remenants of the interrupt controller. + */ +void m68k_set_irq(m68ki_cpu_core *cpu, unsigned int int_level) +{ + uint old_level = CPU_INT_LEVEL; + CPU_INT_LEVEL = int_level << 8; + + /* A transition from < 7 to 7 always interrupts (NMI) */ + /* Note: Level 7 can also level trigger like a normal IRQ */ + if(old_level != 0x0700 && CPU_INT_LEVEL == 0x0700) + m68ki_exception_interrupt(cpu, 7); /* Edge triggered level 7 (NMI) */ + else + m68ki_check_interrupts(cpu); /* Level triggered (IRQ) */ +} + +m68ki_cpu_core *m68k_init(void) +{ + static uint emulation_initialized = 0; + + /* The first call to this function initializes the opcode handler jump table */ + if(!emulation_initialized) + { + m68ki_build_opcode_table(); + emulation_initialized = 1; + } + + m68ki_cpu_core *cpu = malloc (sizeof (m68ki_cpu_core)); + memset (cpu, 0, sizeof (m68ki_cpu_core)); + + m68k_set_int_ack_callback(cpu, NULL); + m68k_set_bkpt_ack_callback(cpu, NULL); + m68k_set_reset_instr_callback(cpu, NULL); + m68k_set_pc_changed_callback(cpu, NULL); + m68k_set_fc_callback(cpu, NULL); + m68k_set_instr_hook_callback(cpu, NULL); + return cpu; +} + +/* Pulse the RESET line on the CPU */ +void m68k_pulse_reset(m68ki_cpu_core *cpu) +{ + /* Clear all stop levels and eat up all remaining cycles */ + CPU_STOPPED = 0; + SET_CYCLES(0); + + CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET; + + /* Turn off tracing */ + FLAG_T1 = FLAG_T0 = 0; + m68ki_clear_trace(); + /* Interrupt mask to level 7 */ + FLAG_INT_MASK = 0x0700; + /* Reset VBR */ + REG_VBR = 0; + /* Go to supervisor mode */ + m68ki_set_sm_flag(cpu, SFLAG_SET | MFLAG_CLEAR); + + /* Invalidate the prefetch queue */ +#if M68K_EMULATE_PREFETCH + /* Set to arbitrary number since our first fetch is from 0 */ + CPU_PREF_ADDR = 0x1000; +#endif /* M68K_EMULATE_PREFETCH */ + + /* Read the initial stack pointer and program counter */ + m68ki_jump(cpu, 0); + REG_SP = m68ki_read_imm_32(cpu); + REG_PC = m68ki_read_imm_32(cpu); + m68ki_jump(cpu, REG_PC); + + CPU_RUN_MODE = RUN_MODE_NORMAL; +} + +/* Pulse the HALT line on the CPU */ +void m68k_pulse_halt(m68ki_cpu_core *cpu) +{ + CPU_STOPPED |= STOP_LEVEL_HALT; +} + +#if 0 + +/* Get and set the current CPU context */ +/* This is to allow for multiple CPUs */ +unsigned int m68k_context_size(m68ki_cpu_core *cpu) +{ + return sizeof(m68ki_cpu_core); +} + +unsigned int m68k_get_context(m68ki_cpu_core *cpu, void* dst) +{ + if(dst) *(m68ki_cpu_core*)dst = cpu; + return sizeof(m68ki_cpu_core); +} + +void m68k_set_context(void* src) +{ + if(src) m68ki_cpu = *(m68ki_cpu_core*)src; +} + +#endif + +/* ======================================================================== */ +/* ============================== MAME STUFF ============================== */ +/* ======================================================================== */ + +#if M68K_COMPILE_FOR_MAME == OPT_ON + +#include "state.h" + +static struct { + UINT16 sr; + int stopped; + int halted; +} m68k_substate; + +static void m68k_prepare_substate(void) +{ + m68k_substate.sr = m68ki_get_sr(); + m68k_substate.stopped = (CPU_STOPPED & STOP_LEVEL_STOP) != 0; + m68k_substate.halted = (CPU_STOPPED & STOP_LEVEL_HALT) != 0; +} + +static void m68k_post_load(void) +{ + m68ki_set_sr_noint_nosp(m68k_substate.sr); + CPU_STOPPED = m68k_substate.stopped ? STOP_LEVEL_STOP : 0 + | m68k_substate.halted ? STOP_LEVEL_HALT : 0; + m68ki_jump(REG_PC); +} + +void m68k_state_register(const char *type) +{ + int cpu = cpu_getactivecpu(); + + state_save_register_UINT32(type, cpu, "D" , REG_D, 8); + state_save_register_UINT32(type, cpu, "A" , REG_A, 8); + state_save_register_UINT32(type, cpu, "PPC" , ®_PPC, 1); + state_save_register_UINT32(type, cpu, "PC" , ®_PC, 1); + state_save_register_UINT32(type, cpu, "USP" , ®_USP, 1); + state_save_register_UINT32(type, cpu, "ISP" , ®_ISP, 1); + state_save_register_UINT32(type, cpu, "MSP" , ®_MSP, 1); + state_save_register_UINT32(type, cpu, "VBR" , ®_VBR, 1); + state_save_register_UINT32(type, cpu, "SFC" , ®_SFC, 1); + state_save_register_UINT32(type, cpu, "DFC" , ®_DFC, 1); + state_save_register_UINT32(type, cpu, "CACR" , ®_CACR, 1); + state_save_register_UINT32(type, cpu, "CAAR" , ®_CAAR, 1); + state_save_register_UINT16(type, cpu, "SR" , &m68k_substate.sr, 1); + state_save_register_UINT32(type, cpu, "INT_LEVEL" , &CPU_INT_LEVEL, 1); + state_save_register_UINT32(type, cpu, "INT_CYCLES", &CPU_INT_CYCLES, 1); + state_save_register_int (type, cpu, "STOPPED" , &m68k_substate.stopped); + state_save_register_int (type, cpu, "HALTED" , &m68k_substate.halted); + state_save_register_UINT32(type, cpu, "PREF_ADDR" , &CPU_PREF_ADDR, 1); + state_save_register_UINT32(type, cpu, "PREF_DATA" , &CPU_PREF_DATA, 1); + state_save_register_func_presave(m68k_prepare_substate); + state_save_register_func_postload(m68k_post_load); +} + +#endif /* M68K_COMPILE_FOR_MAME */ + +/* ======================================================================== */ +/* ============================== END OF FILE ============================= */ +/* ======================================================================== */ diff --git a/plugins/ao/eng_ssf/m68kcpu.h b/plugins/ao/eng_ssf/m68kcpu.h new file mode 100644 index 00000000..77e4191b --- /dev/null +++ b/plugins/ao/eng_ssf/m68kcpu.h @@ -0,0 +1,1989 @@ +#include <stdio.h> +#ifdef _MSC_VER +#include "ao.h" +#else +#undef INLINE +#define INLINE static inline +#endif +/* ======================================================================== */ +/* ========================= LICENSING & COPYRIGHT ======================== */ +/* ======================================================================== */ +/* + * MUSASHI + * Version 3.3 + * + * A portable Motorola M680x0 processor emulation engine. + * Copyright 1998-2001 Karl Stenerud. All rights reserved. + * + * This code may be freely used for non-commercial purposes as long as this + * copyright notice remains unaltered in the source code and any binary files + * containing this code in compiled form. + * + * All other lisencing terms must be negotiated with the author + * (Karl Stenerud). + * + * The latest version of this code can be obtained at: + * http://kstenerud.cjb.net + */ + + + + +#ifndef M68KCPU__HEADER +#define M68KCPU__HEADER + +#include "m68k.h" +#include <limits.h> + +#if M68K_EMULATE_ADDRESS_ERROR +#include <setjmp.h> +#endif /* M68K_EMULATE_ADDRESS_ERROR */ + +/* ======================================================================== */ +/* ==================== ARCHITECTURE-DEPENDANT DEFINES ==================== */ +/* ======================================================================== */ + +/* Check for > 32bit sizes */ +#if UINT_MAX > 0xffffffff + #define M68K_INT_GT_32_BIT 1 +#else + #define M68K_INT_GT_32_BIT 0 +#endif + +/* Data types used in this emulation core */ +#undef sint8 +#undef sint16 +#undef sint32 +#undef sint64 +#undef uint8 +#undef uint16 +#undef uint32 +#undef uint64 +#undef sint +#undef uint + +#define sint8 signed char /* ASG: changed from char to signed char */ +#define sint16 signed short +#define sint32 signed long +#define uint8 unsigned char +#define uint16 unsigned short +#define uint32 unsigned long +/* signed and unsigned int must be at least 32 bits wide */ +#define sint signed int +#define uint unsigned int + + +#if 0 +#if M68K_USE_64_BIT +#define sint64 signed long long +#define uint64 unsigned long long +#else +#define sint64 sint32 +#define uint64 uint32 +#endif /* M68K_USE_64_BIT */ +#endif + + +/* Allow for architectures that don't have 8-bit sizes */ +#if UCHAR_MAX == 0xff + #define MAKE_INT_8(A) (sint8)(A) +#else + #undef sint8 + #define sint8 signed int + #undef uint8 + #define uint8 unsigned int + INLINE sint MAKE_INT_8(uint value) + { + return (value & 0x80) ? value | ~0xff : value & 0xff; + } +#endif /* UCHAR_MAX == 0xff */ + + +/* Allow for architectures that don't have 16-bit sizes */ +#if USHRT_MAX == 0xffff + #define MAKE_INT_16(A) (sint16)(A) +#else + #undef sint16 + #define sint16 signed int + #undef uint16 + #define uint16 unsigned int + INLINE sint MAKE_INT_16(uint value) + { + return (value & 0x8000) ? value | ~0xffff : value & 0xffff; + } +#endif /* USHRT_MAX == 0xffff */ + + +/* Allow for architectures that don't have 32-bit sizes */ +#if ULONG_MAX == 0xffffffff + #define MAKE_INT_32(A) (sint32)(A) +#else + #undef sint32 + #define sint32 signed int + #undef uint32 + #define uint32 unsigned int + INLINE sint MAKE_INT_32(uint value) + { + return (value & 0x80000000) ? value | ~0xffffffff : value & 0xffffffff; + } +#endif /* ULONG_MAX == 0xffffffff */ + +/* ======================================================================== */ +/* =============================== PROTOTYPES ============================= */ +/* ======================================================================== */ + + +typedef struct m68ki_cpu_core_s +{ + uint cpu_type; /* CPU Type: 68000, 68010, 68EC020, or 68020 */ + uint dar[16]; /* Data and Address Registers */ + uint ppc; /* Previous program counter */ + uint pc; /* Program Counter */ + uint sp[7]; /* User, Interrupt, and Master Stack Pointers */ + uint vbr; /* Vector Base Register (m68010+) */ + uint sfc; /* Source Function Code Register (m68010+) */ + uint dfc; /* Destination Function Code Register (m68010+) */ + uint cacr; /* Cache Control Register (m68020, unemulated) */ + uint caar; /* Cache Address Register (m68020, unemulated) */ + uint ir; /* Instruction Register */ + uint t1_flag; /* Trace 1 */ + uint t0_flag; /* Trace 0 */ + uint s_flag; /* Supervisor */ + uint m_flag; /* Master/Interrupt state */ + uint x_flag; /* Extend */ + uint n_flag; /* Negative */ + uint not_z_flag; /* Zero, inverted for speedups */ + uint v_flag; /* Overflow */ + uint c_flag; /* Carry */ + uint int_mask; /* I0-I2 */ + uint int_level; /* State of interrupt pins IPL0-IPL2 -- ASG: changed from ints_pending */ + uint int_cycles; /* ASG: extra cycles from generated interrupts */ + uint stopped; /* Stopped state */ + uint pref_addr; /* Last prefetch address */ + uint pref_data; /* Data in the prefetch queue */ + uint address_mask; /* Available address pins */ + uint sr_mask; /* Implemented status register bits */ + uint instr_mode; /* Stores whether we are in instruction mode or group 0/1 exception mode */ + uint run_mode; /* Stores whether we are processing a reset, bus error, address error, or something else */ + + /* Clocks required for instructions / exceptions */ + uint cyc_bcc_notake_b; + uint cyc_bcc_notake_w; + uint cyc_dbcc_f_noexp; + uint cyc_dbcc_f_exp; + uint cyc_scc_r_false; + uint cyc_movem_w; + uint cyc_movem_l; + uint cyc_shift; + uint cyc_reset; + uint8* cyc_instruction; + uint8* cyc_exception; + + /* Callbacks to host */ + int (*int_ack_callback)(struct m68ki_cpu_core_s *cpu, int int_line); /* Interrupt Acknowledge */ + void (*bkpt_ack_callback)(struct m68ki_cpu_core_s *cpu, unsigned int data); /* Breakpoint Acknowledge */ + void (*reset_instr_callback)(struct m68ki_cpu_core_s *cpu); /* Called when a RESET instruction is encountered */ + void (*pc_changed_callback)(struct m68ki_cpu_core_s *cpu, unsigned int new_pc); /* Called when the PC changes by a large amount */ + void (*set_fc_callback)(struct m68ki_cpu_core_s *cpu, unsigned int new_fc); /* Called when the CPU function code changes */ + void (*instr_hook_callback)(struct m68ki_cpu_core_s *cpu); /* Called every instruction cycle prior to execution */ + +#if M68K_EMULATE_ADDRESS_ERROR + jmp_buf m68ki_aerr_trap; +#endif /* M68K_EMULATE_ADDRESS_ERROR */ + + uint m68ki_aerr_address; + uint m68ki_aerr_write_mode; + uint m68ki_aerr_fc; + + int default_int_ack_callback_data; + unsigned int default_bkpt_ack_callback_data; + unsigned int default_pc_changed_callback_data; + unsigned int default_set_fc_callback_data; + int m68k_trap0; + int m68ki_initial_cycles; + int m68ki_remaining_cycles; /* Number of clocks remaining */ + uint m68ki_tracing; + uint m68ki_address_space; + + uint8 sat_ram[512*1024]; + + void *SCSP; +} m68ki_cpu_core; + + +extern uint8 m68ki_shift_8_table[]; +extern uint16 m68ki_shift_16_table[]; +extern uint m68ki_shift_32_table[]; +extern uint8 m68ki_exception_cycle_table[][256]; +extern uint8 m68ki_ea_idx_cycle_table[]; + +m68ki_cpu_core *m68k_init(void); +/* Execute some instructions until we use up num_cycles clock cycles */ +/* ASG: removed per-instruction interrupt checks */ +int m68k_execute(m68ki_cpu_core *cpu, int num_cycles); + + +/* ======================================================================== */ +/* ============================ GENERAL DEFINES =========================== */ +/* ======================================================================== */ + +/* Exception Vectors handled by emulation */ +#define EXCEPTION_BUS_ERROR 2 /* This one is not emulated! */ +#define EXCEPTION_ADDRESS_ERROR 3 /* This one is partially emulated (doesn't stack a proper frame yet) */ +#define EXCEPTION_ILLEGAL_INSTRUCTION 4 +#define EXCEPTION_ZERO_DIVIDE 5 +#define EXCEPTION_CHK 6 +#define EXCEPTION_TRAPV 7 +#define EXCEPTION_PRIVILEGE_VIOLATION 8 +#define EXCEPTION_TRACE 9 +#define EXCEPTION_1010 10 +#define EXCEPTION_1111 11 +#define EXCEPTION_FORMAT_ERROR 14 +#define EXCEPTION_UNINITIALIZED_INTERRUPT 15 +#define EXCEPTION_SPURIOUS_INTERRUPT 24 +#define EXCEPTION_INTERRUPT_AUTOVECTOR 24 +#define EXCEPTION_TRAP_BASE 32 + +/* Function codes set by CPU during data/address bus activity */ +#define FUNCTION_CODE_USER_DATA 1 +#define FUNCTION_CODE_USER_PROGRAM 2 +#define FUNCTION_CODE_SUPERVISOR_DATA 5 +#define FUNCTION_CODE_SUPERVISOR_PROGRAM 6 +#define FUNCTION_CODE_CPU_SPACE 7 + +/* CPU types for deciding what to emulate */ +#define CPU_TYPE_000 1 +#define CPU_TYPE_010 2 +#define CPU_TYPE_EC020 4 +#define CPU_TYPE_020 8 + +/* Different ways to stop the CPU */ +#define STOP_LEVEL_STOP 1 +#define STOP_LEVEL_HALT 2 + +/* Used for 68000 address error processing */ +#define INSTRUCTION_YES 0 +#define INSTRUCTION_NO 0x08 +#define MODE_READ 0x10 +#define MODE_WRITE 0 + +#define RUN_MODE_NORMAL 0 +#define RUN_MODE_BERR_AERR_RESET 1 + +#ifndef NULL +#define NULL ((void*)0) +#endif + +/* ======================================================================== */ +/* ================================ MACROS ================================ */ +/* ======================================================================== */ + + +/* ---------------------------- General Macros ---------------------------- */ + +/* Bit Isolation Macros */ +#define BIT_0(A) ((A) & 0x00000001) +#define BIT_1(A) ((A) & 0x00000002) +#define BIT_2(A) ((A) & 0x00000004) +#define BIT_3(A) ((A) & 0x00000008) +#define BIT_4(A) ((A) & 0x00000010) +#define BIT_5(A) ((A) & 0x00000020) +#define BIT_6(A) ((A) & 0x00000040) +#define BIT_7(A) ((A) & 0x00000080) +#define BIT_8(A) ((A) & 0x00000100) +#define BIT_9(A) ((A) & 0x00000200) +#define BIT_A(A) ((A) & 0x00000400) +#define BIT_B(A) ((A) & 0x00000800) +#define BIT_C(A) ((A) & 0x00001000) +#define BIT_D(A) ((A) & 0x00002000) +#define BIT_E(A) ((A) & 0x00004000) +#define BIT_F(A) ((A) & 0x00008000) +#define BIT_10(A) ((A) & 0x00010000) +#define BIT_11(A) ((A) & 0x00020000) +#define BIT_12(A) ((A) & 0x00040000) +#define BIT_13(A) ((A) & 0x00080000) +#define BIT_14(A) ((A) & 0x00100000) +#define BIT_15(A) ((A) & 0x00200000) +#define BIT_16(A) ((A) & 0x00400000) +#define BIT_17(A) ((A) & 0x00800000) +#define BIT_18(A) ((A) & 0x01000000) +#define BIT_19(A) ((A) & 0x02000000) +#define BIT_1A(A) ((A) & 0x04000000) +#define BIT_1B(A) ((A) & 0x08000000) +#define BIT_1C(A) ((A) & 0x10000000) +#define BIT_1D(A) ((A) & 0x20000000) +#define BIT_1E(A) ((A) & 0x40000000) +#define BIT_1F(A) ((A) & 0x80000000) + +/* Get the most significant bit for specific sizes */ +#define GET_MSB_8(A) ((A) & 0x80) +#define GET_MSB_9(A) ((A) & 0x100) +#define GET_MSB_16(A) ((A) & 0x8000) +#define GET_MSB_17(A) ((A) & 0x10000) +#define GET_MSB_32(A) ((A) & 0x80000000) +#if M68K_USE_64_BIT +#define GET_MSB_33(A) ((A) & 0x100000000) +#endif /* M68K_USE_64_BIT */ + +/* Isolate nibbles */ +#define LOW_NIBBLE(A) ((A) & 0x0f) +#define HIGH_NIBBLE(A) ((A) & 0xf0) + +/* These are used to isolate 8, 16, and 32 bit sizes */ +#define MASK_OUT_ABOVE_2(A) ((A) & 3) +#define MASK_OUT_ABOVE_8(A) ((A) & 0xff) +#define MASK_OUT_ABOVE_16(A) ((A) & 0xffff) +#define MASK_OUT_BELOW_2(A) ((A) & ~3) +#define MASK_OUT_BELOW_8(A) ((A) & ~0xff) +#define MASK_OUT_BELOW_16(A) ((A) & ~0xffff) + +/* No need to mask if we are 32 bit */ +#if M68K_INT_GT_32_BIT || M68K_USE_64_BIT + #define MASK_OUT_ABOVE_32(A) ((A) & 0xffffffff) + #define MASK_OUT_BELOW_32(A) ((A) & ~0xffffffff) +#else + #define MASK_OUT_ABOVE_32(A) (A) + #define MASK_OUT_BELOW_32(A) 0 +#endif /* M68K_INT_GT_32_BIT || M68K_USE_64_BIT */ + +/* Simulate address lines of 68k family */ +#define ADDRESS_68K(A) ((A)&CPU_ADDRESS_MASK) + + +/* Shift & Rotate Macros. */ +#define LSL(A, C) ((A) << (C)) +#define LSR(A, C) ((A) >> (C)) + +/* Some > 32-bit optimizations */ +#if M68K_INT_GT_32_BIT + /* Shift left and right */ + #define LSR_32(A, C) ((A) >> (C)) + #define LSL_32(A, C) ((A) << (C)) +#else + /* We have to do this because the morons at ANSI decided that shifts + * by >= data size are undefined. + */ + #define LSR_32(A, C) ((C) < 32 ? (A) >> (C) : 0) + #define LSL_32(A, C) ((C) < 32 ? (A) << (C) : 0) +#endif /* M68K_INT_GT_32_BIT */ + +#if M68K_USE_64_BIT + #define LSL_32_64(A, C) ((A) << (C)) + #define LSR_32_64(A, C) ((A) >> (C)) + #define ROL_33_64(A, C) (LSL_32_64(A, C) | LSR_32_64(A, 33-(C))) + #define ROR_33_64(A, C) (LSR_32_64(A, C) | LSL_32_64(A, 33-(C))) +#endif /* M68K_USE_64_BIT */ + +#define ROL_8(A, C) MASK_OUT_ABOVE_8(LSL(A, C) | LSR(A, 8-(C))) +#define ROL_9(A, C) (LSL(A, C) | LSR(A, 9-(C))) +#define ROL_16(A, C) MASK_OUT_ABOVE_16(LSL(A, C) | LSR(A, 16-(C))) +#define ROL_17(A, C) (LSL(A, C) | LSR(A, 17-(C))) +#define ROL_32(A, C) MASK_OUT_ABOVE_32(LSL_32(A, C) | LSR_32(A, 32-(C))) +#define ROL_33(A, C) (LSL_32(A, C) | LSR_32(A, 33-(C))) + +#define ROR_8(A, C) MASK_OUT_ABOVE_8(LSR(A, C) | LSL(A, 8-(C))) +#define ROR_9(A, C) (LSR(A, C) | LSL(A, 9-(C))) +#define ROR_16(A, C) MASK_OUT_ABOVE_16(LSR(A, C) | LSL(A, 16-(C))) +#define ROR_17(A, C) (LSR(A, C) | LSL(A, 17-(C))) +#define ROR_32(A, C) MASK_OUT_ABOVE_32(LSR_32(A, C) | LSL_32(A, 32-(C))) +#define ROR_33(A, C) (LSR_32(A, C) | LSL_32(A, 33-(C))) + + + +/* ------------------------------ CPU Access ------------------------------ */ + +/* Access the CPU registers */ +#define CPU_TYPE cpu->cpu_type + +#define REG_DA cpu->dar /* easy access to data and address regs */ +#define REG_D cpu->dar +#define REG_A (cpu->dar+8) +#define REG_PPC cpu->ppc +#define REG_PC cpu->pc +#define REG_SP_BASE cpu->sp +#define REG_USP cpu->sp[0] +#define REG_ISP cpu->sp[4] +#define REG_MSP cpu->sp[6] +#define REG_SP cpu->dar[15] +#define REG_VBR cpu->vbr +#define REG_SFC cpu->sfc +#define REG_DFC cpu->dfc +#define REG_CACR cpu->cacr +#define REG_CAAR cpu->caar +#define REG_IR cpu->ir + +#define FLAG_T1 cpu->t1_flag +#define FLAG_T0 cpu->t0_flag +#define FLAG_S cpu->s_flag +#define FLAG_M cpu->m_flag +#define FLAG_X cpu->x_flag +#define FLAG_N cpu->n_flag +#define FLAG_Z cpu->not_z_flag +#define FLAG_V cpu->v_flag +#define FLAG_C cpu->c_flag +#define FLAG_INT_MASK cpu->int_mask + +#define CPU_INT_LEVEL cpu->int_level /* ASG: changed from CPU_INTS_PENDING */ +#define CPU_INT_CYCLES cpu->int_cycles /* ASG */ +#define CPU_STOPPED cpu->stopped +#define CPU_PREF_ADDR cpu->pref_addr +#define CPU_PREF_DATA cpu->pref_data +#define CPU_ADDRESS_MASK cpu->address_mask +#define CPU_SR_MASK cpu->sr_mask +#define CPU_INSTR_MODE cpu->instr_mode +#define CPU_RUN_MODE cpu->run_mode + +#define CYC_INSTRUCTION cpu->cyc_instruction +#define CYC_EXCEPTION cpu->cyc_exception +#define CYC_BCC_NOTAKE_B cpu->cyc_bcc_notake_b +#define CYC_BCC_NOTAKE_W cpu->cyc_bcc_notake_w +#define CYC_DBCC_F_NOEXP cpu->cyc_dbcc_f_noexp +#define CYC_DBCC_F_EXP cpu->cyc_dbcc_f_exp +#define CYC_SCC_R_FALSE cpu->cyc_scc_r_false +#define CYC_MOVEM_W cpu->cyc_movem_w +#define CYC_MOVEM_L cpu->cyc_movem_l +#define CYC_SHIFT cpu->cyc_shift +#define CYC_RESET cpu->cyc_reset + + +#define CALLBACK_INT_ACK cpu->int_ack_callback +#define CALLBACK_BKPT_ACK cpu->bkpt_ack_callback +#define CALLBACK_RESET_INSTR cpu->reset_instr_callback +#define CALLBACK_PC_CHANGED cpu->pc_changed_callback +#define CALLBACK_SET_FC cpu->set_fc_callback +#define CALLBACK_INSTR_HOOK cpu->instr_hook_callback + + + +/* ----------------------------- Configuration ---------------------------- */ + +/* These defines are dependant on the configuration defines in m68kconf.h */ + +/* Disable certain comparisons if we're not using all CPU types */ +#if M68K_EMULATE_020 + #define CPU_TYPE_IS_020_PLUS(A) ((A) & CPU_TYPE_020) + #define CPU_TYPE_IS_020_LESS(A) 1 +#else + #define CPU_TYPE_IS_020_PLUS(A) 0 + #define CPU_TYPE_IS_020_LESS(A) 1 +#endif + +#if M68K_EMULATE_EC020 + #define CPU_TYPE_IS_EC020_PLUS(A) ((A) & (CPU_TYPE_EC020 | CPU_TYPE_020)) + #define CPU_TYPE_IS_EC020_LESS(A) ((A) & (CPU_TYPE_000 | CPU_TYPE_010 | CPU_TYPE_EC020)) +#else + #define CPU_TYPE_IS_EC020_PLUS(A) CPU_TYPE_IS_020_PLUS(A) + #define CPU_TYPE_IS_EC020_LESS(A) CPU_TYPE_IS_020_LESS(A) +#endif + +#if M68K_EMULATE_010 + #define CPU_TYPE_IS_010(A) ((A) == CPU_TYPE_010) + #define CPU_TYPE_IS_010_PLUS(A) ((A) & (CPU_TYPE_010 | CPU_TYPE_EC020 | CPU_TYPE_020)) + #define CPU_TYPE_IS_010_LESS(A) ((A) & (CPU_TYPE_000 | CPU_TYPE_010)) +#else + #define CPU_TYPE_IS_010(A) 0 + #define CPU_TYPE_IS_010_PLUS(A) CPU_TYPE_IS_EC020_PLUS(A) + #define CPU_TYPE_IS_010_LESS(A) CPU_TYPE_IS_EC020_LESS(A) +#endif + +#if M68K_EMULATE_020 || M68K_EMULATE_EC020 + #define CPU_TYPE_IS_020_VARIANT(A) ((A) & (CPU_TYPE_EC020 | CPU_TYPE_020)) +#else + #define CPU_TYPE_IS_020_VARIANT(A) 0 +#endif + +#if M68K_EMULATE_020 || M68K_EMULATE_EC020 || M68K_EMULATE_010 + #define CPU_TYPE_IS_000(A) ((A) == CPU_TYPE_000) +#else + #define CPU_TYPE_IS_000(A) 1 +#endif + + +#if !M68K_SEPARATE_READS +#define m68k_read_immediate_16(A) m68ki_read_program_16(A) +#define m68k_read_immediate_32(A) m68ki_read_program_32(A) + +#define m68k_read_pcrelative_8(A) m68ki_read_program_8(A) +#define m68k_read_pcrelative_16(A) m68ki_read_program_16(A) +#define m68k_read_pcrelative_32(A) m68ki_read_program_32(A) +#endif /* M68K_SEPARATE_READS */ + + +/* Enable or disable callback functions */ +#if M68K_EMULATE_INT_ACK + #if M68K_EMULATE_INT_ACK == OPT_SPECIFY_HANDLER + #define m68ki_int_ack(cpu, A) M68K_INT_ACK_CALLBACK(cpu, A) + #else + #define m68ki_int_ack(cpu, A) CALLBACK_INT_ACK(cpu, A) + #endif +#else + /* Default action is to used autovector mode, which is most common */ + #define m68ki_int_ack(cpu, A) M68K_INT_ACK_AUTOVECTOR +#endif /* M68K_EMULATE_INT_ACK */ + +#if M68K_EMULATE_BKPT_ACK + #if M68K_EMULATE_BKPT_ACK == OPT_SPECIFY_HANDLER + #define m68ki_bkpt_ack(A) M68K_BKPT_ACK_CALLBACK(A) + #else + #define m68ki_bkpt_ack(A) CALLBACK_BKPT_ACK(A) + #endif +#else + #define m68ki_bkpt_ack(A) +#endif /* M68K_EMULATE_BKPT_ACK */ + +#if M68K_EMULATE_RESET + #if M68K_EMULATE_RESET == OPT_SPECIFY_HANDLER + #define m68ki_output_reset() M68K_RESET_CALLBACK() + #else + #define m68ki_output_reset() CALLBACK_RESET_INSTR() + #endif +#else + #define m68ki_output_reset() +#endif /* M68K_EMULATE_RESET */ + +#if M68K_INSTRUCTION_HOOK + #if M68K_INSTRUCTION_HOOK == OPT_SPECIFY_HANDLER + #define m68ki_instr_hook() M68K_INSTRUCTION_CALLBACK() + #else + #define m68ki_instr_hook() CALLBACK_INSTR_HOOK() + #endif +#else + #define m68ki_instr_hook() +#endif /* M68K_INSTRUCTION_HOOK */ + +#if M68K_MONITOR_PC + #if M68K_MONITOR_PC == OPT_SPECIFY_HANDLER + #define m68ki_pc_changed(A) M68K_SET_PC_CALLBACK(ADDRESS_68K(A)) + #else + #define m68ki_pc_changed(A) CALLBACK_PC_CHANGED(ADDRESS_68K(A)) + #endif +#else + #define m68ki_pc_changed(A) +#endif /* M68K_MONITOR_PC */ + + +/* Enable or disable function code emulation */ +#if M68K_EMULATE_FC + #if M68K_EMULATE_FC == OPT_SPECIFY_HANDLER + #define m68ki_set_fc(A) M68K_SET_FC_CALLBACK(A) + #else + #define m68ki_set_fc(A) CALLBACK_SET_FC(A) + #endif + #define m68ki_use_data_space() m68ki_address_space = FUNCTION_CODE_USER_DATA + #define m68ki_use_program_space() m68ki_address_space = FUNCTION_CODE_USER_PROGRAM + #define m68ki_get_address_space() m68ki_address_space +#else + #define m68ki_set_fc(A) + #define m68ki_use_data_space() + #define m68ki_use_program_space() + #define m68ki_get_address_space() FUNCTION_CODE_USER_DATA +#endif /* M68K_EMULATE_FC */ + + +/* Enable or disable trace emulation */ +#if M68K_EMULATE_TRACE + /* Initiates trace checking before each instruction (t1) */ + #define m68ki_trace_t1() m68ki_tracing = FLAG_T1 + /* adds t0 to trace checking if we encounter change of flow */ + #define m68ki_trace_t0() m68ki_tracing |= FLAG_T0 + /* Clear all tracing */ + #define m68ki_clear_trace() m68ki_tracing = 0 + /* Cause a trace exception if we are tracing */ + #define m68ki_exception_if_trace() if(m68ki_tracing) m68ki_exception_trace() +#else + #define m68ki_trace_t1() + #define m68ki_trace_t0() + #define m68ki_clear_trace() + #define m68ki_exception_if_trace() +#endif /* M68K_EMULATE_TRACE */ + + + +/* Address error */ +#if M68K_EMULATE_ADDRESS_ERROR + #include <setjmp.h> + extern jmp_buf m68ki_aerr_trap; + + #define m68ki_set_address_error_trap() \ + if(setjmp(m68ki_aerr_trap) != 0) \ + { \ + m68ki_exception_address_error(); \ + if(CPU_STOPPED) \ + { \ + SET_CYCLES(0); \ + CPU_INT_CYCLES = 0; \ + return m68ki_initial_cycles; \ + } \ + } + + #define m68ki_check_address_error(ADDR, WRITE_MODE, FC) \ + if((ADDR)&1) \ + { \ + m68ki_aerr_address = ADDR; \ + m68ki_aerr_write_mode = WRITE_MODE; \ + m68ki_aerr_fc = FC; \ + longjmp(m68ki_aerr_trap, 1); \ + } +#else + #define m68ki_set_address_error_trap() + #define m68ki_check_address_error(ADDR, WRITE_MODE, FC) +#endif /* M68K_ADDRESS_ERROR */ + +/* Logging */ +#if M68K_LOG_ENABLE + #include <stdio.h> + extern FILE* M68K_LOG_FILEHANDLE + extern char* m68ki_cpu_names[]; + + #define M68K_DO_LOG(A) if(M68K_LOG_FILEHANDLE) fprintf A + #if M68K_LOG_1010_1111 + #define M68K_DO_LOG_EMU(A) if(M68K_LOG_FILEHANDLE) fprintf A + #else + #define M68K_DO_LOG_EMU(A) + #endif +#else + #define M68K_DO_LOG(A) + #define M68K_DO_LOG_EMU(A) +#endif + + + +/* -------------------------- EA / Operand Access ------------------------- */ + +/* + * The general instruction format follows this pattern: + * .... XXX. .... .YYY + * where XXX is register X and YYY is register Y + */ +/* Data Register Isolation */ +#define DX (REG_D[(REG_IR >> 9) & 7]) +#define DY (REG_D[REG_IR & 7]) +/* Address Register Isolation */ +#define AX (REG_A[(REG_IR >> 9) & 7]) +#define AY (REG_A[REG_IR & 7]) + + +/* Effective Address Calculations */ +#define EA_AY_AI_8() AY /* address register indirect */ +#define EA_AY_AI_16() EA_AY_AI_8() +#define EA_AY_AI_32() EA_AY_AI_8() +#define EA_AY_PI_8() (AY++) /* postincrement (size = byte) */ +#define EA_AY_PI_16() ((AY+=2)-2) /* postincrement (size = word) */ +#define EA_AY_PI_32() ((AY+=4)-4) /* postincrement (size = long) */ +#define EA_AY_PD_8() (--AY) /* predecrement (size = byte) */ +#define EA_AY_PD_16() (AY-=2) /* predecrement (size = word) */ +#define EA_AY_PD_32() (AY-=4) /* predecrement (size = long) */ +#define EA_AY_DI_8() (AY+MAKE_INT_16(m68ki_read_imm_16(cpu))) /* displacement */ +#define EA_AY_DI_16() EA_AY_DI_8() +#define EA_AY_DI_32() EA_AY_DI_8() +#define EA_AY_IX_8() m68ki_get_ea_ix(cpu, AY) /* indirect + index */ +#define EA_AY_IX_16() EA_AY_IX_8() +#define EA_AY_IX_32() EA_AY_IX_8() + +#define EA_AX_AI_8() AX +#define EA_AX_AI_16() EA_AX_AI_8() +#define EA_AX_AI_32() EA_AX_AI_8() +#define EA_AX_PI_8() (AX++) +#define EA_AX_PI_16() ((AX+=2)-2) +#define EA_AX_PI_32() ((AX+=4)-4) +#define EA_AX_PD_8() (--AX) +#define EA_AX_PD_16() (AX-=2) +#define EA_AX_PD_32() (AX-=4) +#define EA_AX_DI_8() (AX+MAKE_INT_16(m68ki_read_imm_16(cpu))) +#define EA_AX_DI_16() EA_AX_DI_8() +#define EA_AX_DI_32() EA_AX_DI_8() +#define EA_AX_IX_8() m68ki_get_ea_ix(cpu, AX) +#define EA_AX_IX_16() EA_AX_IX_8() +#define EA_AX_IX_32() EA_AX_IX_8() + +#define EA_A7_PI_8() ((REG_A[7]+=2)-2) +#define EA_A7_PD_8() (REG_A[7]-=2) + +#define EA_AW_8() MAKE_INT_16(m68ki_read_imm_16(cpu)) /* absolute word */ +#define EA_AW_16() EA_AW_8() +#define EA_AW_32() EA_AW_8() +#define EA_AL_8() m68ki_read_imm_32(cpu) /* absolute long */ +#define EA_AL_16() EA_AL_8() +#define EA_AL_32() EA_AL_8() +#define EA_PCDI_8() m68ki_get_ea_pcdi(cpu) /* pc indirect + displacement */ +#define EA_PCDI_16() EA_PCDI_8() +#define EA_PCDI_32() EA_PCDI_8() +#define EA_PCIX_8() m68ki_get_ea_pcix(cpu) /* pc indirect + index */ +#define EA_PCIX_16() EA_PCIX_8() +#define EA_PCIX_32() EA_PCIX_8() + + +#define OPER_I_8() m68ki_read_imm_8() +#define OPER_I_16() m68ki_read_imm_16(cpu) +#define OPER_I_32() m68ki_read_imm_32(cpu) + + + +/* --------------------------- Status Register ---------------------------- */ + +/* Flag Calculation Macros */ +#define CFLAG_8(A) (A) +#define CFLAG_16(A) ((A)>>8) + +#if M68K_INT_GT_32_BIT + #define CFLAG_ADD_32(S, D, R) ((R)>>24) + #define CFLAG_SUB_32(S, D, R) ((R)>>24) +#else + #define CFLAG_ADD_32(S, D, R) (((S & D) | (~R & (S | D)))>>23) + #define CFLAG_SUB_32(S, D, R) (((S & R) | (~D & (S | R)))>>23) +#endif /* M68K_INT_GT_32_BIT */ + +#define VFLAG_ADD_8(S, D, R) ((S^R) & (D^R)) +#define VFLAG_ADD_16(S, D, R) (((S^R) & (D^R))>>8) +#define VFLAG_ADD_32(S, D, R) (((S^R) & (D^R))>>24) + +#define VFLAG_SUB_8(S, D, R) ((S^D) & (R^D)) +#define VFLAG_SUB_16(S, D, R) (((S^D) & (R^D))>>8) +#define VFLAG_SUB_32(S, D, R) (((S^D) & (R^D))>>24) + +#define NFLAG_8(A) (A) +#define NFLAG_16(A) ((A)>>8) +#define NFLAG_32(A) ((A)>>24) +#define NFLAG_64(A) ((A)>>56) + +#define ZFLAG_8(A) MASK_OUT_ABOVE_8(A) +#define ZFLAG_16(A) MASK_OUT_ABOVE_16(A) +#define ZFLAG_32(A) MASK_OUT_ABOVE_32(A) + + +/* Flag values */ +#define NFLAG_SET 0x80 +#define NFLAG_CLEAR 0 +#define CFLAG_SET 0x100 +#define CFLAG_CLEAR 0 +#define XFLAG_SET 0x100 +#define XFLAG_CLEAR 0 +#define VFLAG_SET 0x80 +#define VFLAG_CLEAR 0 +#define ZFLAG_SET 0 +#define ZFLAG_CLEAR 0xffffffff + +#define SFLAG_SET 4 +#define SFLAG_CLEAR 0 +#define MFLAG_SET 2 +#define MFLAG_CLEAR 0 + +/* Turn flag values into 1 or 0 */ +#define XFLAG_AS_1() ((FLAG_X>>8)&1) +#define NFLAG_AS_1() ((FLAG_N>>7)&1) +#define VFLAG_AS_1() ((FLAG_V>>7)&1) +#define ZFLAG_AS_1() (!FLAG_Z) +#define CFLAG_AS_1() ((FLAG_C>>8)&1) + + +/* Conditions */ +#define COND_CS() (FLAG_C&0x100) +#define COND_CC() (!COND_CS()) +#define COND_VS() (FLAG_V&0x80) +#define COND_VC() (!COND_VS()) +#define COND_NE() FLAG_Z +#define COND_EQ() (!COND_NE()) +#define COND_MI() (FLAG_N&0x80) +#define COND_PL() (!COND_MI()) +#define COND_LT() ((FLAG_N^FLAG_V)&0x80) +#define COND_GE() (!COND_LT()) +#define COND_HI() (COND_CC() && COND_NE()) +#define COND_LS() (COND_CS() || COND_EQ()) +#define COND_GT() (COND_GE() && COND_NE()) +#define COND_LE() (COND_LT() || COND_EQ()) + +/* Reversed conditions */ +#define COND_NOT_CS() COND_CC() +#define COND_NOT_CC() COND_CS() +#define COND_NOT_VS() COND_VC() +#define COND_NOT_VC() COND_VS() +#define COND_NOT_NE() COND_EQ() +#define COND_NOT_EQ() COND_NE() +#define COND_NOT_MI() COND_PL() +#define COND_NOT_PL() COND_MI() +#define COND_NOT_LT() COND_GE() +#define COND_NOT_GE() COND_LT() +#define COND_NOT_HI() COND_LS() +#define COND_NOT_LS() COND_HI() +#define COND_NOT_GT() COND_LE() +#define COND_NOT_LE() COND_GT() + +/* Not real conditions, but here for convenience */ +#define COND_XS() (FLAG_X&0x100) +#define COND_XC() (!COND_XS) + + +/* Get the condition code register */ +#define m68ki_get_ccr() ((COND_XS() >> 4) | \ + (COND_MI() >> 4) | \ + (COND_EQ() << 2) | \ + (COND_VS() >> 6) | \ + (COND_CS() >> 8)) + +/* Get the status register */ +#define m68ki_get_sr() ( FLAG_T1 | \ + FLAG_T0 | \ + (FLAG_S << 11) | \ + (FLAG_M << 11) | \ + FLAG_INT_MASK | \ + m68ki_get_ccr()) + + + +/* ---------------------------- Cycle Counting ---------------------------- */ + +#define ADD_CYCLES(A) cpu->m68ki_remaining_cycles += (A) +#define USE_CYCLES(A) cpu->m68ki_remaining_cycles -= (A) +#define SET_CYCLES(A) cpu->m68ki_remaining_cycles = A +#define GET_CYCLES() cpu->m68ki_remaining_cycles +#define USE_ALL_CYCLES() cpu->m68ki_remaining_cycles = 0 + + + +/* ----------------------------- Read / Write ----------------------------- */ + +/* Read from the current address space */ +#define m68ki_read_8(A) m68ki_read_8_fc (cpu, A, FLAG_S | m68ki_get_address_space()) +#define m68ki_read_16(A) m68ki_read_16_fc(cpu, A, FLAG_S | m68ki_get_address_space()) +#define m68ki_read_32(A) m68ki_read_32_fc(cpu, A, FLAG_S | m68ki_get_address_space()) + +/* Write to the current data space */ +#define m68ki_write_8(A, V) m68ki_write_8_fc (cpu, A, FLAG_S | FUNCTION_CODE_USER_DATA, V) +#define m68ki_write_16(A, V) m68ki_write_16_fc(cpu, A, FLAG_S | FUNCTION_CODE_USER_DATA, V) +#define m68ki_write_32(A, V) m68ki_write_32_fc(cpu, A, FLAG_S | FUNCTION_CODE_USER_DATA, V) + +#if M68K_SIMULATE_PD_WRITES +#define m68ki_write_32_pd(A, V) m68ki_write_32_pd_fc(cpu, A, FLAG_S | FUNCTION_CODE_USER_DATA, V) +#else +#define m68ki_write_32_pd(A, V) m68ki_write_32_fc(cpu, A, FLAG_S | FUNCTION_CODE_USER_DATA, V) +#endif + +/* map read immediate 8 to read immediate 16 */ +#define m68ki_read_imm_8() MASK_OUT_ABOVE_8(m68ki_read_imm_16(cpu)) + +/* Map PC-relative reads */ +#define m68ki_read_pcrel_8(A) m68k_read_pcrelative_8(A) +#define m68ki_read_pcrel_16(A) m68k_read_pcrelative_16(A) +#define m68ki_read_pcrel_32(A) m68k_read_pcrelative_32(A) + +/* Read from the program space */ +#define m68ki_read_program_8(A) m68ki_read_8_fc(cpu, A, FLAG_S | FUNCTION_CODE_USER_PROGRAM) +#define m68ki_read_program_16(A) m68ki_read_16_fc(cpu, A, FLAG_S | FUNCTION_CODE_USER_PROGRAM) +#define m68ki_read_program_32(A) m68ki_read_32_fc(cpu, A, FLAG_S | FUNCTION_CODE_USER_PROGRAM) + +/* Read from the data space */ +#define m68ki_read_data_8(A) m68ki_read_8_fc(cpu, A, FLAG_S | FUNCTION_CODE_USER_DATA) +#define m68ki_read_data_16(A) m68ki_read_16_fc(cpu, A, FLAG_S | FUNCTION_CODE_USER_DATA) +#define m68ki_read_data_32(A) m68ki_read_32_fc(cpu, A, FLAG_S | FUNCTION_CODE_USER_DATA) + +/* Read data immediately after the program counter */ +INLINE uint m68ki_read_imm_16(m68ki_cpu_core *cpu); +INLINE uint m68ki_read_imm_32(m68ki_cpu_core *cpu); + +/* Read data with specific function code */ +INLINE uint m68ki_read_8_fc (m68ki_cpu_core *cpu, uint address, uint fc); +INLINE uint m68ki_read_16_fc (m68ki_cpu_core *cpu, uint address, uint fc); +INLINE uint m68ki_read_32_fc (m68ki_cpu_core *cpu, uint address, uint fc); + +/* Write data with specific function code */ +INLINE void m68ki_write_8_fc (m68ki_cpu_core *cpu, uint address, uint fc, uint value); +INLINE void m68ki_write_16_fc(m68ki_cpu_core *cpu, uint address, uint fc, uint value); +INLINE void m68ki_write_32_fc(m68ki_cpu_core *cpu, uint address, uint fc, uint value); +#if M68K_SIMULATE_PD_WRITES +INLINE void m68ki_write_32_pd_fc(m68ki_cpu_core *cpu, uint address, uint fc, uint value); +#endif /* M68K_SIMULATE_PD_WRITES */ + +/* Indexed and PC-relative ea fetching */ +INLINE uint m68ki_get_ea_pcdi(m68ki_cpu_core *cpu); +INLINE uint m68ki_get_ea_pcix(m68ki_cpu_core *cpu); +INLINE uint m68ki_get_ea_ix(m68ki_cpu_core *cpu, uint An); + +/* Operand fetching */ +INLINE uint OPER_AY_AI_8(m68ki_cpu_core *cpu); +INLINE uint OPER_AY_AI_16(m68ki_cpu_core *cpu); +INLINE uint OPER_AY_AI_32(m68ki_cpu_core *cpu); +INLINE uint OPER_AY_PI_8(m68ki_cpu_core *cpu); +INLINE uint OPER_AY_PI_16(m68ki_cpu_core *cpu); +INLINE uint OPER_AY_PI_32(m68ki_cpu_core *cpu); +INLINE uint OPER_AY_PD_8(m68ki_cpu_core *cpu); +INLINE uint OPER_AY_PD_16(m68ki_cpu_core *cpu); +INLINE uint OPER_AY_PD_32(m68ki_cpu_core *cpu); +INLINE uint OPER_AY_DI_8(m68ki_cpu_core *cpu); +INLINE uint OPER_AY_DI_16(m68ki_cpu_core *cpu); +INLINE uint OPER_AY_DI_32(m68ki_cpu_core *cpu); +INLINE uint OPER_AY_IX_8(m68ki_cpu_core *cpu); +INLINE uint OPER_AY_IX_16(m68ki_cpu_core *cpu); +INLINE uint OPER_AY_IX_32(m68ki_cpu_core *cpu); + +INLINE uint OPER_AX_AI_8(m68ki_cpu_core *cpu); +INLINE uint OPER_AX_AI_16(m68ki_cpu_core *cpu); +INLINE uint OPER_AX_AI_32(m68ki_cpu_core *cpu); +INLINE uint OPER_AX_PI_8(m68ki_cpu_core *cpu); +INLINE uint OPER_AX_PI_16(m68ki_cpu_core *cpu); +INLINE uint OPER_AX_PI_32(m68ki_cpu_core *cpu); +INLINE uint OPER_AX_PD_8(m68ki_cpu_core *cpu); +INLINE uint OPER_AX_PD_16(m68ki_cpu_core *cpu); +INLINE uint OPER_AX_PD_32(m68ki_cpu_core *cpu); +INLINE uint OPER_AX_DI_8(m68ki_cpu_core *cpu); +INLINE uint OPER_AX_DI_16(m68ki_cpu_core *cpu); +INLINE uint OPER_AX_DI_32(m68ki_cpu_core *cpu); +INLINE uint OPER_AX_IX_8(m68ki_cpu_core *cpu); +INLINE uint OPER_AX_IX_16(m68ki_cpu_core *cpu); +INLINE uint OPER_AX_IX_32(m68ki_cpu_core *cpu); + +INLINE uint OPER_A7_PI_8(m68ki_cpu_core *cpu); +INLINE uint OPER_A7_PD_8(m68ki_cpu_core *cpu); + +INLINE uint OPER_AW_8(m68ki_cpu_core *cpu); +INLINE uint OPER_AW_16(m68ki_cpu_core *cpu); +INLINE uint OPER_AW_32(m68ki_cpu_core *cpu); +INLINE uint OPER_AL_8(m68ki_cpu_core *cpu); +INLINE uint OPER_AL_16(m68ki_cpu_core *cpu); +INLINE uint OPER_AL_32(m68ki_cpu_core *cpu); +INLINE uint OPER_PCDI_8(m68ki_cpu_core *cpu); +INLINE uint OPER_PCDI_16(m68ki_cpu_core *cpu); +INLINE uint OPER_PCDI_32(m68ki_cpu_core *cpu); +INLINE uint OPER_PCIX_8(m68ki_cpu_core *cpu); +INLINE uint OPER_PCIX_16(m68ki_cpu_core *cpu); +INLINE uint OPER_PCIX_32(m68ki_cpu_core *cpu); + +/* Stack operations */ +INLINE void m68ki_push_16(m68ki_cpu_core *cpu, uint value); +INLINE void m68ki_push_32(m68ki_cpu_core *cpu, uint value); +INLINE uint m68ki_pull_16(m68ki_cpu_core *cpu); +INLINE uint m68ki_pull_32(m68ki_cpu_core *cpu); + +/* Program flow operations */ +INLINE void m68ki_jump(m68ki_cpu_core *cpu, uint new_pc); +INLINE void m68ki_jump_vector(m68ki_cpu_core *cpu, uint vector); +INLINE void m68ki_branch_8(m68ki_cpu_core *cpu, uint offset); +INLINE void m68ki_branch_16(m68ki_cpu_core *cpu, uint offset); +INLINE void m68ki_branch_32(m68ki_cpu_core *cpu, uint offset); + +/* Status register operations. */ +INLINE void m68ki_set_s_flag(m68ki_cpu_core *cpu, uint value); /* Only bit 2 of value should be set (i.e. 4 or 0) */ +INLINE void m68ki_set_sm_flag(m68ki_cpu_core *cpu, uint value); /* only bits 1 and 2 of value should be set */ +INLINE void m68ki_set_ccr(m68ki_cpu_core *cpu, uint value); /* set the condition code register */ +INLINE void m68ki_set_sr(m68ki_cpu_core *cpu, uint value); /* set the status register */ +INLINE void m68ki_set_sr_noint(m68ki_cpu_core *cpu, uint value); /* set the status register */ + +/* Exception processing */ +INLINE uint m68ki_init_exception(m68ki_cpu_core *cpu); /* Initial exception processing */ + +INLINE void m68ki_stack_frame_3word(m68ki_cpu_core *cpu, uint pc, uint sr); /* Stack various frame types */ +INLINE void m68ki_stack_frame_buserr(m68ki_cpu_core *cpu, uint sr); + +INLINE void m68ki_stack_frame_0000(m68ki_cpu_core *cpu, uint pc, uint sr, uint vector); +INLINE void m68ki_stack_frame_0001(m68ki_cpu_core *cpu, uint pc, uint sr, uint vector); +INLINE void m68ki_stack_frame_0010(m68ki_cpu_core *cpu, uint sr, uint vector); +INLINE void m68ki_stack_frame_1000(m68ki_cpu_core *cpu, uint pc, uint sr, uint vector); +INLINE void m68ki_stack_frame_1010(m68ki_cpu_core *cpu, uint sr, uint vector, uint pc); +INLINE void m68ki_stack_frame_1011(m68ki_cpu_core *cpu, uint sr, uint vector, uint pc); + +INLINE void m68ki_exception_trap(m68ki_cpu_core *cpu, uint vector); +INLINE void m68ki_exception_trapN(m68ki_cpu_core *cpu, uint vector); +INLINE void m68ki_exception_trace(m68ki_cpu_core *cpu); +INLINE void m68ki_exception_privilege_violation(m68ki_cpu_core *cpu); +INLINE void m68ki_exception_1010(m68ki_cpu_core *cpu); +INLINE void m68ki_exception_1111(m68ki_cpu_core *cpu); +INLINE void m68ki_exception_illegal(m68ki_cpu_core *cpu); +INLINE void m68ki_exception_format_error(m68ki_cpu_core *cpu); +INLINE void m68ki_exception_address_error(m68ki_cpu_core *cpu); +INLINE void m68ki_exception_interrupt(m68ki_cpu_core *cpu, uint int_level); +INLINE void m68ki_check_interrupts(m68ki_cpu_core *cpu); /* ASG: check for interrupts */ + +/* quick disassembly (used for logging) */ +char* m68ki_disassemble_quick(unsigned int pc, unsigned int cpu_type); + + +/* ======================================================================== */ +/* =========================== UTILITY FUNCTIONS ========================== */ +/* ======================================================================== */ + + +/* ---------------------------- Read Immediate ---------------------------- */ + +/* Handles all immediate reads, does address error check, function code setting, + * and prefetching if they are enabled in m68kconf.h + */ +INLINE uint m68ki_read_imm_16(m68ki_cpu_core *cpu) +{ + m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ + m68ki_check_address_error(REG_PC, MODE_READ, FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ +#if M68K_EMULATE_PREFETCH + if(MASK_OUT_BELOW_2(REG_PC) != CPU_PREF_ADDR) + { + CPU_PREF_ADDR = MASK_OUT_BELOW_2(REG_PC); + CPU_PREF_DATA = m68k_read_immediate_32(ADDRESS_68K(CPU_PREF_ADDR)); + } + REG_PC += 2; + return MASK_OUT_ABOVE_16(CPU_PREF_DATA >> ((2-((REG_PC-2)&2))<<3)); +#else + REG_PC += 2; + return m68k_read_immediate_16(ADDRESS_68K(REG_PC-2)); +#endif /* M68K_EMULATE_PREFETCH */ +} +INLINE uint m68ki_read_imm_32(m68ki_cpu_core *cpu) +{ +#if M68K_EMULATE_PREFETCH + uint temp_val; + + m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ + m68ki_check_address_error(REG_PC, MODE_READ, FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ + if(MASK_OUT_BELOW_2(REG_PC) != CPU_PREF_ADDR) + { + CPU_PREF_ADDR = MASK_OUT_BELOW_2(REG_PC); + CPU_PREF_DATA = m68k_read_immediate_32(ADDRESS_68K(CPU_PREF_ADDR)); + } + temp_val = CPU_PREF_DATA; + REG_PC += 2; + if(MASK_OUT_BELOW_2(REG_PC) != CPU_PREF_ADDR) + { + CPU_PREF_ADDR = MASK_OUT_BELOW_2(REG_PC); + CPU_PREF_DATA = m68k_read_immediate_32(ADDRESS_68K(CPU_PREF_ADDR)); + temp_val = MASK_OUT_ABOVE_32((temp_val << 16) | (CPU_PREF_DATA >> 16)); + } + REG_PC += 2; + + return temp_val; +#else + m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ + m68ki_check_address_error(REG_PC, MODE_READ, FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ + REG_PC += 4; + return m68k_read_immediate_32(ADDRESS_68K(REG_PC-4)); +#endif /* M68K_EMULATE_PREFETCH */ +} + + + +/* ------------------------- Top level read/write ------------------------- */ + +/* Handles all memory accesses (except for immediate reads if they are + * configured to use separate functions in m68kconf.h). + * All memory accesses must go through these top level functions. + * These functions will also check for address error and set the function + * code if they are enabled in m68kconf.h. + */ +INLINE uint m68ki_read_8_fc(m68ki_cpu_core *cpu, uint address, uint fc) +{ + m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ + return m68k_read_memory_8(cpu, ADDRESS_68K(address)); +} +INLINE uint m68ki_read_16_fc(m68ki_cpu_core *cpu, uint address, uint fc) +{ + m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ + m68ki_check_address_error(address, MODE_READ, fc); /* auto-disable (see m68kcpu.h) */ + return m68k_read_memory_16(cpu, ADDRESS_68K(address)); +} +INLINE uint m68ki_read_32_fc(m68ki_cpu_core *cpu, uint address, uint fc) +{ + m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ + m68ki_check_address_error(address, MODE_READ, fc); /* auto-disable (see m68kcpu.h) */ + return m68k_read_memory_32(cpu, ADDRESS_68K(address)); +} + +INLINE void m68ki_write_8_fc(m68ki_cpu_core *cpu, uint address, uint fc, uint value) +{ + m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ + m68k_write_memory_8(cpu, ADDRESS_68K(address), value); +} +INLINE void m68ki_write_16_fc(m68ki_cpu_core *cpu, uint address, uint fc, uint value) +{ + m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ + m68ki_check_address_error(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */ + m68k_write_memory_16(cpu, ADDRESS_68K(address), value); +} +INLINE void m68ki_write_32_fc(m68ki_cpu_core *cpu, uint address, uint fc, uint value) +{ + m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ + m68ki_check_address_error(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */ + m68k_write_memory_32(cpu, ADDRESS_68K(address), value); +} + +#if M68K_SIMULATE_PD_WRITES +INLINE void m68ki_write_32_pd_fc(m68ki_cpu_core *cpu, uint address, uint fc, uint value) +{ + m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ + m68ki_check_address_error(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */ + m68k_write_memory_32_pd(ADDRESS_68K(address), value); +} +#endif + + +/* --------------------- Effective Address Calculation -------------------- */ + +/* The program counter relative addressing modes cause operands to be + * retrieved from program space, not data space. + */ +INLINE uint m68ki_get_ea_pcdi(m68ki_cpu_core *cpu) +{ + uint old_pc = REG_PC; + m68ki_use_program_space(); /* auto-disable */ + return old_pc + MAKE_INT_16(m68ki_read_imm_16(cpu)); +} + + +INLINE uint m68ki_get_ea_pcix(m68ki_cpu_core *cpu) +{ + m68ki_use_program_space(); /* auto-disable */ + return m68ki_get_ea_ix(cpu, REG_PC); +} + +/* Indexed addressing modes are encoded as follows: + * + * Base instruction format: + * F E D C B A 9 8 7 6 | 5 4 3 | 2 1 0 + * x x x x x x x x x x | 1 1 0 | BASE REGISTER (An) + * + * Base instruction format for destination EA in move instructions: + * F E D C | B A 9 | 8 7 6 | 5 4 3 2 1 0 + * x x x x | BASE REG | 1 1 0 | X X X X X X (An) + * + * Brief extension format: + * F | E D C | B | A 9 | 8 | 7 6 5 4 3 2 1 0 + * D/A | REGISTER | W/L | SCALE | 0 | DISPLACEMENT + * + * Full extension format: + * F E D C B A 9 8 7 6 5 4 3 2 1 0 + * D/A | REGISTER | W/L | SCALE | 1 | BS | IS | BD SIZE | 0 | I/IS + * BASE DISPLACEMENT (0, 16, 32 bit) (bd) + * OUTER DISPLACEMENT (0, 16, 32 bit) (od) + * + * D/A: 0 = Dn, 1 = An (Xn) + * W/L: 0 = W (sign extend), 1 = L (.SIZE) + * SCALE: 00=1, 01=2, 10=4, 11=8 (*SCALE) + * BS: 0=add base reg, 1=suppress base reg (An suppressed) + * IS: 0=add index, 1=suppress index (Xn suppressed) + * BD SIZE: 00=reserved, 01=NULL, 10=Word, 11=Long (size of bd) + * + * IS I/IS Operation + * 0 000 No Memory Indirect + * 0 001 indir prex with null outer + * 0 010 indir prex with word outer + * 0 011 indir prex with long outer + * 0 100 reserved + * 0 101 indir postx with null outer + * 0 110 indir postx with word outer + * 0 111 indir postx with long outer + * 1 000 no memory indirect + * 1 001 mem indir with null outer + * 1 010 mem indir with word outer + * 1 011 mem indir with long outer + * 1 100-111 reserved + */ +INLINE uint m68ki_get_ea_ix(m68ki_cpu_core *cpu, uint An) +{ + /* An = base register */ + uint extension = m68ki_read_imm_16(cpu); + uint Xn = 0; /* Index register */ + uint bd = 0; /* Base Displacement */ + uint od = 0; /* Outer Displacement */ + + if(CPU_TYPE_IS_010_LESS(CPU_TYPE)) + { + /* Calculate index */ + Xn = REG_DA[extension>>12]; /* Xn */ + if(!BIT_B(extension)) /* W/L */ + Xn = MAKE_INT_16(Xn); + + /* Add base register and displacement and return */ + return An + Xn + MAKE_INT_8(extension); + } + + /* Brief extension format */ + if(!BIT_8(extension)) + { + /* Calculate index */ + Xn = REG_DA[extension>>12]; /* Xn */ + if(!BIT_B(extension)) /* W/L */ + Xn = MAKE_INT_16(Xn); + /* Add scale if proper CPU type */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + Xn <<= (extension>>9) & 3; /* SCALE */ + + /* Add base register and displacement and return */ + return An + Xn + MAKE_INT_8(extension); + } + + /* Full extension format */ + + USE_CYCLES(m68ki_ea_idx_cycle_table[extension&0x3f]); + + /* Check if base register is present */ + if(BIT_7(extension)) /* BS */ + An = 0; /* An */ + + /* Check if index is present */ + if(!BIT_6(extension)) /* IS */ + { + Xn = REG_DA[extension>>12]; /* Xn */ + if(!BIT_B(extension)) /* W/L */ + Xn = MAKE_INT_16(Xn); + Xn <<= (extension>>9) & 3; /* SCALE */ + } + + /* Check if base displacement is present */ + if(BIT_5(extension)) /* BD SIZE */ + bd = BIT_4(extension) ? m68ki_read_imm_32(cpu) : MAKE_INT_16(m68ki_read_imm_16(cpu)); + + /* If no indirect action, we are done */ + if(!(extension&7)) /* No Memory Indirect */ + return An + bd + Xn; + + /* Check if outer displacement is present */ + if(BIT_1(extension)) /* I/IS: od */ + od = BIT_0(extension) ? m68ki_read_imm_32(cpu) : MAKE_INT_16(m68ki_read_imm_16(cpu)); + + /* Postindex */ + if(BIT_2(extension)) /* I/IS: 0 = preindex, 1 = postindex */ + return m68ki_read_32(An + bd) + Xn + od; + + /* Preindex */ + return m68ki_read_32(An + bd + Xn) + od; +} + + +/* Fetch operands */ +INLINE uint OPER_AY_AI_8(m68ki_cpu_core *cpu) {uint ea = EA_AY_AI_8(); return m68ki_read_8(ea); } +INLINE uint OPER_AY_AI_16(m68ki_cpu_core *cpu) {uint ea = EA_AY_AI_16(); return m68ki_read_16(ea);} +INLINE uint OPER_AY_AI_32(m68ki_cpu_core *cpu) {uint ea = EA_AY_AI_32(); return m68ki_read_32(ea);} +INLINE uint OPER_AY_PI_8(m68ki_cpu_core *cpu) {uint ea = EA_AY_PI_8(); return m68ki_read_8(ea); } +INLINE uint OPER_AY_PI_16(m68ki_cpu_core *cpu) {uint ea = EA_AY_PI_16(); return m68ki_read_16(ea);} +INLINE uint OPER_AY_PI_32(m68ki_cpu_core *cpu) {uint ea = EA_AY_PI_32(); return m68ki_read_32(ea);} +INLINE uint OPER_AY_PD_8(m68ki_cpu_core *cpu) {uint ea = EA_AY_PD_8(); return m68ki_read_8(ea); } +INLINE uint OPER_AY_PD_16(m68ki_cpu_core *cpu) {uint ea = EA_AY_PD_16(); return m68ki_read_16(ea);} +INLINE uint OPER_AY_PD_32(m68ki_cpu_core *cpu) {uint ea = EA_AY_PD_32(); return m68ki_read_32(ea);} +INLINE uint OPER_AY_DI_8(m68ki_cpu_core *cpu) {uint ea = EA_AY_DI_8(); return m68ki_read_8(ea); } +INLINE uint OPER_AY_DI_16(m68ki_cpu_core *cpu) {uint ea = EA_AY_DI_16(); return m68ki_read_16(ea);} +INLINE uint OPER_AY_DI_32(m68ki_cpu_core *cpu) {uint ea = EA_AY_DI_32(); return m68ki_read_32(ea);} +INLINE uint OPER_AY_IX_8(m68ki_cpu_core *cpu) {uint ea = EA_AY_IX_8(); return m68ki_read_8(ea); } +INLINE uint OPER_AY_IX_16(m68ki_cpu_core *cpu) {uint ea = EA_AY_IX_16(); return m68ki_read_16(ea);} +INLINE uint OPER_AY_IX_32(m68ki_cpu_core *cpu) {uint ea = EA_AY_IX_32(); return m68ki_read_32(ea);} + +INLINE uint OPER_AX_AI_8(m68ki_cpu_core *cpu) {uint ea = EA_AX_AI_8(); return m68ki_read_8(ea); } +INLINE uint OPER_AX_AI_16(m68ki_cpu_core *cpu) {uint ea = EA_AX_AI_16(); return m68ki_read_16(ea);} +INLINE uint OPER_AX_AI_32(m68ki_cpu_core *cpu) {uint ea = EA_AX_AI_32(); return m68ki_read_32(ea);} +INLINE uint OPER_AX_PI_8(m68ki_cpu_core *cpu) {uint ea = EA_AX_PI_8(); return m68ki_read_8(ea); } +INLINE uint OPER_AX_PI_16(m68ki_cpu_core *cpu) {uint ea = EA_AX_PI_16(); return m68ki_read_16(ea);} +INLINE uint OPER_AX_PI_32(m68ki_cpu_core *cpu) {uint ea = EA_AX_PI_32(); return m68ki_read_32(ea);} +INLINE uint OPER_AX_PD_8(m68ki_cpu_core *cpu) {uint ea = EA_AX_PD_8(); return m68ki_read_8(ea); } +INLINE uint OPER_AX_PD_16(m68ki_cpu_core *cpu) {uint ea = EA_AX_PD_16(); return m68ki_read_16(ea);} +INLINE uint OPER_AX_PD_32(m68ki_cpu_core *cpu) {uint ea = EA_AX_PD_32(); return m68ki_read_32(ea);} +INLINE uint OPER_AX_DI_8(m68ki_cpu_core *cpu) {uint ea = EA_AX_DI_8(); return m68ki_read_8(ea); } +INLINE uint OPER_AX_DI_16(m68ki_cpu_core *cpu) {uint ea = EA_AX_DI_16(); return m68ki_read_16(ea);} +INLINE uint OPER_AX_DI_32(m68ki_cpu_core *cpu) {uint ea = EA_AX_DI_32(); return m68ki_read_32(ea);} +INLINE uint OPER_AX_IX_8(m68ki_cpu_core *cpu) {uint ea = EA_AX_IX_8(); return m68ki_read_8(ea); } +INLINE uint OPER_AX_IX_16(m68ki_cpu_core *cpu) {uint ea = EA_AX_IX_16(); return m68ki_read_16(ea);} +INLINE uint OPER_AX_IX_32(m68ki_cpu_core *cpu) {uint ea = EA_AX_IX_32(); return m68ki_read_32(ea);} + +INLINE uint OPER_A7_PI_8(m68ki_cpu_core *cpu) {uint ea = EA_A7_PI_8(); return m68ki_read_8(ea); } +INLINE uint OPER_A7_PD_8(m68ki_cpu_core *cpu) {uint ea = EA_A7_PD_8(); return m68ki_read_8(ea); } + +INLINE uint OPER_AW_8(m68ki_cpu_core *cpu) {uint ea = EA_AW_8(); return m68ki_read_8(ea); } +INLINE uint OPER_AW_16(m68ki_cpu_core *cpu) {uint ea = EA_AW_16(); return m68ki_read_16(ea);} +INLINE uint OPER_AW_32(m68ki_cpu_core *cpu) {uint ea = EA_AW_32(); return m68ki_read_32(ea);} +INLINE uint OPER_AL_8(m68ki_cpu_core *cpu) {uint ea = EA_AL_8(); return m68ki_read_8(ea); } +INLINE uint OPER_AL_16(m68ki_cpu_core *cpu) {uint ea = EA_AL_16(); return m68ki_read_16(ea);} +INLINE uint OPER_AL_32(m68ki_cpu_core *cpu) {uint ea = EA_AL_32(); return m68ki_read_32(ea);} +INLINE uint OPER_PCDI_8(m68ki_cpu_core *cpu) {uint ea = EA_PCDI_8(); return m68ki_read_pcrel_8(ea); } +INLINE uint OPER_PCDI_16(m68ki_cpu_core *cpu) {uint ea = EA_PCDI_16(); return m68ki_read_pcrel_16(ea);} +INLINE uint OPER_PCDI_32(m68ki_cpu_core *cpu) {uint ea = EA_PCDI_32(); return m68ki_read_pcrel_32(ea);} +INLINE uint OPER_PCIX_8(m68ki_cpu_core *cpu) {uint ea = EA_PCIX_8(); return m68ki_read_pcrel_8(ea); } +INLINE uint OPER_PCIX_16(m68ki_cpu_core *cpu) {uint ea = EA_PCIX_16(); return m68ki_read_pcrel_16(ea);} +INLINE uint OPER_PCIX_32(m68ki_cpu_core *cpu) {uint ea = EA_PCIX_32(); return m68ki_read_pcrel_32(ea);} + + + +/* ---------------------------- Stack Functions --------------------------- */ + +/* Push/pull data from the stack */ +INLINE void m68ki_push_16(m68ki_cpu_core *cpu, uint value) +{ + REG_SP = MASK_OUT_ABOVE_32(REG_SP - 2); + m68ki_write_16(REG_SP, value); +} + +INLINE void m68ki_push_32(m68ki_cpu_core *cpu, uint value) +{ + REG_SP = MASK_OUT_ABOVE_32(REG_SP - 4); + m68ki_write_32(REG_SP, value); +} + +INLINE uint m68ki_pull_16(m68ki_cpu_core *cpu) +{ + REG_SP = MASK_OUT_ABOVE_32(REG_SP + 2); + return m68ki_read_16(REG_SP-2); +} + +INLINE uint m68ki_pull_32(m68ki_cpu_core *cpu) +{ + REG_SP = MASK_OUT_ABOVE_32(REG_SP + 4); + return m68ki_read_32(REG_SP-4); +} + + +/* Increment/decrement the stack as if doing a push/pull but + * don't do any memory access. + */ +INLINE void m68ki_fake_push_16(m68ki_cpu_core *cpu) +{ + REG_SP = MASK_OUT_ABOVE_32(REG_SP - 2); +} + +INLINE void m68ki_fake_push_32(m68ki_cpu_core *cpu) +{ + REG_SP = MASK_OUT_ABOVE_32(REG_SP - 4); +} + +INLINE void m68ki_fake_pull_16(m68ki_cpu_core *cpu) +{ + REG_SP = MASK_OUT_ABOVE_32(REG_SP + 2); +} + +INLINE void m68ki_fake_pull_32(m68ki_cpu_core *cpu) +{ + REG_SP = MASK_OUT_ABOVE_32(REG_SP + 4); +} + + +/* ----------------------------- Program Flow ----------------------------- */ + +/* Jump to a new program location or vector. + * These functions will also call the pc_changed callback if it was enabled + * in m68kconf.h. + */ +INLINE void m68ki_jump(m68ki_cpu_core *cpu, uint new_pc) +{ + REG_PC = new_pc; + m68ki_pc_changed(REG_PC); +} + +INLINE void m68ki_jump_vector(m68ki_cpu_core *cpu, uint vector) +{ + REG_PC = (vector<<2) + REG_VBR; + REG_PC = m68ki_read_data_32(REG_PC); + m68ki_pc_changed(REG_PC); +} + + +/* Branch to a new memory location. + * The 32-bit branch will call pc_changed if it was enabled in m68kconf.h. + * So far I've found no problems with not calling pc_changed for 8 or 16 + * bit branches. + */ +INLINE void m68ki_branch_8(m68ki_cpu_core *cpu, uint offset) +{ + REG_PC += MAKE_INT_8(offset); +} + +INLINE void m68ki_branch_16(m68ki_cpu_core *cpu, uint offset) +{ + REG_PC += MAKE_INT_16(offset); +} + +INLINE void m68ki_branch_32(m68ki_cpu_core *cpu, uint offset) +{ + REG_PC += offset; + m68ki_pc_changed(REG_PC); +} + + + +/* ---------------------------- Status Register --------------------------- */ + +/* Set the S flag and change the active stack pointer. + * Note that value MUST be 4 or 0. + */ +INLINE void m68ki_set_s_flag(m68ki_cpu_core *cpu, uint value) +{ + /* Backup the old stack pointer */ + REG_SP_BASE[FLAG_S | ((FLAG_S>>1) & FLAG_M)] = REG_SP; + /* Set the S flag */ + FLAG_S = value; + /* Set the new stack pointer */ + REG_SP = REG_SP_BASE[FLAG_S | ((FLAG_S>>1) & FLAG_M)]; +} + +/* Set the S and M flags and change the active stack pointer. + * Note that value MUST be 0, 2, 4, or 6 (bit2 = S, bit1 = M). + */ +INLINE void m68ki_set_sm_flag(m68ki_cpu_core *cpu, uint value) +{ + /* Backup the old stack pointer */ + REG_SP_BASE[FLAG_S | ((FLAG_S>>1) & FLAG_M)] = REG_SP; + /* Set the S and M flags */ + FLAG_S = value & SFLAG_SET; + FLAG_M = value & MFLAG_SET; + /* Set the new stack pointer */ + REG_SP = REG_SP_BASE[FLAG_S | ((FLAG_S>>1) & FLAG_M)]; +} + +/* Set the S and M flags. Don't touch the stack pointer. */ +INLINE void m68ki_set_sm_flag_nosp(m68ki_cpu_core *cpu, uint value) +{ + /* Set the S and M flags */ + FLAG_S = value & SFLAG_SET; + FLAG_M = value & MFLAG_SET; +} + + +/* Set the condition code register */ +INLINE void m68ki_set_ccr(m68ki_cpu_core *cpu, uint value) +{ + FLAG_X = BIT_4(value) << 4; + FLAG_N = BIT_3(value) << 4; + FLAG_Z = !BIT_2(value); + FLAG_V = BIT_1(value) << 6; + FLAG_C = BIT_0(value) << 8; +} + +/* Set the status register but don't check for interrupts */ +INLINE void m68ki_set_sr_noint(m68ki_cpu_core *cpu, uint value) +{ + /* Mask out the "unimplemented" bits */ + value &= CPU_SR_MASK; + + /* Now set the status register */ + FLAG_T1 = BIT_F(value); + FLAG_T0 = BIT_E(value); + FLAG_INT_MASK = value & 0x0700; + m68ki_set_ccr(cpu, value); + m68ki_set_sm_flag(cpu, (value >> 11) & 6); +} + +/* Set the status register but don't check for interrupts nor + * change the stack pointer + */ +INLINE void m68ki_set_sr_noint_nosp(m68ki_cpu_core *cpu, uint value) +{ + /* Mask out the "unimplemented" bits */ + value &= CPU_SR_MASK; + + /* Now set the status register */ + FLAG_T1 = BIT_F(value); + FLAG_T0 = BIT_E(value); + FLAG_INT_MASK = value & 0x0700; + m68ki_set_ccr(cpu, value); + m68ki_set_sm_flag_nosp(cpu, (value >> 11) & 6); +} + +/* Set the status register and check for interrupts */ +INLINE void m68ki_set_sr(m68ki_cpu_core *cpu, uint value) +{ + m68ki_set_sr_noint(cpu, value); + m68ki_check_interrupts(cpu); +} + + +/* ------------------------- Exception Processing ------------------------- */ + +/* Initiate exception processing */ +INLINE uint m68ki_init_exception(m68ki_cpu_core *cpu) +{ + /* Save the old status register */ + uint sr = m68ki_get_sr(); + + /* Turn off trace flag, clear pending traces */ + FLAG_T1 = FLAG_T0 = 0; + m68ki_clear_trace(); + /* Enter supervisor mode */ + m68ki_set_s_flag(cpu, SFLAG_SET); + + return sr; +} + +/* 3 word stack frame (68000 only) */ +INLINE void m68ki_stack_frame_3word(m68ki_cpu_core *cpu, uint pc, uint sr) +{ + m68ki_push_32(cpu, pc); + m68ki_push_16(cpu, sr); +} + +/* Format 0 stack frame. + * This is the standard stack frame for 68010+. + */ +INLINE void m68ki_stack_frame_0000(m68ki_cpu_core *cpu, uint pc, uint sr, uint vector) +{ + /* Stack a 3-word frame if we are 68000 */ + if(CPU_TYPE == CPU_TYPE_000) + { + m68ki_stack_frame_3word(cpu, pc, sr); + return; + } + m68ki_push_16(cpu, vector<<2); + m68ki_push_32(cpu, pc); + m68ki_push_16(cpu, sr); +} + +/* Format 1 stack frame (68020). + * For 68020, this is the 4 word throwaway frame. + */ +INLINE void m68ki_stack_frame_0001(m68ki_cpu_core *cpu, uint pc, uint sr, uint vector) +{ + m68ki_push_16(cpu, 0x1000 | (vector<<2)); + m68ki_push_32(cpu, pc); + m68ki_push_16(cpu, sr); +} + +/* Format 2 stack frame. + * This is used only by 68020 for trap exceptions. + */ +INLINE void m68ki_stack_frame_0010(m68ki_cpu_core *cpu, uint sr, uint vector) +{ + m68ki_push_32(cpu, REG_PPC); + m68ki_push_16(cpu, 0x2000 | (vector<<2)); + m68ki_push_32(cpu, REG_PC); + m68ki_push_16(cpu, sr); +} + + +/* Bus error stack frame (68000 only). + */ +INLINE void m68ki_stack_frame_buserr(m68ki_cpu_core *cpu, uint sr) +{ + m68ki_push_32(cpu,REG_PC); + m68ki_push_16(cpu,sr); + m68ki_push_16(cpu,REG_IR); + m68ki_push_32(cpu,cpu->m68ki_aerr_address); /* access address */ + /* 0 0 0 0 0 0 0 0 0 0 0 R/W I/N FC + * R/W 0 = write, 1 = read + * I/N 0 = instruction, 1 = not + * FC 3-bit function code + */ + m68ki_push_16(cpu,cpu->m68ki_aerr_write_mode | CPU_INSTR_MODE | cpu->m68ki_aerr_fc); +} + +/* Format 8 stack frame (68010). + * 68010 only. This is the 29 word bus/address error frame. + */ +void m68ki_stack_frame_1000(m68ki_cpu_core *cpu, uint pc, uint sr, uint vector) +{ + /* VERSION + * NUMBER + * INTERNAL INFORMATION, 16 WORDS + */ + m68ki_fake_push_32(cpu); + m68ki_fake_push_32(cpu); + m68ki_fake_push_32(cpu); + m68ki_fake_push_32(cpu); + m68ki_fake_push_32(cpu); + m68ki_fake_push_32(cpu); + m68ki_fake_push_32(cpu); + m68ki_fake_push_32(cpu); + + /* INSTRUCTION INPUT BUFFER */ + m68ki_push_16(cpu,0); + + /* UNUSED, RESERVED (not written) */ + m68ki_fake_push_16(cpu); + + /* DATA INPUT BUFFER */ + m68ki_push_16(cpu,0); + + /* UNUSED, RESERVED (not written) */ + m68ki_fake_push_16(cpu); + + /* DATA OUTPUT BUFFER */ + m68ki_push_16(cpu,0); + + /* UNUSED, RESERVED (not written) */ + m68ki_fake_push_16(cpu); + + /* FAULT ADDRESS */ + m68ki_push_32(cpu,0); + + /* SPECIAL STATUS WORD */ + m68ki_push_16(cpu,0); + + /* 1000, VECTOR OFFSET */ + m68ki_push_16(cpu,0x8000 | (vector<<2)); + + /* PROGRAM COUNTER */ + m68ki_push_32(cpu,pc); + + /* STATUS REGISTER */ + m68ki_push_16(cpu,sr); +} + +/* Format A stack frame (short bus fault). + * This is used only by 68020 for bus fault and address error + * if the error happens at an instruction boundary. + * PC stacked is address of next instruction. + */ +void m68ki_stack_frame_1010(m68ki_cpu_core *cpu, uint sr, uint vector, uint pc) +{ + /* INTERNAL REGISTER */ + m68ki_push_16(cpu,0); + + /* INTERNAL REGISTER */ + m68ki_push_16(cpu,0); + + /* DATA OUTPUT BUFFER (2 words) */ + m68ki_push_32(cpu,0); + + /* INTERNAL REGISTER */ + m68ki_push_16(cpu,0); + + /* INTERNAL REGISTER */ + m68ki_push_16(cpu,0); + + /* DATA CYCLE FAULT ADDRESS (2 words) */ + m68ki_push_32(cpu,0); + + /* INSTRUCTION PIPE STAGE B */ + m68ki_push_16(cpu,0); + + /* INSTRUCTION PIPE STAGE C */ + m68ki_push_16(cpu,0); + + /* SPECIAL STATUS REGISTER */ + m68ki_push_16(cpu,0); + + /* INTERNAL REGISTER */ + m68ki_push_16(cpu,0); + + /* 1010, VECTOR OFFSET */ + m68ki_push_16(cpu,0xa000 | (vector<<2)); + + /* PROGRAM COUNTER */ + m68ki_push_32(cpu,pc); + + /* STATUS REGISTER */ + m68ki_push_16(cpu,sr); +} + +/* Format B stack frame (long bus fault). + * This is used only by 68020 for bus fault and address error + * if the error happens during instruction execution. + * PC stacked is address of instruction in progress. + */ +void m68ki_stack_frame_1011(m68ki_cpu_core *cpu, uint sr, uint vector, uint pc) +{ + /* INTERNAL REGISTERS (18 words) */ + m68ki_push_32(cpu,0); + m68ki_push_32(cpu,0); + m68ki_push_32(cpu,0); + m68ki_push_32(cpu,0); + m68ki_push_32(cpu,0); + m68ki_push_32(cpu,0); + m68ki_push_32(cpu,0); + m68ki_push_32(cpu,0); + m68ki_push_32(cpu,0); + + /* VERSION# (4 bits), INTERNAL INFORMATION */ + m68ki_push_16(cpu,0); + + /* INTERNAL REGISTERS (3 words) */ + m68ki_push_32(cpu,0); + m68ki_push_16(cpu,0); + + /* DATA INTPUT BUFFER (2 words) */ + m68ki_push_32(cpu,0); + + /* INTERNAL REGISTERS (2 words) */ + m68ki_push_32(cpu,0); + + /* STAGE B ADDRESS (2 words) */ + m68ki_push_32(cpu,0); + + /* INTERNAL REGISTER (4 words) */ + m68ki_push_32(cpu,0); + m68ki_push_32(cpu,0); + + /* DATA OUTPUT BUFFER (2 words) */ + m68ki_push_32(cpu,0); + + /* INTERNAL REGISTER */ + m68ki_push_16(cpu,0); + + /* INTERNAL REGISTER */ + m68ki_push_16(cpu,0); + + /* DATA CYCLE FAULT ADDRESS (2 words) */ + m68ki_push_32(cpu,0); + + /* INSTRUCTION PIPE STAGE B */ + m68ki_push_16(cpu,0); + + /* INSTRUCTION PIPE STAGE C */ + m68ki_push_16(cpu,0); + + /* SPECIAL STATUS REGISTER */ + m68ki_push_16(cpu,0); + + /* INTERNAL REGISTER */ + m68ki_push_16(cpu,0); + + /* 1011, VECTOR OFFSET */ + m68ki_push_16(cpu,0xb000 | (vector<<2)); + + /* PROGRAM COUNTER */ + m68ki_push_32(cpu,pc); + + /* STATUS REGISTER */ + m68ki_push_16(cpu,sr); +} + + +/* Used for Group 2 exceptions. + * These stack a type 2 frame on the 020. + */ +INLINE void m68ki_exception_trap(m68ki_cpu_core *cpu, uint vector) +{ + uint sr = m68ki_init_exception(cpu); + + if(CPU_TYPE_IS_010_LESS(CPU_TYPE)) + m68ki_stack_frame_0000(cpu, REG_PC, sr, vector); + else + m68ki_stack_frame_0010(cpu, sr, vector); + + m68ki_jump_vector(cpu, vector); + + /* Use up some clock cycles */ + USE_CYCLES(CYC_EXCEPTION[vector]); +} + +/* Trap#n stacks a 0 frame but behaves like group2 otherwise */ +INLINE void m68ki_exception_trapN(m68ki_cpu_core *cpu, uint vector) +{ + uint sr = m68ki_init_exception(cpu); + m68ki_stack_frame_0000(cpu, REG_PC, sr, vector); + m68ki_jump_vector(cpu, vector); + + /* Use up some clock cycles */ + USE_CYCLES(CYC_EXCEPTION[vector]); +} + +/* Exception for trace mode */ +INLINE void m68ki_exception_trace(m68ki_cpu_core *cpu) +{ + uint sr = m68ki_init_exception(cpu); + + if(CPU_TYPE_IS_010_LESS(CPU_TYPE)) + { + #if M68K_EMULATE_ADDRESS_ERROR == OPT_ON + if(CPU_TYPE_IS_000(CPU_TYPE)) + { + CPU_INSTR_MODE = INSTRUCTION_NO; + } + #endif /* M68K_EMULATE_ADDRESS_ERROR */ + m68ki_stack_frame_0000(cpu, REG_PC, sr, EXCEPTION_TRACE); + } + else + m68ki_stack_frame_0010(cpu, sr, EXCEPTION_TRACE); + + m68ki_jump_vector(cpu, EXCEPTION_TRACE); + + /* Trace nullifies a STOP instruction */ + CPU_STOPPED &= ~STOP_LEVEL_STOP; + + /* Use up some clock cycles */ + USE_CYCLES(CYC_EXCEPTION[EXCEPTION_TRACE]); +} + +/* Exception for privilege violation */ +INLINE void m68ki_exception_privilege_violation(m68ki_cpu_core *cpu) +{ + uint sr = m68ki_init_exception(cpu); + + #if M68K_EMULATE_ADDRESS_ERROR == OPT_ON + if(CPU_TYPE_IS_000(CPU_TYPE)) + { + CPU_INSTR_MODE = INSTRUCTION_NO; + } + #endif /* M68K_EMULATE_ADDRESS_ERROR */ + + m68ki_stack_frame_0000(cpu, REG_PPC, sr, EXCEPTION_PRIVILEGE_VIOLATION); + m68ki_jump_vector(cpu, EXCEPTION_PRIVILEGE_VIOLATION); + + /* Use up some clock cycles and undo the instruction's cycles */ + USE_CYCLES(CYC_EXCEPTION[EXCEPTION_PRIVILEGE_VIOLATION] - CYC_INSTRUCTION[REG_IR]); +} + +/* Exception for A-Line instructions */ +INLINE void m68ki_exception_1010(m68ki_cpu_core *cpu) +{ + uint sr; +#if M68K_LOG_1010_1111 == OPT_ON + M68K_DO_LOG_EMU((M68K_LOG_FILEHANDLE "%s at %08x: called 1010 instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PPC), REG_IR, + m68ki_disassemble_quick(ADDRESS_68K(REG_PPC)))); +#endif + + sr = m68ki_init_exception(cpu); + m68ki_stack_frame_0000(cpu, REG_PPC, sr, EXCEPTION_1010); + m68ki_jump_vector(cpu, EXCEPTION_1010); + + /* Use up some clock cycles and undo the instruction's cycles */ + USE_CYCLES(CYC_EXCEPTION[EXCEPTION_1010] - CYC_INSTRUCTION[REG_IR]); +} + +/* Exception for F-Line instructions */ +INLINE void m68ki_exception_1111(m68ki_cpu_core *cpu) +{ + uint sr; + +#if M68K_LOG_1010_1111 == OPT_ON + M68K_DO_LOG_EMU((M68K_LOG_FILEHANDLE "%s at %08x: called 1111 instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PPC), REG_IR, + m68ki_disassemble_quick(ADDRESS_68K(REG_PPC)))); +#endif + + sr = m68ki_init_exception(cpu); + m68ki_stack_frame_0000(cpu, REG_PPC, sr, EXCEPTION_1111); + m68ki_jump_vector(cpu, EXCEPTION_1111); + + /* Use up some clock cycles and undo the instruction's cycles */ + USE_CYCLES(CYC_EXCEPTION[EXCEPTION_1111] - CYC_INSTRUCTION[REG_IR]); +} + +/* Exception for illegal instructions */ +INLINE void m68ki_exception_illegal(m68ki_cpu_core *cpu) +{ + uint sr; + + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: illegal instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PPC), REG_IR, + m68ki_disassemble_quick(ADDRESS_68K(REG_PPC)))); + + sr = m68ki_init_exception(cpu); + + #if M68K_EMULATE_ADDRESS_ERROR == OPT_ON + if(CPU_TYPE_IS_000(CPU_TYPE)) + { + CPU_INSTR_MODE = INSTRUCTION_NO; + } + #endif /* M68K_EMULATE_ADDRESS_ERROR */ + + m68ki_stack_frame_0000(cpu, REG_PPC, sr, EXCEPTION_ILLEGAL_INSTRUCTION); + m68ki_jump_vector(cpu, EXCEPTION_ILLEGAL_INSTRUCTION); + + /* Use up some clock cycles and undo the instruction's cycles */ + USE_CYCLES(CYC_EXCEPTION[EXCEPTION_ILLEGAL_INSTRUCTION] - CYC_INSTRUCTION[REG_IR]); +} + +/* Exception for format errror in RTE */ +INLINE void m68ki_exception_format_error(m68ki_cpu_core *cpu) +{ + uint sr = m68ki_init_exception(cpu); + m68ki_stack_frame_0000(cpu, REG_PC, sr, EXCEPTION_FORMAT_ERROR); + m68ki_jump_vector(cpu, EXCEPTION_FORMAT_ERROR); + + /* Use up some clock cycles and undo the instruction's cycles */ + USE_CYCLES(CYC_EXCEPTION[EXCEPTION_FORMAT_ERROR] - CYC_INSTRUCTION[REG_IR]); +} + +/* Exception for address error */ +INLINE void m68ki_exception_address_error(m68ki_cpu_core *cpu) +{ + uint sr = m68ki_init_exception(cpu); + + /* If we were processing a bus error, address error, or reset, + * this is a catastrophic failure. + * Halt the CPU + */ + if(CPU_RUN_MODE == RUN_MODE_BERR_AERR_RESET) + { + m68k_read_memory_8(cpu, 0x00ffff01); + CPU_STOPPED = STOP_LEVEL_HALT; + return; + } + CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET; + + /* Note: This is implemented for 68000 only! */ + m68ki_stack_frame_buserr(cpu, sr); + + m68ki_jump_vector(cpu, EXCEPTION_ADDRESS_ERROR); + + /* Use up some clock cycles and undo the instruction's cycles */ + USE_CYCLES(CYC_EXCEPTION[EXCEPTION_ADDRESS_ERROR] - CYC_INSTRUCTION[REG_IR]); +} + + +/* Service an interrupt request and start exception processing */ +void m68ki_exception_interrupt(m68ki_cpu_core *cpu, uint int_level) +{ + uint vector; + uint sr; + uint new_pc; + + #if M68K_EMULATE_ADDRESS_ERROR == OPT_ON + if(CPU_TYPE_IS_000(CPU_TYPE)) + { + CPU_INSTR_MODE = INSTRUCTION_NO; + } + #endif /* M68K_EMULATE_ADDRESS_ERROR */ + + /* Turn off the stopped state */ + CPU_STOPPED &= ~STOP_LEVEL_STOP; + + /* If we are halted, don't do anything */ + if(CPU_STOPPED) + return; + + /* Acknowledge the interrupt */ + vector = m68ki_int_ack(cpu, int_level); + + /* Get the interrupt vector */ + if(vector == M68K_INT_ACK_AUTOVECTOR) + /* Use the autovectors. This is the most commonly used implementation */ + vector = EXCEPTION_INTERRUPT_AUTOVECTOR+int_level; + else if(vector == M68K_INT_ACK_SPURIOUS) + /* Called if no devices respond to the interrupt acknowledge */ + vector = EXCEPTION_SPURIOUS_INTERRUPT; + else if(vector > 255) + { + M68K_DO_LOG_EMU((M68K_LOG_FILEHANDLE "%s at %08x: Interrupt acknowledge returned invalid vector $%x\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC), vector)); + return; + } + + /* Start exception processing */ + sr = m68ki_init_exception(cpu); + + /* Set the interrupt mask to the level of the one being serviced */ + FLAG_INT_MASK = int_level<<8; + + /* Get the new PC */ + new_pc = m68ki_read_data_32((vector<<2) + REG_VBR); + + /* If vector is uninitialized, call the uninitialized interrupt vector */ + if(new_pc == 0) + new_pc = m68ki_read_data_32((EXCEPTION_UNINITIALIZED_INTERRUPT<<2) + REG_VBR); + + /* Generate a stack frame */ + m68ki_stack_frame_0000(cpu, REG_PC, sr, vector); + if(FLAG_M && CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Create throwaway frame */ + m68ki_set_sm_flag(cpu, FLAG_S); /* clear M */ + sr |= 0x2000; /* Same as SR in master stack frame except S is forced high */ + m68ki_stack_frame_0001(cpu, REG_PC, sr, vector); + } + + m68ki_jump(cpu, new_pc); + + /* Defer cycle counting until later */ + CPU_INT_CYCLES += CYC_EXCEPTION[vector]; + +#if !M68K_EMULATE_INT_ACK + /* Automatically clear IRQ if we are not using an acknowledge scheme */ + CPU_INT_LEVEL = 0; +#endif /* M68K_EMULATE_INT_ACK */ +} + + +/* ASG: Check for interrupts */ +INLINE void m68ki_check_interrupts(m68ki_cpu_core *cpu) +{ + if(CPU_INT_LEVEL > FLAG_INT_MASK) + m68ki_exception_interrupt(cpu, CPU_INT_LEVEL>>8); +} + + + +/* ======================================================================== */ +/* ============================== END OF FILE ============================= */ +/* ======================================================================== */ + +#endif /* M68KCPU__HEADER */ diff --git a/plugins/ao/eng_ssf/m68kmake.c b/plugins/ao/eng_ssf/m68kmake.c new file mode 100644 index 00000000..00e244b9 --- /dev/null +++ b/plugins/ao/eng_ssf/m68kmake.c @@ -0,0 +1,1421 @@ +/* ======================================================================== */ +/* ========================= LICENSING & COPYRIGHT ======================== */ +/* ======================================================================== */ +/* + * MUSASHI + * Version 3.3 + * + * A portable Motorola M680x0 processor emulation engine. + * Copyright 1998-2001 Karl Stenerud. All rights reserved. + * + * This code may be freely used for non-commercial purposes as long as this + * copyright notice remains unaltered in the source code and any binary files + * containing this code in compiled form. + * + * All other lisencing terms must be negotiated with the author + * (Karl Stenerud). + * + * The latest version of this code can be obtained at: + * http://kstenerud.cjb.net + */ + + + +/* ======================================================================== */ +/* ============================ CODE GENERATOR ============================ */ +/* ======================================================================== */ +/* + * This is the code generator program which will generate the opcode table + * and the final opcode handlers. + * + * It requires an input file to function (default m68k_in.c), but you can + * specify your own like so: + * + * m68kmake <output path> <input file> + * + * where output path is the path where the output files should be placed, and + * input file is the file to use for input. + * + * If you modify the input file greatly from its released form, you may have + * to tweak the configuration section a bit since I'm using static allocation + * to keep things simple. + * + * + * TODO: - build a better code generator for the move instruction. + * - Add callm and rtm instructions + * - Fix RTE to handle other format words + * - Add address error (and bus error?) handling + */ + + +char* g_version = "3.3"; + +/* ======================================================================== */ +/* =============================== INCLUDES =============================== */ +/* ======================================================================== */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <stdarg.h> + + + +/* ======================================================================== */ +/* ============================= CONFIGURATION ============================ */ +/* ======================================================================== */ + +#define M68K_MAX_PATH 1024 +#define M68K_MAX_DIR 1024 + +#define NUM_CPUS 3 /* 000, 010, 020 */ +#define MAX_LINE_LENGTH 200 /* length of 1 line */ +#define MAX_BODY_LENGTH 300 /* Number of lines in 1 function */ +#define MAX_REPLACE_LENGTH 30 /* Max number of replace strings */ +#define MAX_INSERT_LENGTH 5000 /* Max size of insert piece */ +#define MAX_NAME_LENGTH 30 /* Max length of ophandler name */ +#define MAX_SPEC_PROC_LENGTH 4 /* Max length of special processing str */ +#define MAX_SPEC_EA_LENGTH 5 /* Max length of specified EA str */ +#define EA_ALLOWED_LENGTH 11 /* Max length of ea allowed str */ +#define MAX_OPCODE_INPUT_TABLE_LENGTH 1000 /* Max length of opcode handler tbl */ +#define MAX_OPCODE_OUTPUT_TABLE_LENGTH 3000 /* Max length of opcode handler tbl */ + +/* Default filenames */ +#define FILENAME_INPUT "m68k_in.c" +#define FILENAME_PROTOTYPE "m68kops.h" +#define FILENAME_TABLE "m68kops.c" +#define FILENAME_OPS_AC "m68kopac.c" +#define FILENAME_OPS_DM "m68kopdm.c" +#define FILENAME_OPS_NZ "m68kopnz.c" + + +/* Identifier sequences recognized by this program */ + +#define ID_INPUT_SEPARATOR "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + +#define ID_BASE "M68KMAKE" +#define ID_PROTOTYPE_HEADER ID_BASE "_PROTOTYPE_HEADER" +#define ID_PROTOTYPE_FOOTER ID_BASE "_PROTOTYPE_FOOTER" +#define ID_TABLE_HEADER ID_BASE "_TABLE_HEADER" +#define ID_TABLE_FOOTER ID_BASE "_TABLE_FOOTER" +#define ID_TABLE_BODY ID_BASE "_TABLE_BODY" +#define ID_TABLE_START ID_BASE "_TABLE_START" +#define ID_OPHANDLER_HEADER ID_BASE "_OPCODE_HANDLER_HEADER" +#define ID_OPHANDLER_FOOTER ID_BASE "_OPCODE_HANDLER_FOOTER" +#define ID_OPHANDLER_BODY ID_BASE "_OPCODE_HANDLER_BODY" +#define ID_END ID_BASE "_END" + +#define ID_OPHANDLER_NAME ID_BASE "_OP" +#define ID_OPHANDLER_EA_AY_8 ID_BASE "_GET_EA_AY_8" +#define ID_OPHANDLER_EA_AY_16 ID_BASE "_GET_EA_AY_16" +#define ID_OPHANDLER_EA_AY_32 ID_BASE "_GET_EA_AY_32" +#define ID_OPHANDLER_OPER_AY_8 ID_BASE "_GET_OPER_AY_8" +#define ID_OPHANDLER_OPER_AY_16 ID_BASE "_GET_OPER_AY_16" +#define ID_OPHANDLER_OPER_AY_32 ID_BASE "_GET_OPER_AY_32" +#define ID_OPHANDLER_CC ID_BASE "_CC" +#define ID_OPHANDLER_NOT_CC ID_BASE "_NOT_CC" + + +#ifndef DECL_SPEC +#define DECL_SPEC +#endif /* DECL_SPEC */ + + + +/* ======================================================================== */ +/* ============================== PROTOTYPES ============================== */ +/* ======================================================================== */ + +#define CPU_TYPE_000 0 +#define CPU_TYPE_010 1 +#define CPU_TYPE_020 2 + +#define UNSPECIFIED "." +#define UNSPECIFIED_CH '.' + +#define HAS_NO_EA_MODE(A) (strcmp(A, "..........") == 0) +#define HAS_EA_AI(A) ((A)[0] == 'A') +#define HAS_EA_PI(A) ((A)[1] == '+') +#define HAS_EA_PD(A) ((A)[2] == '-') +#define HAS_EA_DI(A) ((A)[3] == 'D') +#define HAS_EA_IX(A) ((A)[4] == 'X') +#define HAS_EA_AW(A) ((A)[5] == 'W') +#define HAS_EA_AL(A) ((A)[6] == 'L') +#define HAS_EA_PCDI(A) ((A)[7] == 'd') +#define HAS_EA_PCIX(A) ((A)[8] == 'x') +#define HAS_EA_I(A) ((A)[9] == 'I') + +enum +{ + EA_MODE_NONE, /* No special addressing mode */ + EA_MODE_AI, /* Address register indirect */ + EA_MODE_PI, /* Address register indirect with postincrement */ + EA_MODE_PI7, /* Address register 7 indirect with postincrement */ + EA_MODE_PD, /* Address register indirect with predecrement */ + EA_MODE_PD7, /* Address register 7 indirect with predecrement */ + EA_MODE_DI, /* Address register indirect with displacement */ + EA_MODE_IX, /* Address register indirect with index */ + EA_MODE_AW, /* Absolute word */ + EA_MODE_AL, /* Absolute long */ + EA_MODE_PCDI, /* Program counter indirect with displacement */ + EA_MODE_PCIX, /* Program counter indirect with index */ + EA_MODE_I /* Immediate */ +}; + + +/* Everything we need to know about an opcode */ +typedef struct +{ + char name[MAX_NAME_LENGTH]; /* opcode handler name */ + unsigned char size; /* Size of operation */ + char spec_proc[MAX_SPEC_PROC_LENGTH]; /* Special processing mode */ + char spec_ea[MAX_SPEC_EA_LENGTH]; /* Specified effective addressing mode */ + unsigned char bits; /* Number of significant bits (used for sorting the table) */ + unsigned short op_mask; /* Mask to apply for matching an opcode to a handler */ + unsigned short op_match; /* Value to match after masking */ + char ea_allowed[EA_ALLOWED_LENGTH]; /* Effective addressing modes allowed */ + char cpu_mode[NUM_CPUS]; /* User or supervisor mode */ + char cpus[NUM_CPUS+1]; /* Allowed CPUs */ + unsigned char cycles[NUM_CPUS]; /* cycles for 000, 010, 020 */ +} opcode_struct; + + +/* All modifications necessary for a specific EA mode of an instruction */ +typedef struct +{ + char* fname_add; + char* ea_add; + unsigned int mask_add; + unsigned int match_add; +} ea_info_struct; + + +/* Holds the body of a function */ +typedef struct +{ + char body[MAX_BODY_LENGTH][MAX_LINE_LENGTH+1]; + int length; +} body_struct; + + +/* Holds a sequence of search / replace strings */ +typedef struct +{ + char replace[MAX_REPLACE_LENGTH][2][MAX_LINE_LENGTH+1]; + int length; +} replace_struct; + + +/* Function Prototypes */ +void error_exit(char* fmt, ...); +void perror_exit(char* fmt, ...); +int check_strsncpy(char* dst, char* src, int maxlength); +int check_atoi(char* str, int *result); +int skip_spaces(char* str); +int num_bits(int value); +int atoh(char* buff); +int fgetline(char* buff, int nchars, FILE* file); +int get_oper_cycles(opcode_struct* op, int ea_mode, int cpu_type); +opcode_struct* find_opcode(char* name, int size, char* spec_proc, char* spec_ea); +opcode_struct* find_illegal_opcode(void); +int extract_opcode_info(char* src, char* name, int* size, char* spec_proc, char* spec_ea); +void add_replace_string(replace_struct* replace, char* search_str, char* replace_str); +void write_body(FILE* filep, body_struct* body, replace_struct* replace); +void get_base_name(char* base_name, opcode_struct* op); +void write_prototype(FILE* filep, char* base_name); +void write_function_name(FILE* filep, char* base_name); +void add_opcode_output_table_entry(opcode_struct* op, char* name); +static int DECL_SPEC compare_nof_true_bits(const void* aptr, const void* bptr); +void print_opcode_output_table(FILE* filep); +void write_table_entry(FILE* filep, opcode_struct* op); +void set_opcode_struct(opcode_struct* src, opcode_struct* dst, int ea_mode); +void generate_opcode_handler(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* opinfo, int ea_mode); +void generate_opcode_ea_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op); +void generate_opcode_cc_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op_in, int offset); +void process_opcode_handlers(void); +void populate_table(void); +void read_insert(char* insert); + + + +/* ======================================================================== */ +/* ================================= DATA ================================= */ +/* ======================================================================== */ + +/* Name of the input file */ +char g_input_filename[M68K_MAX_PATH] = FILENAME_INPUT; + +/* File handles */ +FILE* g_input_file = NULL; +FILE* g_prototype_file = NULL; +FILE* g_table_file = NULL; +FILE* g_ops_ac_file = NULL; +FILE* g_ops_dm_file = NULL; +FILE* g_ops_nz_file = NULL; + +int g_num_functions = 0; /* Number of functions processed */ +int g_num_primitives = 0; /* Number of function primitives read */ +int g_line_number = 1; /* Current line number */ + +/* Opcode handler table */ +opcode_struct g_opcode_input_table[MAX_OPCODE_INPUT_TABLE_LENGTH]; + +opcode_struct g_opcode_output_table[MAX_OPCODE_OUTPUT_TABLE_LENGTH]; +int g_opcode_output_table_length = 0; + +ea_info_struct g_ea_info_table[13] = +{/* fname ea mask match */ + {"", "", 0x00, 0x00}, /* EA_MODE_NONE */ + {"ai", "AY_AI", 0x38, 0x10}, /* EA_MODE_AI */ + {"pi", "AY_PI", 0x38, 0x18}, /* EA_MODE_PI */ + {"pi7", "A7_PI", 0x3f, 0x1f}, /* EA_MODE_PI7 */ + {"pd", "AY_PD", 0x38, 0x20}, /* EA_MODE_PD */ + {"pd7", "A7_PD", 0x3f, 0x27}, /* EA_MODE_PD7 */ + {"di", "AY_DI", 0x38, 0x28}, /* EA_MODE_DI */ + {"ix", "AY_IX", 0x38, 0x30}, /* EA_MODE_IX */ + {"aw", "AW", 0x3f, 0x38}, /* EA_MODE_AW */ + {"al", "AL", 0x3f, 0x39}, /* EA_MODE_AL */ + {"pcdi", "PCDI", 0x3f, 0x3a}, /* EA_MODE_PCDI */ + {"pcix", "PCIX", 0x3f, 0x3b}, /* EA_MODE_PCIX */ + {"i", "I", 0x3f, 0x3c}, /* EA_MODE_I */ +}; + + +char* g_cc_table[16][2] = +{ + { "t", "T"}, /* 0000 */ + { "f", "F"}, /* 0001 */ + {"hi", "HI"}, /* 0010 */ + {"ls", "LS"}, /* 0011 */ + {"cc", "CC"}, /* 0100 */ + {"cs", "CS"}, /* 0101 */ + {"ne", "NE"}, /* 0110 */ + {"eq", "EQ"}, /* 0111 */ + {"vc", "VC"}, /* 1000 */ + {"vs", "VS"}, /* 1001 */ + {"pl", "PL"}, /* 1010 */ + {"mi", "MI"}, /* 1011 */ + {"ge", "GE"}, /* 1100 */ + {"lt", "LT"}, /* 1101 */ + {"gt", "GT"}, /* 1110 */ + {"le", "LE"}, /* 1111 */ +}; + +/* size to index translator (0 -> 0, 8 and 16 -> 1, 32 -> 2) */ +int g_size_select_table[33] = +{ + 0, /* unsized */ + 0, 0, 0, 0, 0, 0, 0, 1, /* 8 */ + 0, 0, 0, 0, 0, 0, 0, 1, /* 16 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 /* 32 */ +}; + +/* Extra cycles required for certain EA modes */ +int g_ea_cycle_table[13][NUM_CPUS][3] = +{/* 000 010 020 */ + {{ 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}}, /* EA_MODE_NONE */ + {{ 0, 4, 8}, { 0, 4, 8}, { 0, 4, 4}}, /* EA_MODE_AI */ + {{ 0, 4, 8}, { 0, 4, 8}, { 0, 4, 4}}, /* EA_MODE_PI */ + {{ 0, 4, 8}, { 0, 4, 8}, { 0, 4, 4}}, /* EA_MODE_PI7 */ + {{ 0, 6, 10}, { 0, 6, 10}, { 0, 5, 5}}, /* EA_MODE_PD */ + {{ 0, 6, 10}, { 0, 6, 10}, { 0, 5, 5}}, /* EA_MODE_PD7 */ + {{ 0, 8, 12}, { 0, 8, 12}, { 0, 5, 5}}, /* EA_MODE_DI */ + {{ 0, 10, 14}, { 0, 10, 14}, { 0, 7, 7}}, /* EA_MODE_IX */ + {{ 0, 8, 12}, { 0, 8, 12}, { 0, 4, 4}}, /* EA_MODE_AW */ + {{ 0, 12, 16}, { 0, 12, 16}, { 0, 4, 4}}, /* EA_MODE_AL */ + {{ 0, 8, 12}, { 0, 8, 12}, { 0, 5, 5}}, /* EA_MODE_PCDI */ + {{ 0, 10, 14}, { 0, 10, 14}, { 0, 7, 7}}, /* EA_MODE_PCIX */ + {{ 0, 4, 8}, { 0, 4, 8}, { 0, 2, 4}}, /* EA_MODE_I */ +}; + +/* Extra cycles for JMP instruction (000, 010) */ +int g_jmp_cycle_table[13] = +{ + 0, /* EA_MODE_NONE */ + 4, /* EA_MODE_AI */ + 0, /* EA_MODE_PI */ + 0, /* EA_MODE_PI7 */ + 0, /* EA_MODE_PD */ + 0, /* EA_MODE_PD7 */ + 6, /* EA_MODE_DI */ + 8, /* EA_MODE_IX */ + 6, /* EA_MODE_AW */ + 8, /* EA_MODE_AL */ + 6, /* EA_MODE_PCDI */ + 10, /* EA_MODE_PCIX */ + 0, /* EA_MODE_I */ +}; + +/* Extra cycles for JSR instruction (000, 010) */ +int g_jsr_cycle_table[13] = +{ + 0, /* EA_MODE_NONE */ + 4, /* EA_MODE_AI */ + 0, /* EA_MODE_PI */ + 0, /* EA_MODE_PI7 */ + 0, /* EA_MODE_PD */ + 0, /* EA_MODE_PD7 */ + 6, /* EA_MODE_DI */ + 10, /* EA_MODE_IX */ + 6, /* EA_MODE_AW */ + 8, /* EA_MODE_AL */ + 6, /* EA_MODE_PCDI */ + 10, /* EA_MODE_PCIX */ + 0, /* EA_MODE_I */ +}; + +/* Extra cycles for LEA instruction (000, 010) */ +int g_lea_cycle_table[13] = +{ + 0, /* EA_MODE_NONE */ + 4, /* EA_MODE_AI */ + 0, /* EA_MODE_PI */ + 0, /* EA_MODE_PI7 */ + 0, /* EA_MODE_PD */ + 0, /* EA_MODE_PD7 */ + 8, /* EA_MODE_DI */ + 12, /* EA_MODE_IX */ + 8, /* EA_MODE_AW */ + 12, /* EA_MODE_AL */ + 8, /* EA_MODE_PCDI */ + 12, /* EA_MODE_PCIX */ + 0, /* EA_MODE_I */ +}; + +/* Extra cycles for PEA instruction (000, 010) */ +int g_pea_cycle_table[13] = +{ + 0, /* EA_MODE_NONE */ + 4, /* EA_MODE_AI */ + 0, /* EA_MODE_PI */ + 0, /* EA_MODE_PI7 */ + 0, /* EA_MODE_PD */ + 0, /* EA_MODE_PD7 */ + 10, /* EA_MODE_DI */ + 14, /* EA_MODE_IX */ + 10, /* EA_MODE_AW */ + 14, /* EA_MODE_AL */ + 10, /* EA_MODE_PCDI */ + 14, /* EA_MODE_PCIX */ + 0, /* EA_MODE_I */ +}; + +/* Extra cycles for MOVES instruction (010) */ +int g_moves_cycle_table[13][3] = +{ + { 0, 0, 0}, /* EA_MODE_NONE */ + { 0, 4, 6}, /* EA_MODE_AI */ + { 0, 4, 6}, /* EA_MODE_PI */ + { 0, 4, 6}, /* EA_MODE_PI7 */ + { 0, 6, 12}, /* EA_MODE_PD */ + { 0, 6, 12}, /* EA_MODE_PD7 */ + { 0, 12, 16}, /* EA_MODE_DI */ + { 0, 16, 20}, /* EA_MODE_IX */ + { 0, 12, 16}, /* EA_MODE_AW */ + { 0, 16, 20}, /* EA_MODE_AL */ + { 0, 0, 0}, /* EA_MODE_PCDI */ + { 0, 0, 0}, /* EA_MODE_PCIX */ + { 0, 0, 0}, /* EA_MODE_I */ +}; + +/* Extra cycles for CLR instruction (010) */ +int g_clr_cycle_table[13][3] = +{ + { 0, 0, 0}, /* EA_MODE_NONE */ + { 0, 4, 6}, /* EA_MODE_AI */ + { 0, 4, 6}, /* EA_MODE_PI */ + { 0, 4, 6}, /* EA_MODE_PI7 */ + { 0, 6, 8}, /* EA_MODE_PD */ + { 0, 6, 8}, /* EA_MODE_PD7 */ + { 0, 8, 10}, /* EA_MODE_DI */ + { 0, 10, 14}, /* EA_MODE_IX */ + { 0, 8, 10}, /* EA_MODE_AW */ + { 0, 10, 14}, /* EA_MODE_AL */ + { 0, 0, 0}, /* EA_MODE_PCDI */ + { 0, 0, 0}, /* EA_MODE_PCIX */ + { 0, 0, 0}, /* EA_MODE_I */ +}; + + + +/* ======================================================================== */ +/* =========================== UTILITY FUNCTIONS ========================== */ +/* ======================================================================== */ + +/* Print an error message and exit with status error */ +void error_exit(char* fmt, ...) +{ + va_list args; + fprintf(stderr, "In %s, near or on line %d:\n\t", g_input_filename, g_line_number); + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + fprintf(stderr, "\n"); + + if(g_prototype_file) fclose(g_prototype_file); + if(g_table_file) fclose(g_table_file); + if(g_ops_ac_file) fclose(g_ops_ac_file); + if(g_ops_dm_file) fclose(g_ops_dm_file); + if(g_ops_nz_file) fclose(g_ops_nz_file); + if(g_input_file) fclose(g_input_file); + + exit(EXIT_FAILURE); +} + +/* Print an error message, call perror(), and exit with status error */ +void perror_exit(char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + perror(""); + + if(g_prototype_file) fclose(g_prototype_file); + if(g_table_file) fclose(g_table_file); + if(g_ops_ac_file) fclose(g_ops_ac_file); + if(g_ops_dm_file) fclose(g_ops_dm_file); + if(g_ops_nz_file) fclose(g_ops_nz_file); + if(g_input_file) fclose(g_input_file); + + exit(EXIT_FAILURE); +} + + +/* copy until 0 or space and exit with error if we read too far */ +int check_strsncpy(char* dst, char* src, int maxlength) +{ + char* p = dst; + while(*src && *src != ' ') + { + *p++ = *src++; + if(p - dst > maxlength) + error_exit("Field too long"); + } + *p = 0; + return p - dst; +} + +/* copy until 0 or specified character and exit with error if we read too far */ +int check_strcncpy(char* dst, char* src, char delim, int maxlength) +{ + char* p = dst; + while(*src && *src != delim) + { + *p++ = *src++; + if(p - dst > maxlength) + error_exit("Field too long"); + } + *p = 0; + return p - dst; +} + +/* convert ascii to integer and exit with error if we find invalid data */ +int check_atoi(char* str, int *result) +{ + int accum = 0; + char* p = str; + while(*p >= '0' && *p <= '9') + { + accum *= 10; + accum += *p++ - '0'; + } + if(*p != ' ' && *p != 0) + error_exit("Malformed integer value (%c)", *p); + *result = accum; + return p - str; +} + +/* Skip past spaces in a string */ +int skip_spaces(char* str) +{ + char* p = str; + + while(*p == ' ') + p++; + + return p - str; +} + +/* Count the number of set bits in a value */ +int num_bits(int value) +{ + value = ((value & 0xaaaa) >> 1) + (value & 0x5555); + value = ((value & 0xcccc) >> 2) + (value & 0x3333); + value = ((value & 0xf0f0) >> 4) + (value & 0x0f0f); + value = ((value & 0xff00) >> 8) + (value & 0x00ff); + return value; +} + +/* Convert a hex value written in ASCII */ +int atoh(char* buff) +{ + int accum = 0; + + for(;;buff++) + { + if(*buff >= '0' && *buff <= '9') + { + accum <<= 4; + accum += *buff - '0'; + } + else if(*buff >= 'a' && *buff <= 'f') + { + accum <<= 4; + accum += *buff - 'a' + 10; + } + else break; + } + return accum; +} + +/* Get a line of text from a file, discarding any end-of-line characters */ +int fgetline(char* buff, int nchars, FILE* file) +{ + int length; + + if(fgets(buff, nchars, file) == NULL) + return -1; + if(buff[0] == '\r') + memcpy(buff, buff + 1, nchars - 1); + + length = strlen(buff); + while(length && (buff[length-1] == '\r' || buff[length-1] == '\n')) + length--; + buff[length] = 0; + g_line_number++; + + return length; +} + + + +/* ======================================================================== */ +/* =========================== HELPER FUNCTIONS =========================== */ +/* ======================================================================== */ + +/* Calculate the number of cycles an opcode requires */ +int get_oper_cycles(opcode_struct* op, int ea_mode, int cpu_type) +{ + int size = g_size_select_table[op->size]; + + if(op->cpus[cpu_type] == '.') + return 0; + + if(cpu_type < CPU_TYPE_020) + { + if(cpu_type == CPU_TYPE_010) + { + if(strcmp(op->name, "moves") == 0) + return op->cycles[cpu_type] + g_moves_cycle_table[ea_mode][size]; + if(strcmp(op->name, "clr") == 0) + return op->cycles[cpu_type] + g_clr_cycle_table[ea_mode][size]; + } + + /* ASG: added these cases -- immediate modes take 2 extra cycles here */ + if(cpu_type == CPU_TYPE_000 && ea_mode == EA_MODE_I && + ((strcmp(op->name, "add") == 0 && strcmp(op->spec_proc, "er") == 0) || + strcmp(op->name, "adda") == 0 || + (strcmp(op->name, "and") == 0 && strcmp(op->spec_proc, "er") == 0) || + (strcmp(op->name, "or") == 0 && strcmp(op->spec_proc, "er") == 0) || + (strcmp(op->name, "sub") == 0 && strcmp(op->spec_proc, "er") == 0) || + strcmp(op->name, "suba") == 0)) + return op->cycles[cpu_type] + g_ea_cycle_table[ea_mode][cpu_type][size] + 2; + + if(strcmp(op->name, "jmp") == 0) + return op->cycles[cpu_type] + g_jmp_cycle_table[ea_mode]; + if(strcmp(op->name, "jsr") == 0) + return op->cycles[cpu_type] + g_jsr_cycle_table[ea_mode]; + if(strcmp(op->name, "lea") == 0) + return op->cycles[cpu_type] + g_lea_cycle_table[ea_mode]; + if(strcmp(op->name, "pea") == 0) + return op->cycles[cpu_type] + g_pea_cycle_table[ea_mode]; + } + return op->cycles[cpu_type] + g_ea_cycle_table[ea_mode][cpu_type][size]; +} + +/* Find an opcode in the opcode handler list */ +opcode_struct* find_opcode(char* name, int size, char* spec_proc, char* spec_ea) +{ + opcode_struct* op; + + + for(op = g_opcode_input_table;op->name != NULL;op++) + { + if( strcmp(name, op->name) == 0 && + (size == op->size) && + strcmp(spec_proc, op->spec_proc) == 0 && + strcmp(spec_ea, op->spec_ea) == 0) + return op; + } + return NULL; +} + +/* Specifically find the illegal opcode in the list */ +opcode_struct* find_illegal_opcode(void) +{ + opcode_struct* op; + + for(op = g_opcode_input_table;op->name != NULL;op++) + { + if(strcmp(op->name, "illegal") == 0) + return op; + } + return NULL; +} + +/* Parse an opcode handler name */ +int extract_opcode_info(char* src, char* name, int* size, char* spec_proc, char* spec_ea) +{ + char* ptr = strstr(src, ID_OPHANDLER_NAME); + + if(ptr == NULL) + return 0; + + ptr += strlen(ID_OPHANDLER_NAME) + 1; + + ptr += check_strcncpy(name, ptr, ',', MAX_NAME_LENGTH); + if(*ptr != ',') return 0; + ptr++; + ptr += skip_spaces(ptr); + + *size = atoi(ptr); + ptr = strstr(ptr, ","); + if(ptr == NULL) return 0; + ptr++; + ptr += skip_spaces(ptr); + + ptr += check_strcncpy(spec_proc, ptr, ',', MAX_SPEC_PROC_LENGTH); + if(*ptr != ',') return 0; + ptr++; + ptr += skip_spaces(ptr); + + ptr += check_strcncpy(spec_ea, ptr, ')', MAX_SPEC_EA_LENGTH); + if(*ptr != ')') return 0; + ptr++; + ptr += skip_spaces(ptr); + + return 1; +} + + +/* Add a search/replace pair to a replace structure */ +void add_replace_string(replace_struct* replace, char* search_str, char* replace_str) +{ + if(replace->length >= MAX_REPLACE_LENGTH) + error_exit("overflow in replace structure"); + + strcpy(replace->replace[replace->length][0], search_str); + strcpy(replace->replace[replace->length++][1], replace_str); +} + +/* Write a function body while replacing any selected strings */ +void write_body(FILE* filep, body_struct* body, replace_struct* replace) +{ + int i; + int j; + char* ptr; + char output[MAX_LINE_LENGTH+1]; + char temp_buff[MAX_LINE_LENGTH+1]; + int found; + + for(i=0;i<body->length;i++) + { + strcpy(output, body->body[i]); + /* Check for the base directive header */ + if(strstr(output, ID_BASE) != NULL) + { + /* Search for any text we need to replace */ + found = 0; + for(j=0;j<replace->length;j++) + { + ptr = strstr(output, replace->replace[j][0]); + if(ptr) + { + /* We found something to replace */ + found = 1; + strcpy(temp_buff, ptr+strlen(replace->replace[j][0])); + strcpy(ptr, replace->replace[j][1]); + strcat(ptr, temp_buff); + } + } + /* Found a directive with no matching replace string */ + if(!found) + error_exit("Unknown " ID_BASE " directive"); + } + fprintf(filep, "%s\n", output); + } + fprintf(filep, "\n\n"); +} + +/* Generate a base function name from an opcode struct */ +void get_base_name(char* base_name, opcode_struct* op) +{ + sprintf(base_name, "m68k_op_%s", op->name); + if(op->size > 0) + sprintf(base_name+strlen(base_name), "_%d", op->size); + if(strcmp(op->spec_proc, UNSPECIFIED) != 0) + sprintf(base_name+strlen(base_name), "_%s", op->spec_proc); + if(strcmp(op->spec_ea, UNSPECIFIED) != 0) + sprintf(base_name+strlen(base_name), "_%s", op->spec_ea); +} + +/* Write the prototype of an opcode handler function */ +void write_prototype(FILE* filep, char* base_name) +{ + fprintf(filep, "void %s(void);\n", base_name); +} + +/* Write the name of an opcode handler function */ +void write_function_name(FILE* filep, char* base_name) +{ + fprintf(filep, "void %s(void)\n", base_name); +} + +void add_opcode_output_table_entry(opcode_struct* op, char* name) +{ + opcode_struct* ptr; + if(g_opcode_output_table_length > MAX_OPCODE_OUTPUT_TABLE_LENGTH) + error_exit("Opcode output table overflow"); + + ptr = g_opcode_output_table + g_opcode_output_table_length++; + + *ptr = *op; + strcpy(ptr->name, name); + ptr->bits = num_bits(ptr->op_mask); +} + +/* + * Comparison function for qsort() + * For entries with an equal number of set bits in + * the mask compare the match values + */ +static int DECL_SPEC compare_nof_true_bits(const void* aptr, const void* bptr) +{ + const opcode_struct *a = aptr, *b = bptr; + if(a->bits != b->bits) + return a->bits - b->bits; + if(a->op_mask != b->op_mask) + return a->op_mask - b->op_mask; + return a->op_match - b->op_match; +} + +void print_opcode_output_table(FILE* filep) +{ + int i; + qsort((void *)g_opcode_output_table, g_opcode_output_table_length, sizeof(g_opcode_output_table[0]), compare_nof_true_bits); + + for(i=0;i<g_opcode_output_table_length;i++) + write_table_entry(filep, g_opcode_output_table+i); +} + +/* Write an entry in the opcode handler table */ +void write_table_entry(FILE* filep, opcode_struct* op) +{ + int i; + + fprintf(filep, "\t{%-28s, 0x%04x, 0x%04x, {", + op->name, op->op_mask, op->op_match); + + for(i=0;i<NUM_CPUS;i++) + { + fprintf(filep, "%3d", op->cycles[i]); + if(i < NUM_CPUS-1) + fprintf(filep, ", "); + } + + fprintf(filep, "}},\n"); +} + +/* Fill out an opcode struct with a specific addressing mode of the source opcode struct */ +void set_opcode_struct(opcode_struct* src, opcode_struct* dst, int ea_mode) +{ + int i; + + *dst = *src; + + for(i=0;i<NUM_CPUS;i++) + dst->cycles[i] = get_oper_cycles(dst, ea_mode, i); + if(strcmp(dst->spec_ea, UNSPECIFIED) == 0 && ea_mode != EA_MODE_NONE) + sprintf(dst->spec_ea, "%s", g_ea_info_table[ea_mode].fname_add); + dst->op_mask |= g_ea_info_table[ea_mode].mask_add; + dst->op_match |= g_ea_info_table[ea_mode].match_add; +} + + +/* Generate a final opcode handler from the provided data */ +void generate_opcode_handler(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* opinfo, int ea_mode) +{ + char str[MAX_LINE_LENGTH+1]; + opcode_struct* op = malloc(sizeof(opcode_struct)); + + /* Set the opcode structure and write the tables, prototypes, etc */ + set_opcode_struct(opinfo, op, ea_mode); + get_base_name(str, op); + write_prototype(g_prototype_file, str); + add_opcode_output_table_entry(op, str); + write_function_name(filep, str); + + /* Add any replace strings needed */ + if(ea_mode != EA_MODE_NONE) + { + sprintf(str, "EA_%s_8()", g_ea_info_table[ea_mode].ea_add); + add_replace_string(replace, ID_OPHANDLER_EA_AY_8, str); + sprintf(str, "EA_%s_16()", g_ea_info_table[ea_mode].ea_add); + add_replace_string(replace, ID_OPHANDLER_EA_AY_16, str); + sprintf(str, "EA_%s_32()", g_ea_info_table[ea_mode].ea_add); + add_replace_string(replace, ID_OPHANDLER_EA_AY_32, str); + sprintf(str, "OPER_%s_8()", g_ea_info_table[ea_mode].ea_add); + add_replace_string(replace, ID_OPHANDLER_OPER_AY_8, str); + sprintf(str, "OPER_%s_16()", g_ea_info_table[ea_mode].ea_add); + add_replace_string(replace, ID_OPHANDLER_OPER_AY_16, str); + sprintf(str, "OPER_%s_32()", g_ea_info_table[ea_mode].ea_add); + add_replace_string(replace, ID_OPHANDLER_OPER_AY_32, str); + } + + /* Now write the function body with the selected replace strings */ + write_body(filep, body, replace); + g_num_functions++; + free(op); +} + +/* Generate opcode variants based on available addressing modes */ +void generate_opcode_ea_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op) +{ + int old_length = replace->length; + + /* No ea modes available for this opcode */ + if(HAS_NO_EA_MODE(op->ea_allowed)) + { + generate_opcode_handler(filep, body, replace, op, EA_MODE_NONE); + return; + } + + /* Check for and create specific opcodes for each available addressing mode */ + if(HAS_EA_AI(op->ea_allowed)) + generate_opcode_handler(filep, body, replace, op, EA_MODE_AI); + replace->length = old_length; + if(HAS_EA_PI(op->ea_allowed)) + { + generate_opcode_handler(filep, body, replace, op, EA_MODE_PI); + replace->length = old_length; + if(op->size == 8) + generate_opcode_handler(filep, body, replace, op, EA_MODE_PI7); + } + replace->length = old_length; + if(HAS_EA_PD(op->ea_allowed)) + { + generate_opcode_handler(filep, body, replace, op, EA_MODE_PD); + replace->length = old_length; + if(op->size == 8) + generate_opcode_handler(filep, body, replace, op, EA_MODE_PD7); + } + replace->length = old_length; + if(HAS_EA_DI(op->ea_allowed)) + generate_opcode_handler(filep, body, replace, op, EA_MODE_DI); + replace->length = old_length; + if(HAS_EA_IX(op->ea_allowed)) + generate_opcode_handler(filep, body, replace, op, EA_MODE_IX); + replace->length = old_length; + if(HAS_EA_AW(op->ea_allowed)) + generate_opcode_handler(filep, body, replace, op, EA_MODE_AW); + replace->length = old_length; + if(HAS_EA_AL(op->ea_allowed)) + generate_opcode_handler(filep, body, replace, op, EA_MODE_AL); + replace->length = old_length; + if(HAS_EA_PCDI(op->ea_allowed)) + generate_opcode_handler(filep, body, replace, op, EA_MODE_PCDI); + replace->length = old_length; + if(HAS_EA_PCIX(op->ea_allowed)) + generate_opcode_handler(filep, body, replace, op, EA_MODE_PCIX); + replace->length = old_length; + if(HAS_EA_I(op->ea_allowed)) + generate_opcode_handler(filep, body, replace, op, EA_MODE_I); + replace->length = old_length; +} + +/* Generate variants of condition code opcodes */ +void generate_opcode_cc_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op_in, int offset) +{ + char repl[20]; + char replnot[20]; + int i; + int old_length = replace->length; + opcode_struct* op = malloc(sizeof(opcode_struct)); + + *op = *op_in; + + op->op_mask |= 0x0f00; + + /* Do all condition codes except t and f */ + for(i=2;i<16;i++) + { + /* Add replace strings for this condition code */ + sprintf(repl, "COND_%s()", g_cc_table[i][1]); + sprintf(replnot, "COND_NOT_%s()", g_cc_table[i][1]); + + add_replace_string(replace, ID_OPHANDLER_CC, repl); + add_replace_string(replace, ID_OPHANDLER_NOT_CC, replnot); + + /* Set the new opcode info */ + strcpy(op->name+offset, g_cc_table[i][0]); + + op->op_match = (op->op_match & 0xf0ff) | (i<<8); + + /* Generate all opcode variants for this modified opcode */ + generate_opcode_ea_variants(filep, body, replace, op); + /* Remove the above replace strings */ + replace->length = old_length; + } + free(op); +} + +/* Process the opcode handlers section of the input file */ +void process_opcode_handlers(void) +{ + FILE* input_file = g_input_file; + FILE* output_file; + char func_name[MAX_LINE_LENGTH+1]; + char oper_name[MAX_LINE_LENGTH+1]; + int oper_size; + char oper_spec_proc[MAX_LINE_LENGTH+1]; + char oper_spec_ea[MAX_LINE_LENGTH+1]; + opcode_struct* opinfo; + replace_struct* replace = malloc(sizeof(replace_struct)); + body_struct* body = malloc(sizeof(body_struct)); + + + output_file = g_ops_ac_file; + + for(;;) + { + /* Find the first line of the function */ + func_name[0] = 0; + while(strstr(func_name, ID_OPHANDLER_NAME) == NULL) + { + if(strcmp(func_name, ID_INPUT_SEPARATOR) == 0) + { + free(replace); + free(body); + return; /* all done */ + } + if(fgetline(func_name, MAX_LINE_LENGTH, input_file) < 0) + error_exit("Premature end of file when getting function name"); + } + /* Get the rest of the function */ + for(body->length=0;;body->length++) + { + if(body->length > MAX_BODY_LENGTH) + error_exit("Function too long"); + + if(fgetline(body->body[body->length], MAX_LINE_LENGTH, input_file) < 0) + error_exit("Premature end of file when getting function body"); + + if(body->body[body->length][0] == '}') + { + body->length++; + break; + } + } + + g_num_primitives++; + + /* Extract the function name information */ + if(!extract_opcode_info(func_name, oper_name, &oper_size, oper_spec_proc, oper_spec_ea)) + error_exit("Invalid " ID_OPHANDLER_NAME " format"); + + /* Find the corresponding table entry */ + opinfo = find_opcode(oper_name, oper_size, oper_spec_proc, oper_spec_ea); + if(opinfo == NULL) + error_exit("Unable to find matching table entry for %s", func_name); + + /* Change output files if we pass 'c' or 'n' */ + if(output_file == g_ops_ac_file && oper_name[0] > 'c') + output_file = g_ops_dm_file; + else if(output_file == g_ops_dm_file && oper_name[0] > 'm') + output_file = g_ops_nz_file; + + replace->length = 0; + + /* Generate opcode variants */ + if(strcmp(opinfo->name, "bcc") == 0 || strcmp(opinfo->name, "scc") == 0) + generate_opcode_cc_variants(output_file, body, replace, opinfo, 1); + else if(strcmp(opinfo->name, "dbcc") == 0) + generate_opcode_cc_variants(output_file, body, replace, opinfo, 2); + else if(strcmp(opinfo->name, "trapcc") == 0) + generate_opcode_cc_variants(output_file, body, replace, opinfo, 4); + else + generate_opcode_ea_variants(output_file, body, replace, opinfo); + } + + free(replace); + free(body); +} + + +/* Populate the opcode handler table from the input file */ +void populate_table(void) +{ + char* ptr; + char bitpattern[17]; + opcode_struct* op; + char buff[MAX_LINE_LENGTH]; + int i; + int temp; + + buff[0] = 0; + + /* Find the start of the table */ + while(strcmp(buff, ID_TABLE_START) != 0) + if(fgetline(buff, MAX_LINE_LENGTH, g_input_file) < 0) + error_exit("Premature EOF while reading table"); + + /* Process the entire table */ + for(op = g_opcode_input_table;;op++) + { + if(fgetline(buff, MAX_LINE_LENGTH, g_input_file) < 0) + error_exit("Premature EOF while reading table"); + if(strlen(buff) == 0) + continue; + /* We finish when we find an input separator */ + if(strcmp(buff, ID_INPUT_SEPARATOR) == 0) + break; + + /* Extract the info from the table */ + ptr = buff; + + /* Name */ + ptr += skip_spaces(ptr); + ptr += check_strsncpy(op->name, ptr, MAX_NAME_LENGTH); + + /* Size */ + ptr += skip_spaces(ptr); + ptr += check_atoi(ptr, &temp); + op->size = (unsigned char)temp; + + /* Special processing */ + ptr += skip_spaces(ptr); + ptr += check_strsncpy(op->spec_proc, ptr, MAX_SPEC_PROC_LENGTH); + + /* Specified EA Mode */ + ptr += skip_spaces(ptr); + ptr += check_strsncpy(op->spec_ea, ptr, MAX_SPEC_EA_LENGTH); + + /* Bit Pattern (more processing later) */ + ptr += skip_spaces(ptr); + ptr += check_strsncpy(bitpattern, ptr, 17); + + /* Allowed Addressing Mode List */ + ptr += skip_spaces(ptr); + ptr += check_strsncpy(op->ea_allowed, ptr, EA_ALLOWED_LENGTH); + + /* CPU operating mode (U = user or supervisor, S = supervisor only */ + ptr += skip_spaces(ptr); + for(i=0;i<NUM_CPUS;i++) + { + op->cpu_mode[i] = *ptr++; + ptr += skip_spaces(ptr); + } + + /* Allowed CPUs for this instruction */ + for(i=0;i<NUM_CPUS;i++) + { + ptr += skip_spaces(ptr); + if(*ptr == UNSPECIFIED_CH) + { + op->cpus[i] = UNSPECIFIED_CH; + op->cycles[i] = 0; + ptr++; + } + else + { + op->cpus[i] = '0' + i; + ptr += check_atoi(ptr, &temp); + op->cycles[i] = (unsigned char)temp; + } + } + + /* generate mask and match from bitpattern */ + op->op_mask = 0; + op->op_match = 0; + for(i=0;i<16;i++) + { + op->op_mask |= (bitpattern[i] != '.') << (15-i); + op->op_match |= (bitpattern[i] == '1') << (15-i); + } + } + /* Terminate the list */ + op->name[0] = 0; +} + +/* Read a header or footer insert from the input file */ +void read_insert(char* insert) +{ + char* ptr = insert; + char* overflow = insert + MAX_INSERT_LENGTH - MAX_LINE_LENGTH; + int length; + char* first_blank = NULL; + + first_blank = NULL; + + /* Skip any leading blank lines */ + for(length = 0;length == 0;length = fgetline(ptr, MAX_LINE_LENGTH, g_input_file)) + if(ptr >= overflow) + error_exit("Buffer overflow reading inserts"); + if(length < 0) + error_exit("Premature EOF while reading inserts"); + + /* Advance and append newline */ + ptr += length; + strcpy(ptr++, "\n"); + + /* Read until next separator */ + for(;;) + { + /* Read a new line */ + if(ptr >= overflow) + error_exit("Buffer overflow reading inserts"); + if((length = fgetline(ptr, MAX_LINE_LENGTH, g_input_file)) < 0) + error_exit("Premature EOF while reading inserts"); + + /* Stop if we read a separator */ + if(strcmp(ptr, ID_INPUT_SEPARATOR) == 0) + break; + + /* keep track in case there are trailing blanks */ + if(length == 0) + { + if(first_blank == NULL) + first_blank = ptr; + } + else + first_blank = NULL; + + /* Advance and append newline */ + ptr += length; + strcpy(ptr++, "\n"); + } + + /* kill any trailing blank lines */ + if(first_blank) + ptr = first_blank; + *ptr++ = 0; +} + + + +/* ======================================================================== */ +/* ============================= MAIN FUNCTION ============================ */ +/* ======================================================================== */ + +int main(int argc, char **argv) +{ + /* File stuff */ + char output_path[M68K_MAX_DIR] = ""; + char filename[M68K_MAX_PATH]; + /* Section identifier */ + char section_id[MAX_LINE_LENGTH+1]; + /* Inserts */ + char temp_insert[MAX_INSERT_LENGTH+1]; + char prototype_footer_insert[MAX_INSERT_LENGTH+1]; + char table_footer_insert[MAX_INSERT_LENGTH+1]; + char ophandler_footer_insert[MAX_INSERT_LENGTH+1]; + /* Flags if we've processed certain parts already */ + int prototype_header_read = 0; + int prototype_footer_read = 0; + int table_header_read = 0; + int table_footer_read = 0; + int ophandler_header_read = 0; + int ophandler_footer_read = 0; + int table_body_read = 0; + int ophandler_body_read = 0; + + printf("\n\t\tMusashi v%s 68000, 68010, 68EC020, 68020 emulator\n", g_version); + printf("\t\tCopyright 1998-2000 Karl Stenerud (karl@mame.net)\n\n"); + + /* Check if output path and source for the input file are given */ + if(argc > 1) + { + char *ptr; + strcpy(output_path, argv[1]); + + for(ptr = strchr(output_path, '\\'); ptr; ptr = strchr(ptr, '\\')) + *ptr = '/'; + if(output_path[strlen(output_path)-1] != '/') + strcat(output_path, "/"); + if(argc > 2) + strcpy(g_input_filename, argv[2]); + } + + + /* Open the files we need */ + sprintf(filename, "%s%s", output_path, FILENAME_PROTOTYPE); + if((g_prototype_file = fopen(filename, "wt")) == NULL) + perror_exit("Unable to create prototype file (%s)\n", filename); + + sprintf(filename, "%s%s", output_path, FILENAME_TABLE); + if((g_table_file = fopen(filename, "wt")) == NULL) + perror_exit("Unable to create table file (%s)\n", filename); + + sprintf(filename, "%s%s", output_path, FILENAME_OPS_AC); + if((g_ops_ac_file = fopen(filename, "wt")) == NULL) + perror_exit("Unable to create ops ac file (%s)\n", filename); + + sprintf(filename, "%s%s", output_path, FILENAME_OPS_DM); + if((g_ops_dm_file = fopen(filename, "wt")) == NULL) + perror_exit("Unable to create ops dm file (%s)\n", filename); + + sprintf(filename, "%s%s", output_path, FILENAME_OPS_NZ); + if((g_ops_nz_file = fopen(filename, "wt")) == NULL) + perror_exit("Unable to create ops nz file (%s)\n", filename); + + if((g_input_file=fopen(g_input_filename, "rt")) == NULL) + perror_exit("can't open %s for input", g_input_filename); + + + /* Get to the first section of the input file */ + section_id[0] = 0; + while(strcmp(section_id, ID_INPUT_SEPARATOR) != 0) + if(fgetline(section_id, MAX_LINE_LENGTH, g_input_file) < 0) + error_exit("Premature EOF while reading input file"); + + /* Now process all sections */ + for(;;) + { + if(fgetline(section_id, MAX_LINE_LENGTH, g_input_file) < 0) + error_exit("Premature EOF while reading input file"); + if(strcmp(section_id, ID_PROTOTYPE_HEADER) == 0) + { + if(prototype_header_read) + error_exit("Duplicate prototype header"); + read_insert(temp_insert); + fprintf(g_prototype_file, "%s\n\n", temp_insert); + prototype_header_read = 1; + } + else if(strcmp(section_id, ID_TABLE_HEADER) == 0) + { + if(table_header_read) + error_exit("Duplicate table header"); + read_insert(temp_insert); + fprintf(g_table_file, "%s", temp_insert); + table_header_read = 1; + } + else if(strcmp(section_id, ID_OPHANDLER_HEADER) == 0) + { + if(ophandler_header_read) + error_exit("Duplicate opcode handler header"); + read_insert(temp_insert); + fprintf(g_ops_ac_file, "%s\n\n", temp_insert); + fprintf(g_ops_dm_file, "%s\n\n", temp_insert); + fprintf(g_ops_nz_file, "%s\n\n", temp_insert); + ophandler_header_read = 1; + } + else if(strcmp(section_id, ID_PROTOTYPE_FOOTER) == 0) + { + if(prototype_footer_read) + error_exit("Duplicate prototype footer"); + read_insert(prototype_footer_insert); + prototype_footer_read = 1; + } + else if(strcmp(section_id, ID_TABLE_FOOTER) == 0) + { + if(table_footer_read) + error_exit("Duplicate table footer"); + read_insert(table_footer_insert); + table_footer_read = 1; + } + else if(strcmp(section_id, ID_OPHANDLER_FOOTER) == 0) + { + if(ophandler_footer_read) + error_exit("Duplicate opcode handler footer"); + read_insert(ophandler_footer_insert); + ophandler_footer_read = 1; + } + else if(strcmp(section_id, ID_TABLE_BODY) == 0) + { + if(!prototype_header_read) + error_exit("Table body encountered before prototype header"); + if(!table_header_read) + error_exit("Table body encountered before table header"); + if(!ophandler_header_read) + error_exit("Table body encountered before opcode handler header"); + + if(table_body_read) + error_exit("Duplicate table body"); + + populate_table(); + table_body_read = 1; + } + else if(strcmp(section_id, ID_OPHANDLER_BODY) == 0) + { + if(!prototype_header_read) + error_exit("Opcode handlers encountered before prototype header"); + if(!table_header_read) + error_exit("Opcode handlers encountered before table header"); + if(!ophandler_header_read) + error_exit("Opcode handlers encountered before opcode handler header"); + if(!table_body_read) + error_exit("Opcode handlers encountered before table body"); + + if(ophandler_body_read) + error_exit("Duplicate opcode handler section"); + + process_opcode_handlers(); + + ophandler_body_read = 1; + } + else if(strcmp(section_id, ID_END) == 0) + { + /* End of input file. Do a sanity check and then write footers */ + if(!prototype_header_read) + error_exit("Missing prototype header"); + if(!prototype_footer_read) + error_exit("Missing prototype footer"); + if(!table_header_read) + error_exit("Missing table header"); + if(!table_footer_read) + error_exit("Missing table footer"); + if(!table_body_read) + error_exit("Missing table body"); + if(!ophandler_header_read) + error_exit("Missing opcode handler header"); + if(!ophandler_footer_read) + error_exit("Missing opcode handler footer"); + if(!ophandler_body_read) + error_exit("Missing opcode handler body"); + + print_opcode_output_table(g_table_file); + + fprintf(g_prototype_file, "%s\n\n", prototype_footer_insert); + fprintf(g_table_file, "%s\n\n", table_footer_insert); + fprintf(g_ops_ac_file, "%s\n\n", ophandler_footer_insert); + fprintf(g_ops_dm_file, "%s\n\n", ophandler_footer_insert); + fprintf(g_ops_nz_file, "%s\n\n", ophandler_footer_insert); + + break; + } + else + { + error_exit("Unknown section identifier: %s", section_id); + } + } + + /* Close all files and exit */ + fclose(g_prototype_file); + fclose(g_table_file); + fclose(g_ops_ac_file); + fclose(g_ops_dm_file); + fclose(g_ops_nz_file); + fclose(g_input_file); + + printf("Generated %d opcode handlers from %d primitives\n", g_num_functions, g_num_primitives); + + return 0; +} + + + +/* ======================================================================== */ +/* ============================== END OF FILE ============================= */ +/* ======================================================================== */ diff --git a/plugins/ao/eng_ssf/m68kmame.h b/plugins/ao/eng_ssf/m68kmame.h new file mode 100644 index 00000000..6ac0ec59 --- /dev/null +++ b/plugins/ao/eng_ssf/m68kmame.h @@ -0,0 +1,172 @@ +#ifndef M68KMAME__HEADER +#define M68KMAME__HEADER + +/* ======================================================================== */ +/* ============================== MAME STUFF ============================== */ +/* ======================================================================== */ + +#include "cpuintrf.h" +#include "memory.h" +#include "mamedbg.h" +#include "m68000.h" + +extern int m68ki_remaining_cycles; + +/* Configuration switches (see m68kconf.h for explanation) */ +#define M68K_SEPARATE_READS OPT_ON + +#define M68K_SIMULATE_PD_WRITES OPT_ON + +#define M68K_EMULATE_INT_ACK OPT_ON +#define M68K_INT_ACK_CALLBACK(A) + +#define M68K_EMULATE_BKPT_ACK OPT_OFF +#define M68K_BKPT_ACK_CALLBACK() + +#define M68K_EMULATE_TRACE OPT_OFF + +#define M68K_EMULATE_RESET OPT_ON +#define M68K_RESET_CALLBACK() + +#define M68K_EMULATE_FC OPT_OFF +#define M68K_SET_FC_CALLBACK(A) + +#define M68K_MONITOR_PC OPT_SPECIFY_HANDLER +#define M68K_SET_PC_CALLBACK(A) (*m68k_memory_intf.changepc)(A) + +#define M68K_INSTRUCTION_HOOK OPT_SPECIFY_HANDLER +#define M68K_INSTRUCTION_CALLBACK() CALL_MAME_DEBUG + +#define M68K_EMULATE_PREFETCH OPT_ON + +#define M68K_LOG_ENABLE OPT_OFF +#define M68K_LOG_1010_1111 OPT_OFF +#define M68K_LOG_FILEHANDLE errorlog + +#define M68K_EMULATE_ADDRESS_ERROR OPT_OFF + +#define M68K_USE_64_BIT OPT_OFF + +extern struct m68k_memory_interface m68k_memory_intf; + +#define m68k_read_memory_8(address) (*m68k_memory_intf.read8)(address) +#define m68k_read_memory_16(address) (*m68k_memory_intf.read16)(address) +#define m68k_read_memory_32(address) (*m68k_memory_intf.read32)(address) + +INLINE unsigned int m68k_read_immediate_16(unsigned int address) +{ + return cpu_readop16((address) ^ m68k_memory_intf.opcode_xor); +} + +INLINE unsigned int m68k_read_immediate_32(unsigned int address) +{ + return ((m68k_read_immediate_16(address) << 16) | m68k_read_immediate_16((address)+2)); +} + +INLINE unsigned int m68k_read_pcrelative_8(unsigned int address) +{ + if (address >= encrypted_opcode_start[cpu_getactivecpu()] && + address < encrypted_opcode_end[cpu_getactivecpu()]) + return ((m68k_read_immediate_16(address&~1)>>(8*(1-(address & 1))))&0xff); + else + return m68k_read_memory_8(address); +} + +INLINE unsigned int m68k_read_pcrelative_16(unsigned int address) +{ + if (address >= encrypted_opcode_start[cpu_getactivecpu()] && + address < encrypted_opcode_end[cpu_getactivecpu()]) + return m68k_read_immediate_16(address); + else + return m68k_read_memory_16(address); +} + +INLINE unsigned int m68k_read_pcrelative_32(unsigned int address) +{ + if (address >= encrypted_opcode_start[cpu_getactivecpu()] && + address < encrypted_opcode_end[cpu_getactivecpu()]) + return m68k_read_immediate_32(address); + else + return m68k_read_memory_32(address); +} + +#define m68k_read_disassembler_16(address) m68k_read_immediate_16(address) +#define m68k_read_disassembler_32(address) m68k_read_immediate_32(address) + + +#define m68k_write_memory_8(address, value) (*m68k_memory_intf.write8)(address, value) +#define m68k_write_memory_16(address, value) (*m68k_memory_intf.write16)(address, value) +#define m68k_write_memory_32(address, value) (*m68k_memory_intf.write32)(address, value) + +/* Special call to simulate undocumented 68k behavior when move.l with a + * predecrement destination mode is executed. + * A real 68k first writes the high word to [address+2], and then writes the + * low word to [address]. + */ +INLINE void m68k_write_memory_32_pd(unsigned int address, unsigned int value) +{ + (*m68k_memory_intf.write16)(address+2, value>>16); + (*m68k_memory_intf.write16)(address, value&0xffff); +} + + +#ifdef A68K0 +#define M68K_EMULATE_010 OPT_OFF +#else + +// The PPC 68k core defines A68K0 internal to itself to avoid recompiling +// all of MAME when you want to disable it. The downside is that the C and x86 +// cores can't agree on the same name for the icount variable, so we force the +// issue with a Mac-specific hack. +#ifdef macintosh +extern int m68k_ICount; +#else +#define m68ki_remaining_cycles m68k_ICount +#endif + +/* M68K Variants */ +#if HAS_M68010 +#define M68K_EMULATE_010 OPT_ON +#else +#define M68K_EMULATE_010 OPT_OFF +#endif + +#endif // A68K0 + +#ifdef A68K2 +#define M68K_EMULATE_EC020 OPT_OFF +#define M68K_EMULATE_020 OPT_OFF +#else + +// The PPC 68k core defines A68K2 internal to itself to avoid recompiling +// all of MAME when you want to disable it. The downside is that the C and x86 +// cores can't agree on the same name for the icount variable, so we force the +// issue with a Mac-specific hack. +#ifdef macintosh +extern int M68020_ICount; +#else +#define m68ki_remaining_cycles m68k_ICount +#endif + +#undef M68K_EMULATE_010 +#define M68K_EMULATE_010 OPT_ON + +#if HAS_M68EC020 +#define M68K_EMULATE_EC020 OPT_ON +#else +#define M68K_EMULATE_EC020 OPT_OFF +#endif + +#if HAS_M68020 +#define M68K_EMULATE_020 OPT_ON +#else +#define M68K_EMULATE_020 OPT_OFF +#endif + +#endif // A68K2 + +/* ======================================================================== */ +/* ============================== END OF FILE ============================= */ +/* ======================================================================== */ + +#endif /* M68KMAME__HEADER */ diff --git a/plugins/ao/eng_ssf/m68kopac.c b/plugins/ao/eng_ssf/m68kopac.c new file mode 100644 index 00000000..405b6bbd --- /dev/null +++ b/plugins/ao/eng_ssf/m68kopac.c @@ -0,0 +1,12043 @@ +#include "ao.h" +#include "m68kcpu.h" + +/* ======================================================================== */ +/* ========================= INSTRUCTION HANDLERS ========================= */ +/* ======================================================================== */ + + +void m68k_op_1010(m68ki_cpu_core *cpu) +{ + m68ki_exception_1010(cpu); +} + + +void m68k_op_1111(m68ki_cpu_core *cpu) +{ + m68ki_exception_1111(cpu); +} + + +void m68k_op_abcd_8_rr(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = DY; + uint dst = *r_dst; + uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res += 6; + res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res -= 0xa0; + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; +} + + +void m68k_op_abcd_8_mm_ax7(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_PD_8(cpu); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res += 6; + res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res -= 0xa0; + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +void m68k_op_abcd_8_mm_ay7(m68ki_cpu_core *cpu) +{ + uint src = OPER_A7_PD_8(cpu); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res += 6; + res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res -= 0xa0; + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +void m68k_op_abcd_8_mm_axy7(m68ki_cpu_core *cpu) +{ + uint src = OPER_A7_PD_8(cpu); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res += 6; + res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res -= 0xa0; + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +void m68k_op_abcd_8_mm(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_PD_8(cpu); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res += 6; + res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res -= 0xa0; + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +void m68k_op_add_8_er_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_8(DY); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_add_8_er_ai(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_AI_8(cpu); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_add_8_er_pi(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_PI_8(cpu); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_add_8_er_pi7(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_A7_PI_8(cpu); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_add_8_er_pd(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_PD_8(cpu); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_add_8_er_pd7(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_A7_PD_8(cpu); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_add_8_er_di(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_DI_8(cpu); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_add_8_er_ix(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_IX_8(cpu); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_add_8_er_aw(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AW_8(cpu); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_add_8_er_al(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AL_8(cpu); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_add_8_er_pcdi(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_PCDI_8(cpu); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_add_8_er_pcix(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_PCIX_8(cpu); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_add_8_er_i(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_I_8(); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_add_16_er_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_16(DY); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +void m68k_op_add_16_er_a(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_16(AY); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +void m68k_op_add_16_er_ai(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_AI_16(cpu); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +void m68k_op_add_16_er_pi(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_PI_16(cpu); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +void m68k_op_add_16_er_pd(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_PD_16(cpu); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +void m68k_op_add_16_er_di(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_DI_16(cpu); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +void m68k_op_add_16_er_ix(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_IX_16(cpu); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +void m68k_op_add_16_er_aw(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AW_16(cpu); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +void m68k_op_add_16_er_al(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AL_16(cpu); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +void m68k_op_add_16_er_pcdi(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_PCDI_16(cpu); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +void m68k_op_add_16_er_pcix(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_PCIX_16(cpu); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +void m68k_op_add_16_er_i(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_I_16(); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +void m68k_op_add_32_er_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = DY; + uint dst = *r_dst; + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +void m68k_op_add_32_er_a(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = AY; + uint dst = *r_dst; + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +void m68k_op_add_32_er_ai(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_AI_32(cpu); + uint dst = *r_dst; + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +void m68k_op_add_32_er_pi(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_PI_32(cpu); + uint dst = *r_dst; + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +void m68k_op_add_32_er_pd(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_PD_32(cpu); + uint dst = *r_dst; + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +void m68k_op_add_32_er_di(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_DI_32(cpu); + uint dst = *r_dst; + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +void m68k_op_add_32_er_ix(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_IX_32(cpu); + uint dst = *r_dst; + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +void m68k_op_add_32_er_aw(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AW_32(cpu); + uint dst = *r_dst; + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +void m68k_op_add_32_er_al(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AL_32(cpu); + uint dst = *r_dst; + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +void m68k_op_add_32_er_pcdi(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_PCDI_32(cpu); + uint dst = *r_dst; + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +void m68k_op_add_32_er_pcix(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_PCIX_32(cpu); + uint dst = *r_dst; + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +void m68k_op_add_32_er_i(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_I_32(); + uint dst = *r_dst; + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +void m68k_op_add_8_re_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_8(); + uint src = MASK_OUT_ABOVE_8(DX); + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_add_8_re_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_8(); + uint src = MASK_OUT_ABOVE_8(DX); + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_add_8_re_pi7(m68ki_cpu_core *cpu) +{ + uint ea = EA_A7_PI_8(); + uint src = MASK_OUT_ABOVE_8(DX); + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_add_8_re_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_8(); + uint src = MASK_OUT_ABOVE_8(DX); + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_add_8_re_pd7(m68ki_cpu_core *cpu) +{ + uint ea = EA_A7_PD_8(); + uint src = MASK_OUT_ABOVE_8(DX); + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_add_8_re_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_8(); + uint src = MASK_OUT_ABOVE_8(DX); + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_add_8_re_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_8(); + uint src = MASK_OUT_ABOVE_8(DX); + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_add_8_re_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_8(); + uint src = MASK_OUT_ABOVE_8(DX); + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_add_8_re_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_8(); + uint src = MASK_OUT_ABOVE_8(DX); + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_add_16_re_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_16(); + uint src = MASK_OUT_ABOVE_16(DX); + uint dst = m68ki_read_16(ea); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_add_16_re_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_16(); + uint src = MASK_OUT_ABOVE_16(DX); + uint dst = m68ki_read_16(ea); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_add_16_re_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_16(); + uint src = MASK_OUT_ABOVE_16(DX); + uint dst = m68ki_read_16(ea); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_add_16_re_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_16(); + uint src = MASK_OUT_ABOVE_16(DX); + uint dst = m68ki_read_16(ea); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_add_16_re_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_16(); + uint src = MASK_OUT_ABOVE_16(DX); + uint dst = m68ki_read_16(ea); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_add_16_re_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_16(); + uint src = MASK_OUT_ABOVE_16(DX); + uint dst = m68ki_read_16(ea); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_add_16_re_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_16(); + uint src = MASK_OUT_ABOVE_16(DX); + uint dst = m68ki_read_16(ea); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_add_32_re_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_32(); + uint src = DX; + uint dst = m68ki_read_32(ea); + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_add_32_re_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_32(); + uint src = DX; + uint dst = m68ki_read_32(ea); + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_add_32_re_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_32(); + uint src = DX; + uint dst = m68ki_read_32(ea); + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_add_32_re_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_32(); + uint src = DX; + uint dst = m68ki_read_32(ea); + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_add_32_re_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_32(); + uint src = DX; + uint dst = m68ki_read_32(ea); + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_add_32_re_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_32(); + uint src = DX; + uint dst = m68ki_read_32(ea); + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_add_32_re_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_32(); + uint src = DX; + uint dst = m68ki_read_32(ea); + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_adda_16_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + MAKE_INT_16(DY)); +} + + +void m68k_op_adda_16_a(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + MAKE_INT_16(AY)); +} + + +void m68k_op_adda_16_ai(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + MAKE_INT_16(OPER_AY_AI_16(cpu))); +} + + +void m68k_op_adda_16_pi(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + MAKE_INT_16(OPER_AY_PI_16(cpu))); +} + + +void m68k_op_adda_16_pd(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + MAKE_INT_16(OPER_AY_PD_16(cpu))); +} + + +void m68k_op_adda_16_di(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + MAKE_INT_16(OPER_AY_DI_16(cpu))); +} + + +void m68k_op_adda_16_ix(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + MAKE_INT_16(OPER_AY_IX_16(cpu))); +} + + +void m68k_op_adda_16_aw(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + MAKE_INT_16(OPER_AW_16(cpu))); +} + + +void m68k_op_adda_16_al(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + MAKE_INT_16(OPER_AL_16(cpu))); +} + + +void m68k_op_adda_16_pcdi(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + MAKE_INT_16(OPER_PCDI_16(cpu))); +} + + +void m68k_op_adda_16_pcix(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + MAKE_INT_16(OPER_PCIX_16(cpu))); +} + + +void m68k_op_adda_16_i(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + MAKE_INT_16(OPER_I_16())); +} + + +void m68k_op_adda_32_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + DY); +} + + +void m68k_op_adda_32_a(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + AY); +} + + +void m68k_op_adda_32_ai(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + OPER_AY_AI_32(cpu)); +} + + +void m68k_op_adda_32_pi(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + OPER_AY_PI_32(cpu)); +} + + +void m68k_op_adda_32_pd(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + OPER_AY_PD_32(cpu)); +} + + +void m68k_op_adda_32_di(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + OPER_AY_DI_32(cpu)); +} + + +void m68k_op_adda_32_ix(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + OPER_AY_IX_32(cpu)); +} + + +void m68k_op_adda_32_aw(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + OPER_AW_32(cpu)); +} + + +void m68k_op_adda_32_al(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + OPER_AL_32(cpu)); +} + + +void m68k_op_adda_32_pcdi(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + OPER_PCDI_32(cpu)); +} + + +void m68k_op_adda_32_pcix(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + OPER_PCIX_32(cpu)); +} + + +void m68k_op_adda_32_i(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + OPER_I_32()); +} + + +void m68k_op_addi_8_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint src = OPER_I_8(); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_addi_8_ai(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AY_AI_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_addi_8_pi(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AY_PI_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_addi_8_pi7(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_A7_PI_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_addi_8_pd(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AY_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_addi_8_pd7(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_addi_8_di(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AY_DI_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_addi_8_ix(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AY_IX_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_addi_8_aw(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AW_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_addi_8_al(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AL_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_addi_16_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint src = OPER_I_16(); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +void m68k_op_addi_16_ai(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AY_AI_16(); + uint dst = m68ki_read_16(ea); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_addi_16_pi(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AY_PI_16(); + uint dst = m68ki_read_16(ea); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_addi_16_pd(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AY_PD_16(); + uint dst = m68ki_read_16(ea); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_addi_16_di(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AY_DI_16(); + uint dst = m68ki_read_16(ea); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_addi_16_ix(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AY_IX_16(); + uint dst = m68ki_read_16(ea); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_addi_16_aw(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AW_16(); + uint dst = m68ki_read_16(ea); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_addi_16_al(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AL_16(); + uint dst = m68ki_read_16(ea); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_addi_32_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint src = OPER_I_32(); + uint dst = *r_dst; + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +void m68k_op_addi_32_ai(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AY_AI_32(); + uint dst = m68ki_read_32(ea); + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_addi_32_pi(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AY_PI_32(); + uint dst = m68ki_read_32(ea); + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_addi_32_pd(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AY_PD_32(); + uint dst = m68ki_read_32(ea); + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_addi_32_di(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AY_DI_32(); + uint dst = m68ki_read_32(ea); + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_addi_32_ix(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AY_IX_32(); + uint dst = m68ki_read_32(ea); + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_addi_32_aw(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AW_32(); + uint dst = m68ki_read_32(ea); + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_addi_32_al(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AL_32(); + uint dst = m68ki_read_32(ea); + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_addq_8_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_addq_8_ai(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AY_AI_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_addq_8_pi(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AY_PI_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_addq_8_pi7(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_A7_PI_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_addq_8_pd(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AY_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_addq_8_pd7(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_addq_8_di(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AY_DI_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_addq_8_ix(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AY_IX_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_addq_8_aw(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AW_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_addq_8_al(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AL_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_addq_16_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +void m68k_op_addq_16_a(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AY; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + (((REG_IR >> 9) - 1) & 7) + 1); +} + + +void m68k_op_addq_16_ai(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AY_AI_16(); + uint dst = m68ki_read_16(ea); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_addq_16_pi(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AY_PI_16(); + uint dst = m68ki_read_16(ea); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_addq_16_pd(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AY_PD_16(); + uint dst = m68ki_read_16(ea); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_addq_16_di(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AY_DI_16(); + uint dst = m68ki_read_16(ea); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_addq_16_ix(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AY_IX_16(); + uint dst = m68ki_read_16(ea); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_addq_16_aw(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AW_16(); + uint dst = m68ki_read_16(ea); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_addq_16_al(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AL_16(); + uint dst = m68ki_read_16(ea); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_addq_32_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint dst = *r_dst; + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +void m68k_op_addq_32_a(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AY; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + (((REG_IR >> 9) - 1) & 7) + 1); +} + + +void m68k_op_addq_32_ai(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AY_AI_32(); + uint dst = m68ki_read_32(ea); + uint res = src + dst; + + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_addq_32_pi(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AY_PI_32(); + uint dst = m68ki_read_32(ea); + uint res = src + dst; + + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_addq_32_pd(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AY_PD_32(); + uint dst = m68ki_read_32(ea); + uint res = src + dst; + + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_addq_32_di(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AY_DI_32(); + uint dst = m68ki_read_32(ea); + uint res = src + dst; + + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_addq_32_ix(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AY_IX_32(); + uint dst = m68ki_read_32(ea); + uint res = src + dst; + + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_addq_32_aw(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AW_32(); + uint dst = m68ki_read_32(ea); + uint res = src + dst; + + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_addq_32_al(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AL_32(); + uint dst = m68ki_read_32(ea); + uint res = src + dst; + + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_addx_8_rr(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_8(DY); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; +} + + +void m68k_op_addx_16_rr(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_16(DY); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + + res = MASK_OUT_ABOVE_16(res); + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; +} + + +void m68k_op_addx_32_rr(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = DY; + uint dst = *r_dst; + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + + res = MASK_OUT_ABOVE_32(res); + FLAG_Z |= res; + + *r_dst = res; +} + + +void m68k_op_addx_8_mm_ax7(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_PD_8(cpu); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +void m68k_op_addx_8_mm_ay7(m68ki_cpu_core *cpu) +{ + uint src = OPER_A7_PD_8(cpu); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +void m68k_op_addx_8_mm_axy7(m68ki_cpu_core *cpu) +{ + uint src = OPER_A7_PD_8(cpu); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +void m68k_op_addx_8_mm(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_PD_8(cpu); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +void m68k_op_addx_16_mm(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_PD_16(cpu); + uint ea = EA_AX_PD_16(); + uint dst = m68ki_read_16(ea); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + + res = MASK_OUT_ABOVE_16(res); + FLAG_Z |= res; + + m68ki_write_16(ea, res); +} + + +void m68k_op_addx_32_mm(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_PD_32(cpu); + uint ea = EA_AX_PD_32(); + uint dst = m68ki_read_32(ea); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + + res = MASK_OUT_ABOVE_32(res); + FLAG_Z |= res; + + m68ki_write_32(ea, res); +} + + +void m68k_op_and_8_er_d(m68ki_cpu_core *cpu) +{ + FLAG_Z = MASK_OUT_ABOVE_8(DX &= (DY | 0xffffff00)); + + FLAG_N = NFLAG_8(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_8_er_ai(m68ki_cpu_core *cpu) +{ + FLAG_Z = MASK_OUT_ABOVE_8(DX &= (OPER_AY_AI_8(cpu) | 0xffffff00)); + + FLAG_N = NFLAG_8(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_8_er_pi(m68ki_cpu_core *cpu) +{ + FLAG_Z = MASK_OUT_ABOVE_8(DX &= (OPER_AY_PI_8(cpu) | 0xffffff00)); + + FLAG_N = NFLAG_8(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_8_er_pi7(m68ki_cpu_core *cpu) +{ + FLAG_Z = MASK_OUT_ABOVE_8(DX &= (OPER_A7_PI_8(cpu) | 0xffffff00)); + + FLAG_N = NFLAG_8(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_8_er_pd(m68ki_cpu_core *cpu) +{ + FLAG_Z = MASK_OUT_ABOVE_8(DX &= (OPER_AY_PD_8(cpu) | 0xffffff00)); + + FLAG_N = NFLAG_8(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_8_er_pd7(m68ki_cpu_core *cpu) +{ + FLAG_Z = MASK_OUT_ABOVE_8(DX &= (OPER_A7_PD_8(cpu) | 0xffffff00)); + + FLAG_N = NFLAG_8(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_8_er_di(m68ki_cpu_core *cpu) +{ + FLAG_Z = MASK_OUT_ABOVE_8(DX &= (OPER_AY_DI_8(cpu) | 0xffffff00)); + + FLAG_N = NFLAG_8(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_8_er_ix(m68ki_cpu_core *cpu) +{ + FLAG_Z = MASK_OUT_ABOVE_8(DX &= (OPER_AY_IX_8(cpu) | 0xffffff00)); + + FLAG_N = NFLAG_8(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_8_er_aw(m68ki_cpu_core *cpu) +{ + FLAG_Z = MASK_OUT_ABOVE_8(DX &= (OPER_AW_8(cpu) | 0xffffff00)); + + FLAG_N = NFLAG_8(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_8_er_al(m68ki_cpu_core *cpu) +{ + FLAG_Z = MASK_OUT_ABOVE_8(DX &= (OPER_AL_8(cpu) | 0xffffff00)); + + FLAG_N = NFLAG_8(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_8_er_pcdi(m68ki_cpu_core *cpu) +{ + FLAG_Z = MASK_OUT_ABOVE_8(DX &= (OPER_PCDI_8(cpu) | 0xffffff00)); + + FLAG_N = NFLAG_8(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_8_er_pcix(m68ki_cpu_core *cpu) +{ + FLAG_Z = MASK_OUT_ABOVE_8(DX &= (OPER_PCIX_8(cpu) | 0xffffff00)); + + FLAG_N = NFLAG_8(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_8_er_i(m68ki_cpu_core *cpu) +{ + FLAG_Z = MASK_OUT_ABOVE_8(DX &= (OPER_I_8() | 0xffffff00)); + + FLAG_N = NFLAG_8(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_16_er_d(m68ki_cpu_core *cpu) +{ + FLAG_Z = MASK_OUT_ABOVE_16(DX &= (DY | 0xffff0000)); + + FLAG_N = NFLAG_16(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_16_er_ai(m68ki_cpu_core *cpu) +{ + FLAG_Z = MASK_OUT_ABOVE_16(DX &= (OPER_AY_AI_16(cpu) | 0xffff0000)); + + FLAG_N = NFLAG_16(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_16_er_pi(m68ki_cpu_core *cpu) +{ + FLAG_Z = MASK_OUT_ABOVE_16(DX &= (OPER_AY_PI_16(cpu) | 0xffff0000)); + + FLAG_N = NFLAG_16(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_16_er_pd(m68ki_cpu_core *cpu) +{ + FLAG_Z = MASK_OUT_ABOVE_16(DX &= (OPER_AY_PD_16(cpu) | 0xffff0000)); + + FLAG_N = NFLAG_16(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_16_er_di(m68ki_cpu_core *cpu) +{ + FLAG_Z = MASK_OUT_ABOVE_16(DX &= (OPER_AY_DI_16(cpu) | 0xffff0000)); + + FLAG_N = NFLAG_16(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_16_er_ix(m68ki_cpu_core *cpu) +{ + FLAG_Z = MASK_OUT_ABOVE_16(DX &= (OPER_AY_IX_16(cpu) | 0xffff0000)); + + FLAG_N = NFLAG_16(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_16_er_aw(m68ki_cpu_core *cpu) +{ + FLAG_Z = MASK_OUT_ABOVE_16(DX &= (OPER_AW_16(cpu) | 0xffff0000)); + + FLAG_N = NFLAG_16(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_16_er_al(m68ki_cpu_core *cpu) +{ + FLAG_Z = MASK_OUT_ABOVE_16(DX &= (OPER_AL_16(cpu) | 0xffff0000)); + + FLAG_N = NFLAG_16(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_16_er_pcdi(m68ki_cpu_core *cpu) +{ + FLAG_Z = MASK_OUT_ABOVE_16(DX &= (OPER_PCDI_16(cpu) | 0xffff0000)); + + FLAG_N = NFLAG_16(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_16_er_pcix(m68ki_cpu_core *cpu) +{ + FLAG_Z = MASK_OUT_ABOVE_16(DX &= (OPER_PCIX_16(cpu) | 0xffff0000)); + + FLAG_N = NFLAG_16(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_16_er_i(m68ki_cpu_core *cpu) +{ + FLAG_Z = MASK_OUT_ABOVE_16(DX &= (OPER_I_16() | 0xffff0000)); + + FLAG_N = NFLAG_16(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_32_er_d(m68ki_cpu_core *cpu) +{ + FLAG_Z = DX &= DY; + + FLAG_N = NFLAG_32(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_32_er_ai(m68ki_cpu_core *cpu) +{ + FLAG_Z = DX &= OPER_AY_AI_32(cpu); + + FLAG_N = NFLAG_32(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_32_er_pi(m68ki_cpu_core *cpu) +{ + FLAG_Z = DX &= OPER_AY_PI_32(cpu); + + FLAG_N = NFLAG_32(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_32_er_pd(m68ki_cpu_core *cpu) +{ + FLAG_Z = DX &= OPER_AY_PD_32(cpu); + + FLAG_N = NFLAG_32(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_32_er_di(m68ki_cpu_core *cpu) +{ + FLAG_Z = DX &= OPER_AY_DI_32(cpu); + + FLAG_N = NFLAG_32(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_32_er_ix(m68ki_cpu_core *cpu) +{ + FLAG_Z = DX &= OPER_AY_IX_32(cpu); + + FLAG_N = NFLAG_32(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_32_er_aw(m68ki_cpu_core *cpu) +{ + FLAG_Z = DX &= OPER_AW_32(cpu); + + FLAG_N = NFLAG_32(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_32_er_al(m68ki_cpu_core *cpu) +{ + FLAG_Z = DX &= OPER_AL_32(cpu); + + FLAG_N = NFLAG_32(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_32_er_pcdi(m68ki_cpu_core *cpu) +{ + FLAG_Z = DX &= OPER_PCDI_32(cpu); + + FLAG_N = NFLAG_32(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_32_er_pcix(m68ki_cpu_core *cpu) +{ + FLAG_Z = DX &= OPER_PCIX_32(cpu); + + FLAG_N = NFLAG_32(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_32_er_i(m68ki_cpu_core *cpu) +{ + FLAG_Z = DX &= OPER_I_32(); + + FLAG_N = NFLAG_32(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_and_8_re_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_8(); + uint res = DX & m68ki_read_8(ea); + + FLAG_N = NFLAG_8(res); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_and_8_re_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_8(); + uint res = DX & m68ki_read_8(ea); + + FLAG_N = NFLAG_8(res); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_and_8_re_pi7(m68ki_cpu_core *cpu) +{ + uint ea = EA_A7_PI_8(); + uint res = DX & m68ki_read_8(ea); + + FLAG_N = NFLAG_8(res); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_and_8_re_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_8(); + uint res = DX & m68ki_read_8(ea); + + FLAG_N = NFLAG_8(res); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_and_8_re_pd7(m68ki_cpu_core *cpu) +{ + uint ea = EA_A7_PD_8(); + uint res = DX & m68ki_read_8(ea); + + FLAG_N = NFLAG_8(res); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_and_8_re_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_8(); + uint res = DX & m68ki_read_8(ea); + + FLAG_N = NFLAG_8(res); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_and_8_re_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_8(); + uint res = DX & m68ki_read_8(ea); + + FLAG_N = NFLAG_8(res); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_and_8_re_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_8(); + uint res = DX & m68ki_read_8(ea); + + FLAG_N = NFLAG_8(res); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_and_8_re_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_8(); + uint res = DX & m68ki_read_8(ea); + + FLAG_N = NFLAG_8(res); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_and_16_re_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_16(); + uint res = DX & m68ki_read_16(ea); + + FLAG_N = NFLAG_16(res); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_and_16_re_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_16(); + uint res = DX & m68ki_read_16(ea); + + FLAG_N = NFLAG_16(res); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_and_16_re_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_16(); + uint res = DX & m68ki_read_16(ea); + + FLAG_N = NFLAG_16(res); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_and_16_re_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_16(); + uint res = DX & m68ki_read_16(ea); + + FLAG_N = NFLAG_16(res); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_and_16_re_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_16(); + uint res = DX & m68ki_read_16(ea); + + FLAG_N = NFLAG_16(res); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_and_16_re_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_16(); + uint res = DX & m68ki_read_16(ea); + + FLAG_N = NFLAG_16(res); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_and_16_re_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_16(); + uint res = DX & m68ki_read_16(ea); + + FLAG_N = NFLAG_16(res); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_and_32_re_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_32(); + uint res = DX & m68ki_read_32(ea); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_32(ea, res); +} + + +void m68k_op_and_32_re_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_32(); + uint res = DX & m68ki_read_32(ea); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_32(ea, res); +} + + +void m68k_op_and_32_re_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_32(); + uint res = DX & m68ki_read_32(ea); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_32(ea, res); +} + + +void m68k_op_and_32_re_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_32(); + uint res = DX & m68ki_read_32(ea); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_32(ea, res); +} + + +void m68k_op_and_32_re_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_32(); + uint res = DX & m68ki_read_32(ea); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_32(ea, res); +} + + +void m68k_op_and_32_re_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_32(); + uint res = DX & m68ki_read_32(ea); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_32(ea, res); +} + + +void m68k_op_and_32_re_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_32(); + uint res = DX & m68ki_read_32(ea); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_32(ea, res); +} + + +void m68k_op_andi_8_d(m68ki_cpu_core *cpu) +{ + FLAG_Z = MASK_OUT_ABOVE_8(DY &= (OPER_I_8() | 0xffffff00)); + + FLAG_N = NFLAG_8(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_andi_8_ai(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AY_AI_8(); + uint res = src & m68ki_read_8(ea); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_8(ea, res); +} + + +void m68k_op_andi_8_pi(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AY_PI_8(); + uint res = src & m68ki_read_8(ea); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_8(ea, res); +} + + +void m68k_op_andi_8_pi7(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_A7_PI_8(); + uint res = src & m68ki_read_8(ea); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_8(ea, res); +} + + +void m68k_op_andi_8_pd(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AY_PD_8(); + uint res = src & m68ki_read_8(ea); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_8(ea, res); +} + + +void m68k_op_andi_8_pd7(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_A7_PD_8(); + uint res = src & m68ki_read_8(ea); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_8(ea, res); +} + + +void m68k_op_andi_8_di(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AY_DI_8(); + uint res = src & m68ki_read_8(ea); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_8(ea, res); +} + + +void m68k_op_andi_8_ix(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AY_IX_8(); + uint res = src & m68ki_read_8(ea); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_8(ea, res); +} + + +void m68k_op_andi_8_aw(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AW_8(); + uint res = src & m68ki_read_8(ea); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_8(ea, res); +} + + +void m68k_op_andi_8_al(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AL_8(); + uint res = src & m68ki_read_8(ea); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_8(ea, res); +} + + +void m68k_op_andi_16_d(m68ki_cpu_core *cpu) +{ + FLAG_Z = MASK_OUT_ABOVE_16(DY &= (OPER_I_16() | 0xffff0000)); + + FLAG_N = NFLAG_16(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_andi_16_ai(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AY_AI_16(); + uint res = src & m68ki_read_16(ea); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_16(ea, res); +} + + +void m68k_op_andi_16_pi(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AY_PI_16(); + uint res = src & m68ki_read_16(ea); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_16(ea, res); +} + + +void m68k_op_andi_16_pd(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AY_PD_16(); + uint res = src & m68ki_read_16(ea); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_16(ea, res); +} + + +void m68k_op_andi_16_di(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AY_DI_16(); + uint res = src & m68ki_read_16(ea); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_16(ea, res); +} + + +void m68k_op_andi_16_ix(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AY_IX_16(); + uint res = src & m68ki_read_16(ea); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_16(ea, res); +} + + +void m68k_op_andi_16_aw(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AW_16(); + uint res = src & m68ki_read_16(ea); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_16(ea, res); +} + + +void m68k_op_andi_16_al(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AL_16(); + uint res = src & m68ki_read_16(ea); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_16(ea, res); +} + + +void m68k_op_andi_32_d(m68ki_cpu_core *cpu) +{ + FLAG_Z = DY &= (OPER_I_32()); + + FLAG_N = NFLAG_32(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_andi_32_ai(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AY_AI_32(); + uint res = src & m68ki_read_32(ea); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_32(ea, res); +} + + +void m68k_op_andi_32_pi(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AY_PI_32(); + uint res = src & m68ki_read_32(ea); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_32(ea, res); +} + + +void m68k_op_andi_32_pd(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AY_PD_32(); + uint res = src & m68ki_read_32(ea); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_32(ea, res); +} + + +void m68k_op_andi_32_di(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AY_DI_32(); + uint res = src & m68ki_read_32(ea); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_32(ea, res); +} + + +void m68k_op_andi_32_ix(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AY_IX_32(); + uint res = src & m68ki_read_32(ea); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_32(ea, res); +} + + +void m68k_op_andi_32_aw(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AW_32(); + uint res = src & m68ki_read_32(ea); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_32(ea, res); +} + + +void m68k_op_andi_32_al(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AL_32(); + uint res = src & m68ki_read_32(ea); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_32(ea, res); +} + + +void m68k_op_andi_16_toc(m68ki_cpu_core *cpu) +{ + m68ki_set_ccr(cpu, m68ki_get_ccr() & OPER_I_16()); +} + + +void m68k_op_andi_16_tos(m68ki_cpu_core *cpu) +{ + if(FLAG_S) + { + uint src = OPER_I_16(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_set_sr(cpu, m68ki_get_sr() & src); + return; + } + m68ki_exception_privilege_violation(cpu); +} + + +void m68k_op_asr_8_s(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = src >> shift; + + if(GET_MSB_8(src)) + res |= m68ki_shift_8_table[shift]; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_X = FLAG_C = src << (9-shift); +} + + +void m68k_op_asr_16_s(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = src >> shift; + + if(GET_MSB_16(src)) + res |= m68ki_shift_16_table[shift]; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_X = FLAG_C = src << (9-shift); +} + + +void m68k_op_asr_32_s(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = *r_dst; + uint res = src >> shift; + + if(GET_MSB_32(src)) + res |= m68ki_shift_32_table[shift]; + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_X = FLAG_C = src << (9-shift); +} + + +void m68k_op_asr_8_r(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = src >> shift; + + if(shift != 0) + { + USE_CYCLES(shift<<CYC_SHIFT); + + if(shift < 8) + { + if(GET_MSB_8(src)) + res |= m68ki_shift_8_table[shift]; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_X = FLAG_C = src << (9-shift); + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + if(GET_MSB_8(src)) + { + *r_dst |= 0xff; + FLAG_C = CFLAG_SET; + FLAG_X = XFLAG_SET; + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + return; + } + + *r_dst &= 0xffffff00; + FLAG_C = CFLAG_CLEAR; + FLAG_X = XFLAG_CLEAR; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_8(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_asr_16_r(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = src >> shift; + + if(shift != 0) + { + USE_CYCLES(shift<<CYC_SHIFT); + + if(shift < 16) + { + if(GET_MSB_16(src)) + res |= m68ki_shift_16_table[shift]; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_C = FLAG_X = (src >> (shift - 1))<<8; + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + if(GET_MSB_16(src)) + { + *r_dst |= 0xffff; + FLAG_C = CFLAG_SET; + FLAG_X = XFLAG_SET; + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + return; + } + + *r_dst &= 0xffff0000; + FLAG_C = CFLAG_CLEAR; + FLAG_X = XFLAG_CLEAR; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_16(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_asr_32_r(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = *r_dst; + uint res = src >> shift; + + if(shift != 0) + { + USE_CYCLES(shift<<CYC_SHIFT); + + if(shift < 32) + { + if(GET_MSB_32(src)) + res |= m68ki_shift_32_table[shift]; + + *r_dst = res; + + FLAG_C = FLAG_X = (src >> (shift - 1))<<8; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + if(GET_MSB_32(src)) + { + *r_dst = 0xffffffff; + FLAG_C = CFLAG_SET; + FLAG_X = XFLAG_SET; + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + return; + } + + *r_dst = 0; + FLAG_C = CFLAG_CLEAR; + FLAG_X = XFLAG_CLEAR; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_32(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_asr_16_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_16(); + uint src = m68ki_read_16(ea); + uint res = src >> 1; + + if(GET_MSB_16(src)) + res |= 0x8000; + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = FLAG_X = src << 8; +} + + +void m68k_op_asr_16_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_16(); + uint src = m68ki_read_16(ea); + uint res = src >> 1; + + if(GET_MSB_16(src)) + res |= 0x8000; + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = FLAG_X = src << 8; +} + + +void m68k_op_asr_16_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_16(); + uint src = m68ki_read_16(ea); + uint res = src >> 1; + + if(GET_MSB_16(src)) + res |= 0x8000; + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = FLAG_X = src << 8; +} + + +void m68k_op_asr_16_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_16(); + uint src = m68ki_read_16(ea); + uint res = src >> 1; + + if(GET_MSB_16(src)) + res |= 0x8000; + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = FLAG_X = src << 8; +} + + +void m68k_op_asr_16_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_16(); + uint src = m68ki_read_16(ea); + uint res = src >> 1; + + if(GET_MSB_16(src)) + res |= 0x8000; + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = FLAG_X = src << 8; +} + + +void m68k_op_asr_16_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_16(); + uint src = m68ki_read_16(ea); + uint res = src >> 1; + + if(GET_MSB_16(src)) + res |= 0x8000; + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = FLAG_X = src << 8; +} + + +void m68k_op_asr_16_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_16(); + uint src = m68ki_read_16(ea); + uint res = src >> 1; + + if(GET_MSB_16(src)) + res |= 0x8000; + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = FLAG_X = src << 8; +} + + +void m68k_op_asl_8_s(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = MASK_OUT_ABOVE_8(src << shift); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_X = FLAG_C = src << shift; + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + src &= m68ki_shift_8_table[shift + 1]; + FLAG_V = (!(src == 0 || (src == m68ki_shift_8_table[shift + 1] && shift < 8)))<<7; +} + + +void m68k_op_asl_16_s(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = MASK_OUT_ABOVE_16(src << shift); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_X = FLAG_C = src >> (8-shift); + src &= m68ki_shift_16_table[shift + 1]; + FLAG_V = (!(src == 0 || src == m68ki_shift_16_table[shift + 1]))<<7; +} + + +void m68k_op_asl_32_s(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32(src << shift); + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_X = FLAG_C = src >> (24-shift); + src &= m68ki_shift_32_table[shift + 1]; + FLAG_V = (!(src == 0 || src == m68ki_shift_32_table[shift + 1]))<<7; +} + + +void m68k_op_asl_8_r(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = MASK_OUT_ABOVE_8(src << shift); + + if(shift != 0) + { + USE_CYCLES(shift<<CYC_SHIFT); + + if(shift < 8) + { + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + FLAG_X = FLAG_C = src << shift; + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + src &= m68ki_shift_8_table[shift + 1]; + FLAG_V = (!(src == 0 || src == m68ki_shift_8_table[shift + 1]))<<7; + return; + } + + *r_dst &= 0xffffff00; + FLAG_X = FLAG_C = ((shift == 8 ? src & 1 : 0))<<8; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = (!(src == 0))<<7; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_8(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_asl_16_r(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = MASK_OUT_ABOVE_16(src << shift); + + if(shift != 0) + { + USE_CYCLES(shift<<CYC_SHIFT); + + if(shift < 16) + { + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + FLAG_X = FLAG_C = (src << shift) >> 8; + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + src &= m68ki_shift_16_table[shift + 1]; + FLAG_V = (!(src == 0 || src == m68ki_shift_16_table[shift + 1]))<<7; + return; + } + + *r_dst &= 0xffff0000; + FLAG_X = FLAG_C = ((shift == 16 ? src & 1 : 0))<<8; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = (!(src == 0))<<7; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_16(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_asl_32_r(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32(src << shift); + + if(shift != 0) + { + USE_CYCLES(shift<<CYC_SHIFT); + + if(shift < 32) + { + *r_dst = res; + FLAG_X = FLAG_C = (src >> (32 - shift)) << 8; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + src &= m68ki_shift_32_table[shift + 1]; + FLAG_V = (!(src == 0 || src == m68ki_shift_32_table[shift + 1]))<<7; + return; + } + + *r_dst = 0; + FLAG_X = FLAG_C = ((shift == 32 ? src & 1 : 0))<<8; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = (!(src == 0))<<7; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_32(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_asl_16_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_16(); + uint src = m68ki_read_16(ea); + uint res = MASK_OUT_ABOVE_16(src << 1); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_X = FLAG_C = src >> 7; + src &= 0xc000; + FLAG_V = (!(src == 0 || src == 0xc000))<<7; +} + + +void m68k_op_asl_16_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_16(); + uint src = m68ki_read_16(ea); + uint res = MASK_OUT_ABOVE_16(src << 1); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_X = FLAG_C = src >> 7; + src &= 0xc000; + FLAG_V = (!(src == 0 || src == 0xc000))<<7; +} + + +void m68k_op_asl_16_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_16(); + uint src = m68ki_read_16(ea); + uint res = MASK_OUT_ABOVE_16(src << 1); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_X = FLAG_C = src >> 7; + src &= 0xc000; + FLAG_V = (!(src == 0 || src == 0xc000))<<7; +} + + +void m68k_op_asl_16_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_16(); + uint src = m68ki_read_16(ea); + uint res = MASK_OUT_ABOVE_16(src << 1); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_X = FLAG_C = src >> 7; + src &= 0xc000; + FLAG_V = (!(src == 0 || src == 0xc000))<<7; +} + + +void m68k_op_asl_16_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_16(); + uint src = m68ki_read_16(ea); + uint res = MASK_OUT_ABOVE_16(src << 1); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_X = FLAG_C = src >> 7; + src &= 0xc000; + FLAG_V = (!(src == 0 || src == 0xc000))<<7; +} + + +void m68k_op_asl_16_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_16(); + uint src = m68ki_read_16(ea); + uint res = MASK_OUT_ABOVE_16(src << 1); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_X = FLAG_C = src >> 7; + src &= 0xc000; + FLAG_V = (!(src == 0 || src == 0xc000))<<7; +} + + +void m68k_op_asl_16_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_16(); + uint src = m68ki_read_16(ea); + uint res = MASK_OUT_ABOVE_16(src << 1); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_X = FLAG_C = src >> 7; + src &= 0xc000; + FLAG_V = (!(src == 0 || src == 0xc000))<<7; +} + + +void m68k_op_bhi_8(m68ki_cpu_core *cpu) +{ + if(COND_HI()) + { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_8(cpu, MASK_OUT_ABOVE_8(REG_IR)); + return; + } + USE_CYCLES(CYC_BCC_NOTAKE_B); +} + + +void m68k_op_bls_8(m68ki_cpu_core *cpu) +{ + if(COND_LS()) + { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_8(cpu, MASK_OUT_ABOVE_8(REG_IR)); + return; + } + USE_CYCLES(CYC_BCC_NOTAKE_B); +} + + +void m68k_op_bcc_8(m68ki_cpu_core *cpu) +{ + if(COND_CC()) + { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_8(cpu, MASK_OUT_ABOVE_8(REG_IR)); + return; + } + USE_CYCLES(CYC_BCC_NOTAKE_B); +} + + +void m68k_op_bcs_8(m68ki_cpu_core *cpu) +{ + if(COND_CS()) + { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_8(cpu, MASK_OUT_ABOVE_8(REG_IR)); + return; + } + USE_CYCLES(CYC_BCC_NOTAKE_B); +} + + +void m68k_op_bne_8(m68ki_cpu_core *cpu) +{ + if(COND_NE()) + { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_8(cpu, MASK_OUT_ABOVE_8(REG_IR)); + return; + } + USE_CYCLES(CYC_BCC_NOTAKE_B); +} + + +void m68k_op_beq_8(m68ki_cpu_core *cpu) +{ + if(COND_EQ()) + { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_8(cpu, MASK_OUT_ABOVE_8(REG_IR)); + return; + } + USE_CYCLES(CYC_BCC_NOTAKE_B); +} + + +void m68k_op_bvc_8(m68ki_cpu_core *cpu) +{ + if(COND_VC()) + { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_8(cpu, MASK_OUT_ABOVE_8(REG_IR)); + return; + } + USE_CYCLES(CYC_BCC_NOTAKE_B); +} + + +void m68k_op_bvs_8(m68ki_cpu_core *cpu) +{ + if(COND_VS()) + { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_8(cpu, MASK_OUT_ABOVE_8(REG_IR)); + return; + } + USE_CYCLES(CYC_BCC_NOTAKE_B); +} + + +void m68k_op_bpl_8(m68ki_cpu_core *cpu) +{ + if(COND_PL()) + { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_8(cpu, MASK_OUT_ABOVE_8(REG_IR)); + return; + } + USE_CYCLES(CYC_BCC_NOTAKE_B); +} + + +void m68k_op_bmi_8(m68ki_cpu_core *cpu) +{ + if(COND_MI()) + { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_8(cpu, MASK_OUT_ABOVE_8(REG_IR)); + return; + } + USE_CYCLES(CYC_BCC_NOTAKE_B); +} + + +void m68k_op_bge_8(m68ki_cpu_core *cpu) +{ + if(COND_GE()) + { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_8(cpu, MASK_OUT_ABOVE_8(REG_IR)); + return; + } + USE_CYCLES(CYC_BCC_NOTAKE_B); +} + + +void m68k_op_blt_8(m68ki_cpu_core *cpu) +{ + if(COND_LT()) + { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_8(cpu, MASK_OUT_ABOVE_8(REG_IR)); + return; + } + USE_CYCLES(CYC_BCC_NOTAKE_B); +} + + +void m68k_op_bgt_8(m68ki_cpu_core *cpu) +{ + if(COND_GT()) + { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_8(cpu, MASK_OUT_ABOVE_8(REG_IR)); + return; + } + USE_CYCLES(CYC_BCC_NOTAKE_B); +} + + +void m68k_op_ble_8(m68ki_cpu_core *cpu) +{ + if(COND_LE()) + { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_8(cpu, MASK_OUT_ABOVE_8(REG_IR)); + return; + } + USE_CYCLES(CYC_BCC_NOTAKE_B); +} + + +void m68k_op_bhi_16(m68ki_cpu_core *cpu) +{ + if(COND_HI()) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(cpu, offset); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_BCC_NOTAKE_W); +} + + +void m68k_op_bls_16(m68ki_cpu_core *cpu) +{ + if(COND_LS()) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(cpu, offset); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_BCC_NOTAKE_W); +} + + +void m68k_op_bcc_16(m68ki_cpu_core *cpu) +{ + if(COND_CC()) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(cpu, offset); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_BCC_NOTAKE_W); +} + + +void m68k_op_bcs_16(m68ki_cpu_core *cpu) +{ + if(COND_CS()) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(cpu, offset); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_BCC_NOTAKE_W); +} + + +void m68k_op_bne_16(m68ki_cpu_core *cpu) +{ + if(COND_NE()) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(cpu, offset); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_BCC_NOTAKE_W); +} + + +void m68k_op_beq_16(m68ki_cpu_core *cpu) +{ + if(COND_EQ()) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(cpu, offset); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_BCC_NOTAKE_W); +} + + +void m68k_op_bvc_16(m68ki_cpu_core *cpu) +{ + if(COND_VC()) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(cpu, offset); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_BCC_NOTAKE_W); +} + + +void m68k_op_bvs_16(m68ki_cpu_core *cpu) +{ + if(COND_VS()) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(cpu, offset); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_BCC_NOTAKE_W); +} + + +void m68k_op_bpl_16(m68ki_cpu_core *cpu) +{ + if(COND_PL()) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(cpu, offset); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_BCC_NOTAKE_W); +} + + +void m68k_op_bmi_16(m68ki_cpu_core *cpu) +{ + if(COND_MI()) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(cpu, offset); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_BCC_NOTAKE_W); +} + + +void m68k_op_bge_16(m68ki_cpu_core *cpu) +{ + if(COND_GE()) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(cpu, offset); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_BCC_NOTAKE_W); +} + + +void m68k_op_blt_16(m68ki_cpu_core *cpu) +{ + if(COND_LT()) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(cpu, offset); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_BCC_NOTAKE_W); +} + + +void m68k_op_bgt_16(m68ki_cpu_core *cpu) +{ + if(COND_GT()) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(cpu, offset); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_BCC_NOTAKE_W); +} + + +void m68k_op_ble_16(m68ki_cpu_core *cpu) +{ + if(COND_LE()) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(cpu, offset); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_BCC_NOTAKE_W); +} + + +void m68k_op_bhi_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_HI()) + { + uint offset = OPER_I_32(); + REG_PC -= 4; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_32(cpu, offset); + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bls_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_LS()) + { + uint offset = OPER_I_32(); + REG_PC -= 4; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_32(cpu, offset); + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bcc_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_CC()) + { + uint offset = OPER_I_32(); + REG_PC -= 4; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_32(cpu, offset); + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bcs_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_CS()) + { + uint offset = OPER_I_32(); + REG_PC -= 4; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_32(cpu, offset); + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bne_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_NE()) + { + uint offset = OPER_I_32(); + REG_PC -= 4; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_32(cpu, offset); + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_beq_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_EQ()) + { + uint offset = OPER_I_32(); + REG_PC -= 4; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_32(cpu, offset); + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bvc_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_VC()) + { + uint offset = OPER_I_32(); + REG_PC -= 4; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_32(cpu, offset); + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bvs_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_VS()) + { + uint offset = OPER_I_32(); + REG_PC -= 4; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_32(cpu, offset); + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bpl_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_PL()) + { + uint offset = OPER_I_32(); + REG_PC -= 4; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_32(cpu, offset); + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bmi_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_MI()) + { + uint offset = OPER_I_32(); + REG_PC -= 4; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_32(cpu, offset); + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bge_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_GE()) + { + uint offset = OPER_I_32(); + REG_PC -= 4; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_32(cpu, offset); + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_blt_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_LT()) + { + uint offset = OPER_I_32(); + REG_PC -= 4; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_32(cpu, offset); + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bgt_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_GT()) + { + uint offset = OPER_I_32(); + REG_PC -= 4; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_32(cpu, offset); + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_ble_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_LE()) + { + uint offset = OPER_I_32(); + REG_PC -= 4; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_32(cpu, offset); + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bchg_32_r_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint mask = 1 << (DX & 0x1f); + + FLAG_Z = *r_dst & mask; + *r_dst ^= mask; +} + + +void m68k_op_bchg_8_r_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_8(); + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src ^ mask); +} + + +void m68k_op_bchg_8_r_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_8(); + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src ^ mask); +} + + +void m68k_op_bchg_8_r_pi7(m68ki_cpu_core *cpu) +{ + uint ea = EA_A7_PI_8(); + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src ^ mask); +} + + +void m68k_op_bchg_8_r_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_8(); + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src ^ mask); +} + + +void m68k_op_bchg_8_r_pd7(m68ki_cpu_core *cpu) +{ + uint ea = EA_A7_PD_8(); + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src ^ mask); +} + + +void m68k_op_bchg_8_r_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_8(); + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src ^ mask); +} + + +void m68k_op_bchg_8_r_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_8(); + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src ^ mask); +} + + +void m68k_op_bchg_8_r_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_8(); + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src ^ mask); +} + + +void m68k_op_bchg_8_r_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_8(); + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src ^ mask); +} + + +void m68k_op_bchg_32_s_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint mask = 1 << (OPER_I_8() & 0x1f); + + FLAG_Z = *r_dst & mask; + *r_dst ^= mask; +} + + +void m68k_op_bchg_8_s_ai(m68ki_cpu_core *cpu) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = EA_AY_AI_8(); + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src ^ mask); +} + + +void m68k_op_bchg_8_s_pi(m68ki_cpu_core *cpu) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = EA_AY_PI_8(); + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src ^ mask); +} + + +void m68k_op_bchg_8_s_pi7(m68ki_cpu_core *cpu) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = EA_A7_PI_8(); + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src ^ mask); +} + + +void m68k_op_bchg_8_s_pd(m68ki_cpu_core *cpu) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = EA_AY_PD_8(); + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src ^ mask); +} + + +void m68k_op_bchg_8_s_pd7(m68ki_cpu_core *cpu) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = EA_A7_PD_8(); + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src ^ mask); +} + + +void m68k_op_bchg_8_s_di(m68ki_cpu_core *cpu) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = EA_AY_DI_8(); + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src ^ mask); +} + + +void m68k_op_bchg_8_s_ix(m68ki_cpu_core *cpu) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = EA_AY_IX_8(); + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src ^ mask); +} + + +void m68k_op_bchg_8_s_aw(m68ki_cpu_core *cpu) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = EA_AW_8(); + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src ^ mask); +} + + +void m68k_op_bchg_8_s_al(m68ki_cpu_core *cpu) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = EA_AL_8(); + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src ^ mask); +} + + +void m68k_op_bclr_32_r_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint mask = 1 << (DX & 0x1f); + + FLAG_Z = *r_dst & mask; + *r_dst &= ~mask; +} + + +void m68k_op_bclr_8_r_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_8(); + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src & ~mask); +} + + +void m68k_op_bclr_8_r_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_8(); + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src & ~mask); +} + + +void m68k_op_bclr_8_r_pi7(m68ki_cpu_core *cpu) +{ + uint ea = EA_A7_PI_8(); + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src & ~mask); +} + + +void m68k_op_bclr_8_r_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_8(); + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src & ~mask); +} + + +void m68k_op_bclr_8_r_pd7(m68ki_cpu_core *cpu) +{ + uint ea = EA_A7_PD_8(); + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src & ~mask); +} + + +void m68k_op_bclr_8_r_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_8(); + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src & ~mask); +} + + +void m68k_op_bclr_8_r_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_8(); + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src & ~mask); +} + + +void m68k_op_bclr_8_r_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_8(); + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src & ~mask); +} + + +void m68k_op_bclr_8_r_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_8(); + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src & ~mask); +} + + +void m68k_op_bclr_32_s_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint mask = 1 << (OPER_I_8() & 0x1f); + + FLAG_Z = *r_dst & mask; + *r_dst &= ~mask; +} + + +void m68k_op_bclr_8_s_ai(m68ki_cpu_core *cpu) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = EA_AY_AI_8(); + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src & ~mask); +} + + +void m68k_op_bclr_8_s_pi(m68ki_cpu_core *cpu) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = EA_AY_PI_8(); + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src & ~mask); +} + + +void m68k_op_bclr_8_s_pi7(m68ki_cpu_core *cpu) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = EA_A7_PI_8(); + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src & ~mask); +} + + +void m68k_op_bclr_8_s_pd(m68ki_cpu_core *cpu) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = EA_AY_PD_8(); + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src & ~mask); +} + + +void m68k_op_bclr_8_s_pd7(m68ki_cpu_core *cpu) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = EA_A7_PD_8(); + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src & ~mask); +} + + +void m68k_op_bclr_8_s_di(m68ki_cpu_core *cpu) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = EA_AY_DI_8(); + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src & ~mask); +} + + +void m68k_op_bclr_8_s_ix(m68ki_cpu_core *cpu) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = EA_AY_IX_8(); + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src & ~mask); +} + + +void m68k_op_bclr_8_s_aw(m68ki_cpu_core *cpu) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = EA_AW_8(); + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src & ~mask); +} + + +void m68k_op_bclr_8_s_al(m68ki_cpu_core *cpu) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = EA_AL_8(); + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src & ~mask); +} + + +void m68k_op_bfchg_32_d(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint* data = &DY; + uint64 mask; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + offset &= 31; + width = ((width-1) & 31) + 1; + + mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask = ROR_32(mask, offset); + + FLAG_N = NFLAG_32(*data<<offset); + FLAG_Z = *data & mask; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + *data ^= mask; + + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfchg_32_ai(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = EA_AY_AI_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = NFLAG_32(data_long << offset); + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, data_long ^ mask_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, data_byte ^ mask_byte); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfchg_32_di(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = EA_AY_DI_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = NFLAG_32(data_long << offset); + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, data_long ^ mask_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, data_byte ^ mask_byte); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfchg_32_ix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = EA_AY_IX_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = NFLAG_32(data_long << offset); + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, data_long ^ mask_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, data_byte ^ mask_byte); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfchg_32_aw(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = EA_AW_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = NFLAG_32(data_long << offset); + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, data_long ^ mask_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, data_byte ^ mask_byte); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfchg_32_al(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = EA_AL_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = NFLAG_32(data_long << offset); + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, data_long ^ mask_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, data_byte ^ mask_byte); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfclr_32_d(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint* data = &DY; + uint64 mask; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + + offset &= 31; + width = ((width-1) & 31) + 1; + + + mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask = ROR_32(mask, offset); + + FLAG_N = NFLAG_32(*data<<offset); + FLAG_Z = *data & mask; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + *data &= ~mask; + + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfclr_32_ai(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = EA_AY_AI_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = NFLAG_32(data_long << offset); + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, data_long & ~mask_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, data_byte & ~mask_byte); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfclr_32_di(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = EA_AY_DI_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = NFLAG_32(data_long << offset); + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, data_long & ~mask_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, data_byte & ~mask_byte); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfclr_32_ix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = EA_AY_IX_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = NFLAG_32(data_long << offset); + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, data_long & ~mask_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, data_byte & ~mask_byte); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfclr_32_aw(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = EA_AW_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = NFLAG_32(data_long << offset); + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, data_long & ~mask_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, data_byte & ~mask_byte); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfclr_32_al(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = EA_AL_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = NFLAG_32(data_long << offset); + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, data_long & ~mask_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, data_byte & ~mask_byte); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfexts_32_d(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint64 data = DY; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + offset &= 31; + width = ((width-1) & 31) + 1; + + data = ROL_32(data, offset); + FLAG_N = NFLAG_32(data); + data = MAKE_INT_32(data) >> (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + REG_D[(word2>>12)&7] = data; + + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfexts_32_ai(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint data; + uint ea = EA_AY_AI_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + data = m68ki_read_32(ea); + + data = MASK_OUT_ABOVE_32(data<<offset); + + if((offset+width) > 32) + data |= (m68ki_read_8(ea+4) << offset) >> 8; + + FLAG_N = NFLAG_32(data); + data = MAKE_INT_32(data) >> (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + REG_D[(word2 >> 12) & 7] = data; + + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfexts_32_di(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint data; + uint ea = EA_AY_DI_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + data = m68ki_read_32(ea); + + data = MASK_OUT_ABOVE_32(data<<offset); + + if((offset+width) > 32) + data |= (m68ki_read_8(ea+4) << offset) >> 8; + + FLAG_N = NFLAG_32(data); + data = MAKE_INT_32(data) >> (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + REG_D[(word2 >> 12) & 7] = data; + + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfexts_32_ix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint data; + uint ea = EA_AY_IX_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + data = m68ki_read_32(ea); + + data = MASK_OUT_ABOVE_32(data<<offset); + + if((offset+width) > 32) + data |= (m68ki_read_8(ea+4) << offset) >> 8; + + FLAG_N = NFLAG_32(data); + data = MAKE_INT_32(data) >> (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + REG_D[(word2 >> 12) & 7] = data; + + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfexts_32_aw(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint data; + uint ea = EA_AW_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + data = m68ki_read_32(ea); + + data = MASK_OUT_ABOVE_32(data<<offset); + + if((offset+width) > 32) + data |= (m68ki_read_8(ea+4) << offset) >> 8; + + FLAG_N = NFLAG_32(data); + data = MAKE_INT_32(data) >> (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + REG_D[(word2 >> 12) & 7] = data; + + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfexts_32_al(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint data; + uint ea = EA_AL_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + data = m68ki_read_32(ea); + + data = MASK_OUT_ABOVE_32(data<<offset); + + if((offset+width) > 32) + data |= (m68ki_read_8(ea+4) << offset) >> 8; + + FLAG_N = NFLAG_32(data); + data = MAKE_INT_32(data) >> (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + REG_D[(word2 >> 12) & 7] = data; + + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfexts_32_pcdi(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint data; + uint ea = EA_PCDI_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + data = m68ki_read_32(ea); + + data = MASK_OUT_ABOVE_32(data<<offset); + + if((offset+width) > 32) + data |= (m68ki_read_8(ea+4) << offset) >> 8; + + FLAG_N = NFLAG_32(data); + data = MAKE_INT_32(data) >> (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + REG_D[(word2 >> 12) & 7] = data; + + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfexts_32_pcix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint data; + uint ea = EA_PCIX_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + data = m68ki_read_32(ea); + + data = MASK_OUT_ABOVE_32(data<<offset); + + if((offset+width) > 32) + data |= (m68ki_read_8(ea+4) << offset) >> 8; + + FLAG_N = NFLAG_32(data); + data = MAKE_INT_32(data) >> (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + REG_D[(word2 >> 12) & 7] = data; + + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfextu_32_d(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint64 data = DY; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + offset &= 31; + width = ((width-1) & 31) + 1; + + data = ROL_32(data, offset); + FLAG_N = NFLAG_32(data); + data >>= 32 - width; + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + REG_D[(word2>>12)&7] = data; + + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfextu_32_ai(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint data; + uint ea = EA_AY_AI_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + data = m68ki_read_32(ea); + data = MASK_OUT_ABOVE_32(data<<offset); + + if((offset+width) > 32) + data |= (m68ki_read_8(ea+4) << offset) >> 8; + + FLAG_N = NFLAG_32(data); + data >>= (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + REG_D[(word2 >> 12) & 7] = data; + + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfextu_32_di(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint data; + uint ea = EA_AY_DI_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + data = m68ki_read_32(ea); + data = MASK_OUT_ABOVE_32(data<<offset); + + if((offset+width) > 32) + data |= (m68ki_read_8(ea+4) << offset) >> 8; + + FLAG_N = NFLAG_32(data); + data >>= (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + REG_D[(word2 >> 12) & 7] = data; + + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfextu_32_ix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint data; + uint ea = EA_AY_IX_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + data = m68ki_read_32(ea); + data = MASK_OUT_ABOVE_32(data<<offset); + + if((offset+width) > 32) + data |= (m68ki_read_8(ea+4) << offset) >> 8; + + FLAG_N = NFLAG_32(data); + data >>= (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + REG_D[(word2 >> 12) & 7] = data; + + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfextu_32_aw(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint data; + uint ea = EA_AW_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + data = m68ki_read_32(ea); + data = MASK_OUT_ABOVE_32(data<<offset); + + if((offset+width) > 32) + data |= (m68ki_read_8(ea+4) << offset) >> 8; + + FLAG_N = NFLAG_32(data); + data >>= (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + REG_D[(word2 >> 12) & 7] = data; + + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfextu_32_al(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint data; + uint ea = EA_AL_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + data = m68ki_read_32(ea); + data = MASK_OUT_ABOVE_32(data<<offset); + + if((offset+width) > 32) + data |= (m68ki_read_8(ea+4) << offset) >> 8; + + FLAG_N = NFLAG_32(data); + data >>= (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + REG_D[(word2 >> 12) & 7] = data; + + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfextu_32_pcdi(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint data; + uint ea = EA_PCDI_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + data = m68ki_read_32(ea); + data = MASK_OUT_ABOVE_32(data<<offset); + + if((offset+width) > 32) + data |= (m68ki_read_8(ea+4) << offset) >> 8; + + FLAG_N = NFLAG_32(data); + data >>= (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + REG_D[(word2 >> 12) & 7] = data; + + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfextu_32_pcix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint data; + uint ea = EA_PCIX_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + data = m68ki_read_32(ea); + data = MASK_OUT_ABOVE_32(data<<offset); + + if((offset+width) > 32) + data |= (m68ki_read_8(ea+4) << offset) >> 8; + + FLAG_N = NFLAG_32(data); + data >>= (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + REG_D[(word2 >> 12) & 7] = data; + + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfffo_32_d(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint64 data = DY; + uint bit; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + offset &= 31; + width = ((width-1) & 31) + 1; + + data = ROL_32(data, offset); + FLAG_N = NFLAG_32(data); + data >>= 32 - width; + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + for(bit = 1<<(width-1);bit && !(data & bit);bit>>= 1) + offset++; + + REG_D[(word2>>12)&7] = offset; + + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfffo_32_ai(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + sint local_offset; + uint width = word2; + uint data; + uint bit; + uint ea = EA_AY_AI_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + local_offset = offset % 8; + if(local_offset < 0) + { + local_offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + data = m68ki_read_32(ea); + data = MASK_OUT_ABOVE_32(data<<local_offset); + + if((local_offset+width) > 32) + data |= (m68ki_read_8(ea+4) << local_offset) >> 8; + + FLAG_N = NFLAG_32(data); + data >>= (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + for(bit = 1<<(width-1);bit && !(data & bit);bit>>= 1) + offset++; + + REG_D[(word2>>12)&7] = offset; + + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfffo_32_di(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + sint local_offset; + uint width = word2; + uint data; + uint bit; + uint ea = EA_AY_DI_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + local_offset = offset % 8; + if(local_offset < 0) + { + local_offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + data = m68ki_read_32(ea); + data = MASK_OUT_ABOVE_32(data<<local_offset); + + if((local_offset+width) > 32) + data |= (m68ki_read_8(ea+4) << local_offset) >> 8; + + FLAG_N = NFLAG_32(data); + data >>= (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + for(bit = 1<<(width-1);bit && !(data & bit);bit>>= 1) + offset++; + + REG_D[(word2>>12)&7] = offset; + + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfffo_32_ix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + sint local_offset; + uint width = word2; + uint data; + uint bit; + uint ea = EA_AY_IX_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + local_offset = offset % 8; + if(local_offset < 0) + { + local_offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + data = m68ki_read_32(ea); + data = MASK_OUT_ABOVE_32(data<<local_offset); + + if((local_offset+width) > 32) + data |= (m68ki_read_8(ea+4) << local_offset) >> 8; + + FLAG_N = NFLAG_32(data); + data >>= (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + for(bit = 1<<(width-1);bit && !(data & bit);bit>>= 1) + offset++; + + REG_D[(word2>>12)&7] = offset; + + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfffo_32_aw(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + sint local_offset; + uint width = word2; + uint data; + uint bit; + uint ea = EA_AW_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + local_offset = offset % 8; + if(local_offset < 0) + { + local_offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + data = m68ki_read_32(ea); + data = MASK_OUT_ABOVE_32(data<<local_offset); + + if((local_offset+width) > 32) + data |= (m68ki_read_8(ea+4) << local_offset) >> 8; + + FLAG_N = NFLAG_32(data); + data >>= (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + for(bit = 1<<(width-1);bit && !(data & bit);bit>>= 1) + offset++; + + REG_D[(word2>>12)&7] = offset; + + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfffo_32_al(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + sint local_offset; + uint width = word2; + uint data; + uint bit; + uint ea = EA_AL_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + local_offset = offset % 8; + if(local_offset < 0) + { + local_offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + data = m68ki_read_32(ea); + data = MASK_OUT_ABOVE_32(data<<local_offset); + + if((local_offset+width) > 32) + data |= (m68ki_read_8(ea+4) << local_offset) >> 8; + + FLAG_N = NFLAG_32(data); + data >>= (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + for(bit = 1<<(width-1);bit && !(data & bit);bit>>= 1) + offset++; + + REG_D[(word2>>12)&7] = offset; + + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfffo_32_pcdi(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + sint local_offset; + uint width = word2; + uint data; + uint bit; + uint ea = EA_PCDI_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + local_offset = offset % 8; + if(local_offset < 0) + { + local_offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + data = m68ki_read_32(ea); + data = MASK_OUT_ABOVE_32(data<<local_offset); + + if((local_offset+width) > 32) + data |= (m68ki_read_8(ea+4) << local_offset) >> 8; + + FLAG_N = NFLAG_32(data); + data >>= (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + for(bit = 1<<(width-1);bit && !(data & bit);bit>>= 1) + offset++; + + REG_D[(word2>>12)&7] = offset; + + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfffo_32_pcix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + sint local_offset; + uint width = word2; + uint data; + uint bit; + uint ea = EA_PCIX_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + local_offset = offset % 8; + if(local_offset < 0) + { + local_offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + data = m68ki_read_32(ea); + data = MASK_OUT_ABOVE_32(data<<local_offset); + + if((local_offset+width) > 32) + data |= (m68ki_read_8(ea+4) << local_offset) >> 8; + + FLAG_N = NFLAG_32(data); + data >>= (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + for(bit = 1<<(width-1);bit && !(data & bit);bit>>= 1) + offset++; + + REG_D[(word2>>12)&7] = offset; + + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfins_32_d(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint* data = &DY; + uint64 mask; + uint64 insert = REG_D[(word2>>12)&7]; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + + offset &= 31; + width = ((width-1) & 31) + 1; + + + mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask = ROR_32(mask, offset); + + insert = MASK_OUT_ABOVE_32(insert << (32 - width)); + FLAG_N = NFLAG_32(insert); + FLAG_Z = insert; + insert = ROR_32(insert, offset); + + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + *data &= ~mask; + *data |= insert; + + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfins_32_ai(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint insert_base = REG_D[(word2>>12)&7]; + uint insert_long; + uint insert_byte; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = EA_AY_AI_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + insert_base = MASK_OUT_ABOVE_32(insert_base << (32 - width)); + FLAG_N = NFLAG_32(insert_base); + FLAG_Z = insert_base; + insert_long = insert_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, (data_long & ~mask_long) | insert_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + insert_byte = MASK_OUT_ABOVE_8(insert_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, (data_byte & ~mask_byte) | insert_byte); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfins_32_di(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint insert_base = REG_D[(word2>>12)&7]; + uint insert_long; + uint insert_byte; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = EA_AY_DI_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + insert_base = MASK_OUT_ABOVE_32(insert_base << (32 - width)); + FLAG_N = NFLAG_32(insert_base); + FLAG_Z = insert_base; + insert_long = insert_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, (data_long & ~mask_long) | insert_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + insert_byte = MASK_OUT_ABOVE_8(insert_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, (data_byte & ~mask_byte) | insert_byte); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfins_32_ix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint insert_base = REG_D[(word2>>12)&7]; + uint insert_long; + uint insert_byte; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = EA_AY_IX_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + insert_base = MASK_OUT_ABOVE_32(insert_base << (32 - width)); + FLAG_N = NFLAG_32(insert_base); + FLAG_Z = insert_base; + insert_long = insert_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, (data_long & ~mask_long) | insert_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + insert_byte = MASK_OUT_ABOVE_8(insert_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, (data_byte & ~mask_byte) | insert_byte); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfins_32_aw(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint insert_base = REG_D[(word2>>12)&7]; + uint insert_long; + uint insert_byte; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = EA_AW_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + insert_base = MASK_OUT_ABOVE_32(insert_base << (32 - width)); + FLAG_N = NFLAG_32(insert_base); + FLAG_Z = insert_base; + insert_long = insert_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, (data_long & ~mask_long) | insert_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + insert_byte = MASK_OUT_ABOVE_8(insert_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, (data_byte & ~mask_byte) | insert_byte); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfins_32_al(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint insert_base = REG_D[(word2>>12)&7]; + uint insert_long; + uint insert_byte; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = EA_AL_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + insert_base = MASK_OUT_ABOVE_32(insert_base << (32 - width)); + FLAG_N = NFLAG_32(insert_base); + FLAG_Z = insert_base; + insert_long = insert_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, (data_long & ~mask_long) | insert_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + insert_byte = MASK_OUT_ABOVE_8(insert_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, (data_byte & ~mask_byte) | insert_byte); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfset_32_d(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint* data = &DY; + uint64 mask; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + + offset &= 31; + width = ((width-1) & 31) + 1; + + + mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask = ROR_32(mask, offset); + + FLAG_N = NFLAG_32(*data<<offset); + FLAG_Z = *data & mask; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + *data |= mask; + + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfset_32_ai(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = EA_AY_AI_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = NFLAG_32(data_long << offset); + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, data_long | mask_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, data_byte | mask_byte); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfset_32_di(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = EA_AY_DI_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = NFLAG_32(data_long << offset); + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, data_long | mask_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, data_byte | mask_byte); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfset_32_ix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = EA_AY_IX_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = NFLAG_32(data_long << offset); + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, data_long | mask_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, data_byte | mask_byte); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfset_32_aw(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = EA_AW_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = NFLAG_32(data_long << offset); + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, data_long | mask_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, data_byte | mask_byte); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bfset_32_al(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = EA_AL_8(); + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = NFLAG_32(data_long << offset); + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, data_long | mask_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, data_byte | mask_byte); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bftst_32_d(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint* data = &DY; + uint64 mask; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + + offset &= 31; + width = ((width-1) & 31) + 1; + + + mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask = ROR_32(mask, offset); + + FLAG_N = NFLAG_32(*data<<offset); + FLAG_Z = *data & mask; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bftst_32_ai(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = EA_AY_AI_8(); + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = ((data_long & (0x80000000 >> offset))<<offset)>>24; + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bftst_32_di(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = EA_AY_DI_8(); + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = ((data_long & (0x80000000 >> offset))<<offset)>>24; + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bftst_32_ix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = EA_AY_IX_8(); + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = ((data_long & (0x80000000 >> offset))<<offset)>>24; + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bftst_32_aw(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = EA_AW_8(); + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = ((data_long & (0x80000000 >> offset))<<offset)>>24; + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bftst_32_al(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = EA_AL_8(); + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = ((data_long & (0x80000000 >> offset))<<offset)>>24; + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bftst_32_pcdi(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = EA_PCDI_8(); + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = ((data_long & (0x80000000 >> offset))<<offset)>>24; + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bftst_32_pcix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = EA_PCIX_8(); + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = ((data_long & (0x80000000 >> offset))<<offset)>>24; + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bkpt(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + m68ki_bkpt_ack(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE) ? REG_IR & 7 : 0); /* auto-disable (see m68kcpu.h) */ + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bra_8(m68ki_cpu_core *cpu) +{ + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_8(cpu, MASK_OUT_ABOVE_8(REG_IR)); + if(REG_PC == REG_PPC) + USE_ALL_CYCLES(); +} + + +void m68k_op_bra_16(m68ki_cpu_core *cpu) +{ + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(cpu, offset); + if(REG_PC == REG_PPC) + USE_ALL_CYCLES(); +} + + +void m68k_op_bra_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint offset = OPER_I_32(); + REG_PC -= 4; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_32(cpu, offset); + if(REG_PC == REG_PPC) + USE_ALL_CYCLES(); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_bset_32_r_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint mask = 1 << (DX & 0x1f); + + FLAG_Z = *r_dst & mask; + *r_dst |= mask; +} + + +void m68k_op_bset_8_r_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_8(); + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src | mask); +} + + +void m68k_op_bset_8_r_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_8(); + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src | mask); +} + + +void m68k_op_bset_8_r_pi7(m68ki_cpu_core *cpu) +{ + uint ea = EA_A7_PI_8(); + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src | mask); +} + + +void m68k_op_bset_8_r_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_8(); + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src | mask); +} + + +void m68k_op_bset_8_r_pd7(m68ki_cpu_core *cpu) +{ + uint ea = EA_A7_PD_8(); + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src | mask); +} + + +void m68k_op_bset_8_r_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_8(); + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src | mask); +} + + +void m68k_op_bset_8_r_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_8(); + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src | mask); +} + + +void m68k_op_bset_8_r_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_8(); + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src | mask); +} + + +void m68k_op_bset_8_r_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_8(); + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src | mask); +} + + +void m68k_op_bset_32_s_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint mask = 1 << (OPER_I_8() & 0x1f); + + FLAG_Z = *r_dst & mask; + *r_dst |= mask; +} + + +void m68k_op_bset_8_s_ai(m68ki_cpu_core *cpu) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = EA_AY_AI_8(); + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src | mask); +} + + +void m68k_op_bset_8_s_pi(m68ki_cpu_core *cpu) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = EA_AY_PI_8(); + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src | mask); +} + + +void m68k_op_bset_8_s_pi7(m68ki_cpu_core *cpu) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = EA_A7_PI_8(); + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src | mask); +} + + +void m68k_op_bset_8_s_pd(m68ki_cpu_core *cpu) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = EA_AY_PD_8(); + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src | mask); +} + + +void m68k_op_bset_8_s_pd7(m68ki_cpu_core *cpu) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = EA_A7_PD_8(); + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src | mask); +} + + +void m68k_op_bset_8_s_di(m68ki_cpu_core *cpu) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = EA_AY_DI_8(); + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src | mask); +} + + +void m68k_op_bset_8_s_ix(m68ki_cpu_core *cpu) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = EA_AY_IX_8(); + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src | mask); +} + + +void m68k_op_bset_8_s_aw(m68ki_cpu_core *cpu) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = EA_AW_8(); + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src | mask); +} + + +void m68k_op_bset_8_s_al(m68ki_cpu_core *cpu) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = EA_AL_8(); + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src | mask); +} + + +void m68k_op_bsr_8(m68ki_cpu_core *cpu) +{ + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_push_32(cpu, REG_PC); + m68ki_branch_8(cpu, MASK_OUT_ABOVE_8(REG_IR)); +} + + +void m68k_op_bsr_16(m68ki_cpu_core *cpu) +{ + uint offset = OPER_I_16(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_push_32(cpu, REG_PC); + REG_PC -= 2; + m68ki_branch_16(cpu, offset); +} + + +void m68k_op_bsr_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint offset = OPER_I_32(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_push_32(cpu, REG_PC); + REG_PC -= 4; + m68ki_branch_32(cpu, offset); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_btst_32_r_d(m68ki_cpu_core *cpu) +{ + FLAG_Z = DY & (1 << (DX & 0x1f)); +} + + +void m68k_op_btst_8_r_ai(m68ki_cpu_core *cpu) +{ + FLAG_Z = OPER_AY_AI_8(cpu) & (1 << (DX & 7)); +} + + +void m68k_op_btst_8_r_pi(m68ki_cpu_core *cpu) +{ + FLAG_Z = OPER_AY_PI_8(cpu) & (1 << (DX & 7)); +} + + +void m68k_op_btst_8_r_pi7(m68ki_cpu_core *cpu) +{ + FLAG_Z = OPER_A7_PI_8(cpu) & (1 << (DX & 7)); +} + + +void m68k_op_btst_8_r_pd(m68ki_cpu_core *cpu) +{ + FLAG_Z = OPER_AY_PD_8(cpu) & (1 << (DX & 7)); +} + + +void m68k_op_btst_8_r_pd7(m68ki_cpu_core *cpu) +{ + FLAG_Z = OPER_A7_PD_8(cpu) & (1 << (DX & 7)); +} + + +void m68k_op_btst_8_r_di(m68ki_cpu_core *cpu) +{ + FLAG_Z = OPER_AY_DI_8(cpu) & (1 << (DX & 7)); +} + + +void m68k_op_btst_8_r_ix(m68ki_cpu_core *cpu) +{ + FLAG_Z = OPER_AY_IX_8(cpu) & (1 << (DX & 7)); +} + + +void m68k_op_btst_8_r_aw(m68ki_cpu_core *cpu) +{ + FLAG_Z = OPER_AW_8(cpu) & (1 << (DX & 7)); +} + + +void m68k_op_btst_8_r_al(m68ki_cpu_core *cpu) +{ + FLAG_Z = OPER_AL_8(cpu) & (1 << (DX & 7)); +} + + +void m68k_op_btst_8_r_pcdi(m68ki_cpu_core *cpu) +{ + FLAG_Z = OPER_PCDI_8(cpu) & (1 << (DX & 7)); +} + + +void m68k_op_btst_8_r_pcix(m68ki_cpu_core *cpu) +{ + FLAG_Z = OPER_PCIX_8(cpu) & (1 << (DX & 7)); +} + + +void m68k_op_btst_8_r_i(m68ki_cpu_core *cpu) +{ + FLAG_Z = OPER_I_8() & (1 << (DX & 7)); +} + + +void m68k_op_btst_32_s_d(m68ki_cpu_core *cpu) +{ + FLAG_Z = DY & (1 << (OPER_I_8() & 0x1f)); +} + + +void m68k_op_btst_8_s_ai(m68ki_cpu_core *cpu) +{ + uint bit = OPER_I_8() & 7; + + FLAG_Z = OPER_AY_AI_8(cpu) & (1 << bit); +} + + +void m68k_op_btst_8_s_pi(m68ki_cpu_core *cpu) +{ + uint bit = OPER_I_8() & 7; + + FLAG_Z = OPER_AY_PI_8(cpu) & (1 << bit); +} + + +void m68k_op_btst_8_s_pi7(m68ki_cpu_core *cpu) +{ + uint bit = OPER_I_8() & 7; + + FLAG_Z = OPER_A7_PI_8(cpu) & (1 << bit); +} + + +void m68k_op_btst_8_s_pd(m68ki_cpu_core *cpu) +{ + uint bit = OPER_I_8() & 7; + + FLAG_Z = OPER_AY_PD_8(cpu) & (1 << bit); +} + + +void m68k_op_btst_8_s_pd7(m68ki_cpu_core *cpu) +{ + uint bit = OPER_I_8() & 7; + + FLAG_Z = OPER_A7_PD_8(cpu) & (1 << bit); +} + + +void m68k_op_btst_8_s_di(m68ki_cpu_core *cpu) +{ + uint bit = OPER_I_8() & 7; + + FLAG_Z = OPER_AY_DI_8(cpu) & (1 << bit); +} + + +void m68k_op_btst_8_s_ix(m68ki_cpu_core *cpu) +{ + uint bit = OPER_I_8() & 7; + + FLAG_Z = OPER_AY_IX_8(cpu) & (1 << bit); +} + + +void m68k_op_btst_8_s_aw(m68ki_cpu_core *cpu) +{ + uint bit = OPER_I_8() & 7; + + FLAG_Z = OPER_AW_8(cpu) & (1 << bit); +} + + +void m68k_op_btst_8_s_al(m68ki_cpu_core *cpu) +{ + uint bit = OPER_I_8() & 7; + + FLAG_Z = OPER_AL_8(cpu) & (1 << bit); +} + + +void m68k_op_btst_8_s_pcdi(m68ki_cpu_core *cpu) +{ + uint bit = OPER_I_8() & 7; + + FLAG_Z = OPER_PCDI_8(cpu) & (1 << bit); +} + + +void m68k_op_btst_8_s_pcix(m68ki_cpu_core *cpu) +{ + uint bit = OPER_I_8() & 7; + + FLAG_Z = OPER_PCIX_8(cpu) & (1 << bit); +} + + +void m68k_op_callm_32_ai(m68ki_cpu_core *cpu) +{ + /* note: watch out for pcrelative modes */ + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + { + uint ea = EA_AY_AI_32(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + REG_PC += 2; + (uint)ea; /* just to avoid an 'unused variable' warning */ + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_callm_32_di(m68ki_cpu_core *cpu) +{ + /* note: watch out for pcrelative modes */ + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + { + uint ea = EA_AY_DI_32(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + REG_PC += 2; + (uint)ea; /* just to avoid an 'unused variable' warning */ + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_callm_32_ix(m68ki_cpu_core *cpu) +{ + /* note: watch out for pcrelative modes */ + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + { + uint ea = EA_AY_IX_32(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + REG_PC += 2; + (uint)ea; /* just to avoid an 'unused variable' warning */ + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_callm_32_aw(m68ki_cpu_core *cpu) +{ + /* note: watch out for pcrelative modes */ + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + { + uint ea = EA_AW_32(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + REG_PC += 2; + (uint)ea; /* just to avoid an 'unused variable' warning */ + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_callm_32_al(m68ki_cpu_core *cpu) +{ + /* note: watch out for pcrelative modes */ + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + { + uint ea = EA_AL_32(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + REG_PC += 2; + (uint)ea; /* just to avoid an 'unused variable' warning */ + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_callm_32_pcdi(m68ki_cpu_core *cpu) +{ + /* note: watch out for pcrelative modes */ + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + { + uint ea = EA_PCDI_32(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + REG_PC += 2; + (uint)ea; /* just to avoid an 'unused variable' warning */ + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_callm_32_pcix(m68ki_cpu_core *cpu) +{ + /* note: watch out for pcrelative modes */ + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + { + uint ea = EA_PCIX_32(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + REG_PC += 2; + (uint)ea; /* just to avoid an 'unused variable' warning */ + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cas_8_ai(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = EA_AY_AI_8(); + uint dest = m68ki_read_8(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - MASK_OUT_ABOVE_8(*compare); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(*compare, dest, res); + FLAG_C = CFLAG_8(res); + + if(COND_NE()) + *compare = MASK_OUT_BELOW_8(*compare) | dest; + else + { + USE_CYCLES(3); + m68ki_write_8(ea, MASK_OUT_ABOVE_8(REG_D[(word2 >> 6) & 7])); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cas_8_pi(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = EA_AY_PI_8(); + uint dest = m68ki_read_8(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - MASK_OUT_ABOVE_8(*compare); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(*compare, dest, res); + FLAG_C = CFLAG_8(res); + + if(COND_NE()) + *compare = MASK_OUT_BELOW_8(*compare) | dest; + else + { + USE_CYCLES(3); + m68ki_write_8(ea, MASK_OUT_ABOVE_8(REG_D[(word2 >> 6) & 7])); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cas_8_pi7(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = EA_A7_PI_8(); + uint dest = m68ki_read_8(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - MASK_OUT_ABOVE_8(*compare); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(*compare, dest, res); + FLAG_C = CFLAG_8(res); + + if(COND_NE()) + *compare = MASK_OUT_BELOW_8(*compare) | dest; + else + { + USE_CYCLES(3); + m68ki_write_8(ea, MASK_OUT_ABOVE_8(REG_D[(word2 >> 6) & 7])); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cas_8_pd(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = EA_AY_PD_8(); + uint dest = m68ki_read_8(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - MASK_OUT_ABOVE_8(*compare); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(*compare, dest, res); + FLAG_C = CFLAG_8(res); + + if(COND_NE()) + *compare = MASK_OUT_BELOW_8(*compare) | dest; + else + { + USE_CYCLES(3); + m68ki_write_8(ea, MASK_OUT_ABOVE_8(REG_D[(word2 >> 6) & 7])); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cas_8_pd7(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = EA_A7_PD_8(); + uint dest = m68ki_read_8(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - MASK_OUT_ABOVE_8(*compare); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(*compare, dest, res); + FLAG_C = CFLAG_8(res); + + if(COND_NE()) + *compare = MASK_OUT_BELOW_8(*compare) | dest; + else + { + USE_CYCLES(3); + m68ki_write_8(ea, MASK_OUT_ABOVE_8(REG_D[(word2 >> 6) & 7])); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cas_8_di(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = EA_AY_DI_8(); + uint dest = m68ki_read_8(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - MASK_OUT_ABOVE_8(*compare); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(*compare, dest, res); + FLAG_C = CFLAG_8(res); + + if(COND_NE()) + *compare = MASK_OUT_BELOW_8(*compare) | dest; + else + { + USE_CYCLES(3); + m68ki_write_8(ea, MASK_OUT_ABOVE_8(REG_D[(word2 >> 6) & 7])); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cas_8_ix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = EA_AY_IX_8(); + uint dest = m68ki_read_8(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - MASK_OUT_ABOVE_8(*compare); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(*compare, dest, res); + FLAG_C = CFLAG_8(res); + + if(COND_NE()) + *compare = MASK_OUT_BELOW_8(*compare) | dest; + else + { + USE_CYCLES(3); + m68ki_write_8(ea, MASK_OUT_ABOVE_8(REG_D[(word2 >> 6) & 7])); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cas_8_aw(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = EA_AW_8(); + uint dest = m68ki_read_8(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - MASK_OUT_ABOVE_8(*compare); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(*compare, dest, res); + FLAG_C = CFLAG_8(res); + + if(COND_NE()) + *compare = MASK_OUT_BELOW_8(*compare) | dest; + else + { + USE_CYCLES(3); + m68ki_write_8(ea, MASK_OUT_ABOVE_8(REG_D[(word2 >> 6) & 7])); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cas_8_al(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = EA_AL_8(); + uint dest = m68ki_read_8(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - MASK_OUT_ABOVE_8(*compare); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(*compare, dest, res); + FLAG_C = CFLAG_8(res); + + if(COND_NE()) + *compare = MASK_OUT_BELOW_8(*compare) | dest; + else + { + USE_CYCLES(3); + m68ki_write_8(ea, MASK_OUT_ABOVE_8(REG_D[(word2 >> 6) & 7])); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cas_16_ai(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = EA_AY_AI_16(); + uint dest = m68ki_read_16(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - MASK_OUT_ABOVE_16(*compare); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(*compare, dest, res); + FLAG_C = CFLAG_16(res); + + if(COND_NE()) + *compare = MASK_OUT_BELOW_16(*compare) | dest; + else + { + USE_CYCLES(3); + m68ki_write_16(ea, MASK_OUT_ABOVE_16(REG_D[(word2 >> 6) & 7])); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cas_16_pi(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = EA_AY_PI_16(); + uint dest = m68ki_read_16(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - MASK_OUT_ABOVE_16(*compare); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(*compare, dest, res); + FLAG_C = CFLAG_16(res); + + if(COND_NE()) + *compare = MASK_OUT_BELOW_16(*compare) | dest; + else + { + USE_CYCLES(3); + m68ki_write_16(ea, MASK_OUT_ABOVE_16(REG_D[(word2 >> 6) & 7])); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cas_16_pd(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = EA_AY_PD_16(); + uint dest = m68ki_read_16(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - MASK_OUT_ABOVE_16(*compare); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(*compare, dest, res); + FLAG_C = CFLAG_16(res); + + if(COND_NE()) + *compare = MASK_OUT_BELOW_16(*compare) | dest; + else + { + USE_CYCLES(3); + m68ki_write_16(ea, MASK_OUT_ABOVE_16(REG_D[(word2 >> 6) & 7])); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cas_16_di(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = EA_AY_DI_16(); + uint dest = m68ki_read_16(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - MASK_OUT_ABOVE_16(*compare); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(*compare, dest, res); + FLAG_C = CFLAG_16(res); + + if(COND_NE()) + *compare = MASK_OUT_BELOW_16(*compare) | dest; + else + { + USE_CYCLES(3); + m68ki_write_16(ea, MASK_OUT_ABOVE_16(REG_D[(word2 >> 6) & 7])); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cas_16_ix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = EA_AY_IX_16(); + uint dest = m68ki_read_16(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - MASK_OUT_ABOVE_16(*compare); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(*compare, dest, res); + FLAG_C = CFLAG_16(res); + + if(COND_NE()) + *compare = MASK_OUT_BELOW_16(*compare) | dest; + else + { + USE_CYCLES(3); + m68ki_write_16(ea, MASK_OUT_ABOVE_16(REG_D[(word2 >> 6) & 7])); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cas_16_aw(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = EA_AW_16(); + uint dest = m68ki_read_16(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - MASK_OUT_ABOVE_16(*compare); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(*compare, dest, res); + FLAG_C = CFLAG_16(res); + + if(COND_NE()) + *compare = MASK_OUT_BELOW_16(*compare) | dest; + else + { + USE_CYCLES(3); + m68ki_write_16(ea, MASK_OUT_ABOVE_16(REG_D[(word2 >> 6) & 7])); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cas_16_al(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = EA_AL_16(); + uint dest = m68ki_read_16(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - MASK_OUT_ABOVE_16(*compare); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(*compare, dest, res); + FLAG_C = CFLAG_16(res); + + if(COND_NE()) + *compare = MASK_OUT_BELOW_16(*compare) | dest; + else + { + USE_CYCLES(3); + m68ki_write_16(ea, MASK_OUT_ABOVE_16(REG_D[(word2 >> 6) & 7])); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cas_32_ai(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = EA_AY_AI_32(); + uint dest = m68ki_read_32(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - *compare; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(*compare, dest, res); + FLAG_C = CFLAG_SUB_32(*compare, dest, res); + + if(COND_NE()) + *compare = dest; + else + { + USE_CYCLES(3); + m68ki_write_32(ea, REG_D[(word2 >> 6) & 7]); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cas_32_pi(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = EA_AY_PI_32(); + uint dest = m68ki_read_32(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - *compare; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(*compare, dest, res); + FLAG_C = CFLAG_SUB_32(*compare, dest, res); + + if(COND_NE()) + *compare = dest; + else + { + USE_CYCLES(3); + m68ki_write_32(ea, REG_D[(word2 >> 6) & 7]); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cas_32_pd(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = EA_AY_PD_32(); + uint dest = m68ki_read_32(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - *compare; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(*compare, dest, res); + FLAG_C = CFLAG_SUB_32(*compare, dest, res); + + if(COND_NE()) + *compare = dest; + else + { + USE_CYCLES(3); + m68ki_write_32(ea, REG_D[(word2 >> 6) & 7]); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cas_32_di(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = EA_AY_DI_32(); + uint dest = m68ki_read_32(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - *compare; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(*compare, dest, res); + FLAG_C = CFLAG_SUB_32(*compare, dest, res); + + if(COND_NE()) + *compare = dest; + else + { + USE_CYCLES(3); + m68ki_write_32(ea, REG_D[(word2 >> 6) & 7]); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cas_32_ix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = EA_AY_IX_32(); + uint dest = m68ki_read_32(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - *compare; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(*compare, dest, res); + FLAG_C = CFLAG_SUB_32(*compare, dest, res); + + if(COND_NE()) + *compare = dest; + else + { + USE_CYCLES(3); + m68ki_write_32(ea, REG_D[(word2 >> 6) & 7]); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cas_32_aw(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = EA_AW_32(); + uint dest = m68ki_read_32(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - *compare; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(*compare, dest, res); + FLAG_C = CFLAG_SUB_32(*compare, dest, res); + + if(COND_NE()) + *compare = dest; + else + { + USE_CYCLES(3); + m68ki_write_32(ea, REG_D[(word2 >> 6) & 7]); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cas_32_al(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = EA_AL_32(); + uint dest = m68ki_read_32(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - *compare; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(*compare, dest, res); + FLAG_C = CFLAG_SUB_32(*compare, dest, res); + + if(COND_NE()) + *compare = dest; + else + { + USE_CYCLES(3); + m68ki_write_32(ea, REG_D[(word2 >> 6) & 7]); + } + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cas2_16(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_32(); + uint* compare1 = ®_D[(word2 >> 16) & 7]; + uint ea1 = REG_DA[(word2 >> 28) & 15]; + uint dest1 = m68ki_read_16(ea1); + uint res1 = dest1 - MASK_OUT_ABOVE_16(*compare1); + uint* compare2 = ®_D[word2 & 7]; + uint ea2 = REG_DA[(word2 >> 12) & 15]; + uint dest2 = m68ki_read_16(ea2); + uint res2; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_16(res1); + FLAG_Z = MASK_OUT_ABOVE_16(res1); + FLAG_V = VFLAG_SUB_16(*compare1, dest1, res1); + FLAG_C = CFLAG_16(res1); + + if(COND_EQ()) + { + res2 = dest2 - MASK_OUT_ABOVE_16(*compare2); + + FLAG_N = NFLAG_16(res2); + FLAG_Z = MASK_OUT_ABOVE_16(res2); + FLAG_V = VFLAG_SUB_16(*compare2, dest2, res2); + FLAG_C = CFLAG_16(res2); + + if(COND_EQ()) + { + USE_CYCLES(3); + m68ki_write_16(ea1, REG_D[(word2 >> 22) & 7]); + m68ki_write_16(ea2, REG_D[(word2 >> 6) & 7]); + return; + } + } + *compare1 = BIT_1F(word2) ? MAKE_INT_16(dest1) : MASK_OUT_BELOW_16(*compare1) | dest1; + *compare2 = BIT_F(word2) ? MAKE_INT_16(dest2) : MASK_OUT_BELOW_16(*compare2) | dest2; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cas2_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_32(); + uint* compare1 = ®_D[(word2 >> 16) & 7]; + uint ea1 = REG_DA[(word2 >> 28) & 15]; + uint dest1 = m68ki_read_32(ea1); + uint res1 = dest1 - *compare1; + uint* compare2 = ®_D[word2 & 7]; + uint ea2 = REG_DA[(word2 >> 12) & 15]; + uint dest2 = m68ki_read_32(ea2); + uint res2; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_32(res1); + FLAG_Z = MASK_OUT_ABOVE_32(res1); + FLAG_V = VFLAG_SUB_32(*compare1, dest1, res1); + FLAG_C = CFLAG_SUB_32(*compare1, dest1, res1); + + if(COND_EQ()) + { + res2 = dest2 - *compare2; + + FLAG_N = NFLAG_32(res2); + FLAG_Z = MASK_OUT_ABOVE_32(res2); + FLAG_V = VFLAG_SUB_32(*compare2, dest2, res2); + FLAG_C = CFLAG_SUB_32(*compare2, dest2, res2); + + if(COND_EQ()) + { + USE_CYCLES(3); + m68ki_write_32(ea1, REG_D[(word2 >> 22) & 7]); + m68ki_write_32(ea2, REG_D[(word2 >> 6) & 7]); + return; + } + } + *compare1 = dest1; + *compare2 = dest2; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk_16_d(m68ki_cpu_core *cpu) +{ + sint src = MAKE_INT_16(DX); + sint bound = MAKE_INT_16(DY); + + FLAG_Z = ZFLAG_16(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(cpu, EXCEPTION_CHK); +} + + +void m68k_op_chk_16_ai(m68ki_cpu_core *cpu) +{ + sint src = MAKE_INT_16(DX); + sint bound = MAKE_INT_16(OPER_AY_AI_16(cpu)); + + FLAG_Z = ZFLAG_16(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(cpu, EXCEPTION_CHK); +} + + +void m68k_op_chk_16_pi(m68ki_cpu_core *cpu) +{ + sint src = MAKE_INT_16(DX); + sint bound = MAKE_INT_16(OPER_AY_PI_16(cpu)); + + FLAG_Z = ZFLAG_16(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(cpu, EXCEPTION_CHK); +} + + +void m68k_op_chk_16_pd(m68ki_cpu_core *cpu) +{ + sint src = MAKE_INT_16(DX); + sint bound = MAKE_INT_16(OPER_AY_PD_16(cpu)); + + FLAG_Z = ZFLAG_16(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(cpu, EXCEPTION_CHK); +} + + +void m68k_op_chk_16_di(m68ki_cpu_core *cpu) +{ + sint src = MAKE_INT_16(DX); + sint bound = MAKE_INT_16(OPER_AY_DI_16(cpu)); + + FLAG_Z = ZFLAG_16(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(cpu, EXCEPTION_CHK); +} + + +void m68k_op_chk_16_ix(m68ki_cpu_core *cpu) +{ + sint src = MAKE_INT_16(DX); + sint bound = MAKE_INT_16(OPER_AY_IX_16(cpu)); + + FLAG_Z = ZFLAG_16(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(cpu, EXCEPTION_CHK); +} + + +void m68k_op_chk_16_aw(m68ki_cpu_core *cpu) +{ + sint src = MAKE_INT_16(DX); + sint bound = MAKE_INT_16(OPER_AW_16(cpu)); + + FLAG_Z = ZFLAG_16(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(cpu, EXCEPTION_CHK); +} + + +void m68k_op_chk_16_al(m68ki_cpu_core *cpu) +{ + sint src = MAKE_INT_16(DX); + sint bound = MAKE_INT_16(OPER_AL_16(cpu)); + + FLAG_Z = ZFLAG_16(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(cpu, EXCEPTION_CHK); +} + + +void m68k_op_chk_16_pcdi(m68ki_cpu_core *cpu) +{ + sint src = MAKE_INT_16(DX); + sint bound = MAKE_INT_16(OPER_PCDI_16(cpu)); + + FLAG_Z = ZFLAG_16(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(cpu, EXCEPTION_CHK); +} + + +void m68k_op_chk_16_pcix(m68ki_cpu_core *cpu) +{ + sint src = MAKE_INT_16(DX); + sint bound = MAKE_INT_16(OPER_PCIX_16(cpu)); + + FLAG_Z = ZFLAG_16(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(cpu, EXCEPTION_CHK); +} + + +void m68k_op_chk_16_i(m68ki_cpu_core *cpu) +{ + sint src = MAKE_INT_16(DX); + sint bound = MAKE_INT_16(OPER_I_16()); + + FLAG_Z = ZFLAG_16(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(cpu, EXCEPTION_CHK); +} + + +void m68k_op_chk_32_d(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + sint src = MAKE_INT_32(DX); + sint bound = MAKE_INT_32(DY); + + FLAG_Z = ZFLAG_32(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk_32_ai(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + sint src = MAKE_INT_32(DX); + sint bound = MAKE_INT_32(OPER_AY_AI_32(cpu)); + + FLAG_Z = ZFLAG_32(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk_32_pi(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + sint src = MAKE_INT_32(DX); + sint bound = MAKE_INT_32(OPER_AY_PI_32(cpu)); + + FLAG_Z = ZFLAG_32(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk_32_pd(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + sint src = MAKE_INT_32(DX); + sint bound = MAKE_INT_32(OPER_AY_PD_32(cpu)); + + FLAG_Z = ZFLAG_32(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk_32_di(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + sint src = MAKE_INT_32(DX); + sint bound = MAKE_INT_32(OPER_AY_DI_32(cpu)); + + FLAG_Z = ZFLAG_32(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk_32_ix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + sint src = MAKE_INT_32(DX); + sint bound = MAKE_INT_32(OPER_AY_IX_32(cpu)); + + FLAG_Z = ZFLAG_32(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk_32_aw(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + sint src = MAKE_INT_32(DX); + sint bound = MAKE_INT_32(OPER_AW_32(cpu)); + + FLAG_Z = ZFLAG_32(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk_32_al(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + sint src = MAKE_INT_32(DX); + sint bound = MAKE_INT_32(OPER_AL_32(cpu)); + + FLAG_Z = ZFLAG_32(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk_32_pcdi(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + sint src = MAKE_INT_32(DX); + sint bound = MAKE_INT_32(OPER_PCDI_32(cpu)); + + FLAG_Z = ZFLAG_32(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk_32_pcix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + sint src = MAKE_INT_32(DX); + sint bound = MAKE_INT_32(OPER_PCIX_32(cpu)); + + FLAG_Z = ZFLAG_32(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk_32_i(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + sint src = MAKE_INT_32(DX); + sint bound = MAKE_INT_32(OPER_I_32()); + + FLAG_Z = ZFLAG_32(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk2cmp2_8_pcdi(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]&0xff; + uint ea = EA_PCDI_8(); + uint lower_bound = m68ki_read_pcrel_8(ea); + uint upper_bound = m68ki_read_pcrel_8(ea + 1); + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_8(compare) - MAKE_INT_8(lower_bound); + else + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + + FLAG_C = upper_bound - compare; + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk2cmp2_8_pcix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]&0xff; + uint ea = EA_PCIX_8(); + uint lower_bound = m68ki_read_pcrel_8(ea); + uint upper_bound = m68ki_read_pcrel_8(ea + 1); + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_8(compare) - MAKE_INT_8(lower_bound); + else + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + + FLAG_C = upper_bound - compare; + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk2cmp2_8_ai(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]&0xff; + uint ea = EA_AY_AI_8(); + uint lower_bound = m68ki_read_8(ea); + uint upper_bound = m68ki_read_8(ea + 1); + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_8(compare) - MAKE_INT_8(lower_bound); + else + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + + FLAG_C = upper_bound - compare; + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk2cmp2_8_di(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]&0xff; + uint ea = EA_AY_DI_8(); + uint lower_bound = m68ki_read_8(ea); + uint upper_bound = m68ki_read_8(ea + 1); + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_8(compare) - MAKE_INT_8(lower_bound); + else + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + + FLAG_C = upper_bound - compare; + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk2cmp2_8_ix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]&0xff; + uint ea = EA_AY_IX_8(); + uint lower_bound = m68ki_read_8(ea); + uint upper_bound = m68ki_read_8(ea + 1); + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_8(compare) - MAKE_INT_8(lower_bound); + else + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + + FLAG_C = upper_bound - compare; + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk2cmp2_8_aw(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]&0xff; + uint ea = EA_AW_8(); + uint lower_bound = m68ki_read_8(ea); + uint upper_bound = m68ki_read_8(ea + 1); + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_8(compare) - MAKE_INT_8(lower_bound); + else + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + + FLAG_C = upper_bound - compare; + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk2cmp2_8_al(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]&0xff; + uint ea = EA_AL_8(); + uint lower_bound = m68ki_read_8(ea); + uint upper_bound = m68ki_read_8(ea + 1); + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_8(compare) - MAKE_INT_8(lower_bound); + else + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + + FLAG_C = upper_bound - compare; + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk2cmp2_16_pcdi(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]&0xffff; + uint ea = EA_PCDI_16(); + uint lower_bound = m68ki_read_pcrel_16(ea); + uint upper_bound = m68ki_read_pcrel_16(ea + 2); + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_16(compare) - MAKE_INT_16(lower_bound); + else + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + FLAG_C = CFLAG_16(FLAG_C); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_16(upper_bound) - MAKE_INT_16(compare); + else + FLAG_C = upper_bound - compare; + FLAG_C = CFLAG_16(FLAG_C); + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk2cmp2_16_pcix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]&0xffff; + uint ea = EA_PCIX_16(); + uint lower_bound = m68ki_read_pcrel_16(ea); + uint upper_bound = m68ki_read_pcrel_16(ea + 2); + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_16(compare) - MAKE_INT_16(lower_bound); + else + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + FLAG_C = CFLAG_16(FLAG_C); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_16(upper_bound) - MAKE_INT_16(compare); + else + FLAG_C = upper_bound - compare; + FLAG_C = CFLAG_16(FLAG_C); + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk2cmp2_16_ai(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]&0xffff; + uint ea = EA_AY_AI_16(); + uint lower_bound = m68ki_read_16(ea); + uint upper_bound = m68ki_read_16(ea + 2); + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_16(compare) - MAKE_INT_16(lower_bound); + else + FLAG_C = compare - lower_bound; + + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + FLAG_C = CFLAG_16(FLAG_C); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_16(upper_bound) - MAKE_INT_16(compare); + else + FLAG_C = upper_bound - compare; + + FLAG_C = CFLAG_16(FLAG_C); + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk2cmp2_16_di(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]&0xffff; + uint ea = EA_AY_DI_16(); + uint lower_bound = m68ki_read_16(ea); + uint upper_bound = m68ki_read_16(ea + 2); + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_16(compare) - MAKE_INT_16(lower_bound); + else + FLAG_C = compare - lower_bound; + + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + FLAG_C = CFLAG_16(FLAG_C); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_16(upper_bound) - MAKE_INT_16(compare); + else + FLAG_C = upper_bound - compare; + + FLAG_C = CFLAG_16(FLAG_C); + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk2cmp2_16_ix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]&0xffff; + uint ea = EA_AY_IX_16(); + uint lower_bound = m68ki_read_16(ea); + uint upper_bound = m68ki_read_16(ea + 2); + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_16(compare) - MAKE_INT_16(lower_bound); + else + FLAG_C = compare - lower_bound; + + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + FLAG_C = CFLAG_16(FLAG_C); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_16(upper_bound) - MAKE_INT_16(compare); + else + FLAG_C = upper_bound - compare; + + FLAG_C = CFLAG_16(FLAG_C); + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk2cmp2_16_aw(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]&0xffff; + uint ea = EA_AW_16(); + uint lower_bound = m68ki_read_16(ea); + uint upper_bound = m68ki_read_16(ea + 2); + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_16(compare) - MAKE_INT_16(lower_bound); + else + FLAG_C = compare - lower_bound; + + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + FLAG_C = CFLAG_16(FLAG_C); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_16(upper_bound) - MAKE_INT_16(compare); + else + FLAG_C = upper_bound - compare; + + FLAG_C = CFLAG_16(FLAG_C); + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk2cmp2_16_al(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]&0xffff; + uint ea = EA_AL_16(); + uint lower_bound = m68ki_read_16(ea); + uint upper_bound = m68ki_read_16(ea + 2); + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_16(compare) - MAKE_INT_16(lower_bound); + else + FLAG_C = compare - lower_bound; + + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + FLAG_C = CFLAG_16(FLAG_C); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_16(upper_bound) - MAKE_INT_16(compare); + else + FLAG_C = upper_bound - compare; + + FLAG_C = CFLAG_16(FLAG_C); + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk2cmp2_32_pcdi(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]; + uint ea = EA_PCDI_32(); + uint lower_bound = m68ki_read_pcrel_32(ea); + uint upper_bound = m68ki_read_pcrel_32(ea + 4); + + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + FLAG_C = CFLAG_SUB_32(lower_bound, compare, FLAG_C); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + + FLAG_C = upper_bound - compare; + FLAG_C = CFLAG_SUB_32(compare, upper_bound, FLAG_C); + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk2cmp2_32_pcix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]; + uint ea = EA_PCIX_32(); + uint lower_bound = m68ki_read_pcrel_32(ea); + uint upper_bound = m68ki_read_pcrel_32(ea + 4); + + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + FLAG_C = CFLAG_SUB_32(lower_bound, compare, FLAG_C); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + + FLAG_C = upper_bound - compare; + FLAG_C = CFLAG_SUB_32(compare, upper_bound, FLAG_C); + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk2cmp2_32_ai(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]; + uint ea = EA_AY_AI_32(); + uint lower_bound = m68ki_read_32(ea); + uint upper_bound = m68ki_read_32(ea + 4); + + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + FLAG_C = CFLAG_SUB_32(lower_bound, compare, FLAG_C); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + + FLAG_C = upper_bound - compare; + FLAG_C = CFLAG_SUB_32(compare, upper_bound, FLAG_C); + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk2cmp2_32_di(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]; + uint ea = EA_AY_DI_32(); + uint lower_bound = m68ki_read_32(ea); + uint upper_bound = m68ki_read_32(ea + 4); + + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + FLAG_C = CFLAG_SUB_32(lower_bound, compare, FLAG_C); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + + FLAG_C = upper_bound - compare; + FLAG_C = CFLAG_SUB_32(compare, upper_bound, FLAG_C); + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk2cmp2_32_ix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]; + uint ea = EA_AY_IX_32(); + uint lower_bound = m68ki_read_32(ea); + uint upper_bound = m68ki_read_32(ea + 4); + + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + FLAG_C = CFLAG_SUB_32(lower_bound, compare, FLAG_C); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + + FLAG_C = upper_bound - compare; + FLAG_C = CFLAG_SUB_32(compare, upper_bound, FLAG_C); + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk2cmp2_32_aw(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]; + uint ea = EA_AW_32(); + uint lower_bound = m68ki_read_32(ea); + uint upper_bound = m68ki_read_32(ea + 4); + + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + FLAG_C = CFLAG_SUB_32(lower_bound, compare, FLAG_C); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + + FLAG_C = upper_bound - compare; + FLAG_C = CFLAG_SUB_32(compare, upper_bound, FLAG_C); + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_chk2cmp2_32_al(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]; + uint ea = EA_AL_32(); + uint lower_bound = m68ki_read_32(ea); + uint upper_bound = m68ki_read_32(ea + 4); + + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + FLAG_C = CFLAG_SUB_32(lower_bound, compare, FLAG_C); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + + FLAG_C = upper_bound - compare; + FLAG_C = CFLAG_SUB_32(compare, upper_bound, FLAG_C); + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(cpu, EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_clr_8_d(m68ki_cpu_core *cpu) +{ + DY &= 0xffffff00; + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +void m68k_op_clr_8_ai(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_AI_8(), 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +void m68k_op_clr_8_pi(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PI_8(), 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +void m68k_op_clr_8_pi7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PI_8(), 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +void m68k_op_clr_8_pd(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PD_8(), 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +void m68k_op_clr_8_pd7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PD_8(), 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +void m68k_op_clr_8_di(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_DI_8(), 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +void m68k_op_clr_8_ix(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_IX_8(), 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +void m68k_op_clr_8_aw(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AW_8(), 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +void m68k_op_clr_8_al(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AL_8(), 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +void m68k_op_clr_16_d(m68ki_cpu_core *cpu) +{ + DY &= 0xffff0000; + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +void m68k_op_clr_16_ai(m68ki_cpu_core *cpu) +{ + m68ki_write_16(EA_AY_AI_16(), 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +void m68k_op_clr_16_pi(m68ki_cpu_core *cpu) +{ + m68ki_write_16(EA_AY_PI_16(), 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +void m68k_op_clr_16_pd(m68ki_cpu_core *cpu) +{ + m68ki_write_16(EA_AY_PD_16(), 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +void m68k_op_clr_16_di(m68ki_cpu_core *cpu) +{ + m68ki_write_16(EA_AY_DI_16(), 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +void m68k_op_clr_16_ix(m68ki_cpu_core *cpu) +{ + m68ki_write_16(EA_AY_IX_16(), 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +void m68k_op_clr_16_aw(m68ki_cpu_core *cpu) +{ + m68ki_write_16(EA_AW_16(), 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +void m68k_op_clr_16_al(m68ki_cpu_core *cpu) +{ + m68ki_write_16(EA_AL_16(), 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +void m68k_op_clr_32_d(m68ki_cpu_core *cpu) +{ + DY = 0; + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +void m68k_op_clr_32_ai(m68ki_cpu_core *cpu) +{ + m68ki_write_32(EA_AY_AI_32(), 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +void m68k_op_clr_32_pi(m68ki_cpu_core *cpu) +{ + m68ki_write_32(EA_AY_PI_32(), 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +void m68k_op_clr_32_pd(m68ki_cpu_core *cpu) +{ + m68ki_write_32(EA_AY_PD_32(), 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +void m68k_op_clr_32_di(m68ki_cpu_core *cpu) +{ + m68ki_write_32(EA_AY_DI_32(), 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +void m68k_op_clr_32_ix(m68ki_cpu_core *cpu) +{ + m68ki_write_32(EA_AY_IX_32(), 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +void m68k_op_clr_32_aw(m68ki_cpu_core *cpu) +{ + m68ki_write_32(EA_AW_32(), 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +void m68k_op_clr_32_al(m68ki_cpu_core *cpu) +{ + m68ki_write_32(EA_AL_32(), 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +void m68k_op_cmp_8_d(m68ki_cpu_core *cpu) +{ + uint src = MASK_OUT_ABOVE_8(DY); + uint dst = MASK_OUT_ABOVE_8(DX); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +void m68k_op_cmp_8_ai(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_AI_8(cpu); + uint dst = MASK_OUT_ABOVE_8(DX); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +void m68k_op_cmp_8_pi(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_PI_8(cpu); + uint dst = MASK_OUT_ABOVE_8(DX); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +void m68k_op_cmp_8_pi7(m68ki_cpu_core *cpu) +{ + uint src = OPER_A7_PI_8(cpu); + uint dst = MASK_OUT_ABOVE_8(DX); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +void m68k_op_cmp_8_pd(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_PD_8(cpu); + uint dst = MASK_OUT_ABOVE_8(DX); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +void m68k_op_cmp_8_pd7(m68ki_cpu_core *cpu) +{ + uint src = OPER_A7_PD_8(cpu); + uint dst = MASK_OUT_ABOVE_8(DX); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +void m68k_op_cmp_8_di(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_DI_8(cpu); + uint dst = MASK_OUT_ABOVE_8(DX); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +void m68k_op_cmp_8_ix(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_IX_8(cpu); + uint dst = MASK_OUT_ABOVE_8(DX); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +void m68k_op_cmp_8_aw(m68ki_cpu_core *cpu) +{ + uint src = OPER_AW_8(cpu); + uint dst = MASK_OUT_ABOVE_8(DX); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +void m68k_op_cmp_8_al(m68ki_cpu_core *cpu) +{ + uint src = OPER_AL_8(cpu); + uint dst = MASK_OUT_ABOVE_8(DX); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +void m68k_op_cmp_8_pcdi(m68ki_cpu_core *cpu) +{ + uint src = OPER_PCDI_8(cpu); + uint dst = MASK_OUT_ABOVE_8(DX); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +void m68k_op_cmp_8_pcix(m68ki_cpu_core *cpu) +{ + uint src = OPER_PCIX_8(cpu); + uint dst = MASK_OUT_ABOVE_8(DX); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +void m68k_op_cmp_8_i(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint dst = MASK_OUT_ABOVE_8(DX); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +void m68k_op_cmp_16_d(m68ki_cpu_core *cpu) +{ + uint src = MASK_OUT_ABOVE_16(DY); + uint dst = MASK_OUT_ABOVE_16(DX); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +void m68k_op_cmp_16_a(m68ki_cpu_core *cpu) +{ + uint src = MASK_OUT_ABOVE_16(AY); + uint dst = MASK_OUT_ABOVE_16(DX); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +void m68k_op_cmp_16_ai(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_AI_16(cpu); + uint dst = MASK_OUT_ABOVE_16(DX); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +void m68k_op_cmp_16_pi(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_PI_16(cpu); + uint dst = MASK_OUT_ABOVE_16(DX); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +void m68k_op_cmp_16_pd(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_PD_16(cpu); + uint dst = MASK_OUT_ABOVE_16(DX); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +void m68k_op_cmp_16_di(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_DI_16(cpu); + uint dst = MASK_OUT_ABOVE_16(DX); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +void m68k_op_cmp_16_ix(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_IX_16(cpu); + uint dst = MASK_OUT_ABOVE_16(DX); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +void m68k_op_cmp_16_aw(m68ki_cpu_core *cpu) +{ + uint src = OPER_AW_16(cpu); + uint dst = MASK_OUT_ABOVE_16(DX); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +void m68k_op_cmp_16_al(m68ki_cpu_core *cpu) +{ + uint src = OPER_AL_16(cpu); + uint dst = MASK_OUT_ABOVE_16(DX); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +void m68k_op_cmp_16_pcdi(m68ki_cpu_core *cpu) +{ + uint src = OPER_PCDI_16(cpu); + uint dst = MASK_OUT_ABOVE_16(DX); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +void m68k_op_cmp_16_pcix(m68ki_cpu_core *cpu) +{ + uint src = OPER_PCIX_16(cpu); + uint dst = MASK_OUT_ABOVE_16(DX); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +void m68k_op_cmp_16_i(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint dst = MASK_OUT_ABOVE_16(DX); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +void m68k_op_cmp_32_d(m68ki_cpu_core *cpu) +{ + uint src = DY; + uint dst = DX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmp_32_a(m68ki_cpu_core *cpu) +{ + uint src = AY; + uint dst = DX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmp_32_ai(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_AI_32(cpu); + uint dst = DX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmp_32_pi(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_PI_32(cpu); + uint dst = DX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmp_32_pd(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_PD_32(cpu); + uint dst = DX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmp_32_di(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_DI_32(cpu); + uint dst = DX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmp_32_ix(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_IX_32(cpu); + uint dst = DX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmp_32_aw(m68ki_cpu_core *cpu) +{ + uint src = OPER_AW_32(cpu); + uint dst = DX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmp_32_al(m68ki_cpu_core *cpu) +{ + uint src = OPER_AL_32(cpu); + uint dst = DX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmp_32_pcdi(m68ki_cpu_core *cpu) +{ + uint src = OPER_PCDI_32(cpu); + uint dst = DX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmp_32_pcix(m68ki_cpu_core *cpu) +{ + uint src = OPER_PCIX_32(cpu); + uint dst = DX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmp_32_i(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint dst = DX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpa_16_d(m68ki_cpu_core *cpu) +{ + uint src = MAKE_INT_16(DY); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpa_16_a(m68ki_cpu_core *cpu) +{ + uint src = MAKE_INT_16(AY); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpa_16_ai(m68ki_cpu_core *cpu) +{ + uint src = MAKE_INT_16(OPER_AY_AI_16(cpu)); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpa_16_pi(m68ki_cpu_core *cpu) +{ + uint src = MAKE_INT_16(OPER_AY_PI_16(cpu)); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpa_16_pd(m68ki_cpu_core *cpu) +{ + uint src = MAKE_INT_16(OPER_AY_PD_16(cpu)); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpa_16_di(m68ki_cpu_core *cpu) +{ + uint src = MAKE_INT_16(OPER_AY_DI_16(cpu)); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpa_16_ix(m68ki_cpu_core *cpu) +{ + uint src = MAKE_INT_16(OPER_AY_IX_16(cpu)); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpa_16_aw(m68ki_cpu_core *cpu) +{ + uint src = MAKE_INT_16(OPER_AW_16(cpu)); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpa_16_al(m68ki_cpu_core *cpu) +{ + uint src = MAKE_INT_16(OPER_AL_16(cpu)); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpa_16_pcdi(m68ki_cpu_core *cpu) +{ + uint src = MAKE_INT_16(OPER_PCDI_16(cpu)); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpa_16_pcix(m68ki_cpu_core *cpu) +{ + uint src = MAKE_INT_16(OPER_PCIX_16(cpu)); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpa_16_i(m68ki_cpu_core *cpu) +{ + uint src = MAKE_INT_16(OPER_I_16()); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpa_32_d(m68ki_cpu_core *cpu) +{ + uint src = DY; + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpa_32_a(m68ki_cpu_core *cpu) +{ + uint src = AY; + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpa_32_ai(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_AI_32(cpu); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpa_32_pi(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_PI_32(cpu); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpa_32_pd(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_PD_32(cpu); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpa_32_di(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_DI_32(cpu); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpa_32_ix(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_IX_32(cpu); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpa_32_aw(m68ki_cpu_core *cpu) +{ + uint src = OPER_AW_32(cpu); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpa_32_al(m68ki_cpu_core *cpu) +{ + uint src = OPER_AL_32(cpu); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpa_32_pcdi(m68ki_cpu_core *cpu) +{ + uint src = OPER_PCDI_32(cpu); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpa_32_pcix(m68ki_cpu_core *cpu) +{ + uint src = OPER_PCIX_32(cpu); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpa_32_i(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpi_8_d(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint dst = MASK_OUT_ABOVE_8(DY); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +void m68k_op_cmpi_8_ai(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint dst = OPER_AY_AI_8(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +void m68k_op_cmpi_8_pi(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint dst = OPER_AY_PI_8(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +void m68k_op_cmpi_8_pi7(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint dst = OPER_A7_PI_8(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +void m68k_op_cmpi_8_pd(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint dst = OPER_AY_PD_8(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +void m68k_op_cmpi_8_pd7(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint dst = OPER_A7_PD_8(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +void m68k_op_cmpi_8_di(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint dst = OPER_AY_DI_8(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +void m68k_op_cmpi_8_ix(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint dst = OPER_AY_IX_8(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +void m68k_op_cmpi_8_aw(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint dst = OPER_AW_8(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +void m68k_op_cmpi_8_al(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint dst = OPER_AL_8(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +void m68k_op_cmpi_8_pcdi(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint src = OPER_I_8(); + uint dst = OPER_PCDI_8(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cmpi_8_pcix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint src = OPER_I_8(); + uint dst = OPER_PCIX_8(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cmpi_16_d(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint dst = MASK_OUT_ABOVE_16(DY); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +void m68k_op_cmpi_16_ai(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint dst = OPER_AY_AI_16(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +void m68k_op_cmpi_16_pi(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint dst = OPER_AY_PI_16(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +void m68k_op_cmpi_16_pd(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint dst = OPER_AY_PD_16(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +void m68k_op_cmpi_16_di(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint dst = OPER_AY_DI_16(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +void m68k_op_cmpi_16_ix(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint dst = OPER_AY_IX_16(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +void m68k_op_cmpi_16_aw(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint dst = OPER_AW_16(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +void m68k_op_cmpi_16_al(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint dst = OPER_AL_16(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +void m68k_op_cmpi_16_pcdi(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint src = OPER_I_16(); + uint dst = OPER_PCDI_16(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cmpi_16_pcix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint src = OPER_I_16(); + uint dst = OPER_PCIX_16(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cmpi_32_d(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint dst = DY; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpi_32_ai(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint dst = OPER_AY_AI_32(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpi_32_pi(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint dst = OPER_AY_PI_32(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpi_32_pd(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint dst = OPER_AY_PD_32(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpi_32_di(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint dst = OPER_AY_DI_32(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpi_32_ix(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint dst = OPER_AY_IX_32(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpi_32_aw(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint dst = OPER_AW_32(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpi_32_al(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint dst = OPER_AL_32(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cmpi_32_pcdi(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint src = OPER_I_32(); + uint dst = OPER_PCDI_32(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cmpi_32_pcix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint src = OPER_I_32(); + uint dst = OPER_PCIX_32(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_cmpm_8_ax7(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_PI_8(cpu); + uint dst = OPER_A7_PI_8(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +void m68k_op_cmpm_8_ay7(m68ki_cpu_core *cpu) +{ + uint src = OPER_A7_PI_8(cpu); + uint dst = OPER_AX_PI_8(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +void m68k_op_cmpm_8_axy7(m68ki_cpu_core *cpu) +{ + uint src = OPER_A7_PI_8(cpu); + uint dst = OPER_A7_PI_8(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +void m68k_op_cmpm_8(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_PI_8(cpu); + uint dst = OPER_AX_PI_8(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +void m68k_op_cmpm_16(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_PI_16(cpu); + uint dst = OPER_AX_PI_16(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +void m68k_op_cmpm_32(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_PI_32(cpu); + uint dst = OPER_AX_PI_32(cpu); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +void m68k_op_cpbcc_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_1111(cpu); +} + + +void m68k_op_cpdbcc_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_1111(cpu); +} + + +void m68k_op_cpgen_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_1111(cpu); +} + + +void m68k_op_cpscc_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_1111(cpu); +} + + +void m68k_op_cptrapcc_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_1111(cpu); +} + + +/* ======================================================================== */ +/* ============================== END OF FILE ============================= */ +/* ======================================================================== */ + + diff --git a/plugins/ao/eng_ssf/m68kopdm.c b/plugins/ao/eng_ssf/m68kopdm.c new file mode 100644 index 00000000..509435a1 --- /dev/null +++ b/plugins/ao/eng_ssf/m68kopdm.c @@ -0,0 +1,13221 @@ +#include "m68kcpu.h" + +/* ======================================================================== */ +/* ========================= INSTRUCTION HANDLERS ========================= */ +/* ======================================================================== */ + + +void m68k_op_dbt_16(m68ki_cpu_core *cpu) +{ + REG_PC += 2; +} + + +void m68k_op_dbf_16(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint res = MASK_OUT_ABOVE_16(*r_dst - 1); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + if(res != 0xffff) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(cpu, offset); + return; + } + REG_PC += 2; +} + + +void m68k_op_dbhi_16(m68ki_cpu_core *cpu) +{ + if(COND_NOT_HI()) + { + uint* r_dst = &DY; + uint res = MASK_OUT_ABOVE_16(*r_dst - 1); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + if(res != 0xffff) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(cpu, offset); + USE_CYCLES(CYC_DBCC_F_NOEXP); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_DBCC_F_EXP); + return; + } + REG_PC += 2; +} + + +void m68k_op_dbls_16(m68ki_cpu_core *cpu) +{ + if(COND_NOT_LS()) + { + uint* r_dst = &DY; + uint res = MASK_OUT_ABOVE_16(*r_dst - 1); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + if(res != 0xffff) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(cpu, offset); + USE_CYCLES(CYC_DBCC_F_NOEXP); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_DBCC_F_EXP); + return; + } + REG_PC += 2; +} + + +void m68k_op_dbcc_16(m68ki_cpu_core *cpu) +{ + if(COND_NOT_CC()) + { + uint* r_dst = &DY; + uint res = MASK_OUT_ABOVE_16(*r_dst - 1); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + if(res != 0xffff) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(cpu, offset); + USE_CYCLES(CYC_DBCC_F_NOEXP); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_DBCC_F_EXP); + return; + } + REG_PC += 2; +} + + +void m68k_op_dbcs_16(m68ki_cpu_core *cpu) +{ + if(COND_NOT_CS()) + { + uint* r_dst = &DY; + uint res = MASK_OUT_ABOVE_16(*r_dst - 1); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + if(res != 0xffff) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(cpu, offset); + USE_CYCLES(CYC_DBCC_F_NOEXP); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_DBCC_F_EXP); + return; + } + REG_PC += 2; +} + + +void m68k_op_dbne_16(m68ki_cpu_core *cpu) +{ + if(COND_NOT_NE()) + { + uint* r_dst = &DY; + uint res = MASK_OUT_ABOVE_16(*r_dst - 1); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + if(res != 0xffff) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(cpu, offset); + USE_CYCLES(CYC_DBCC_F_NOEXP); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_DBCC_F_EXP); + return; + } + REG_PC += 2; +} + + +void m68k_op_dbeq_16(m68ki_cpu_core *cpu) +{ + if(COND_NOT_EQ()) + { + uint* r_dst = &DY; + uint res = MASK_OUT_ABOVE_16(*r_dst - 1); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + if(res != 0xffff) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(cpu, offset); + USE_CYCLES(CYC_DBCC_F_NOEXP); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_DBCC_F_EXP); + return; + } + REG_PC += 2; +} + + +void m68k_op_dbvc_16(m68ki_cpu_core *cpu) +{ + if(COND_NOT_VC()) + { + uint* r_dst = &DY; + uint res = MASK_OUT_ABOVE_16(*r_dst - 1); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + if(res != 0xffff) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(cpu, offset); + USE_CYCLES(CYC_DBCC_F_NOEXP); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_DBCC_F_EXP); + return; + } + REG_PC += 2; +} + + +void m68k_op_dbvs_16(m68ki_cpu_core *cpu) +{ + if(COND_NOT_VS()) + { + uint* r_dst = &DY; + uint res = MASK_OUT_ABOVE_16(*r_dst - 1); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + if(res != 0xffff) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(cpu, offset); + USE_CYCLES(CYC_DBCC_F_NOEXP); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_DBCC_F_EXP); + return; + } + REG_PC += 2; +} + + +void m68k_op_dbpl_16(m68ki_cpu_core *cpu) +{ + if(COND_NOT_PL()) + { + uint* r_dst = &DY; + uint res = MASK_OUT_ABOVE_16(*r_dst - 1); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + if(res != 0xffff) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(cpu, offset); + USE_CYCLES(CYC_DBCC_F_NOEXP); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_DBCC_F_EXP); + return; + } + REG_PC += 2; +} + + +void m68k_op_dbmi_16(m68ki_cpu_core *cpu) +{ + if(COND_NOT_MI()) + { + uint* r_dst = &DY; + uint res = MASK_OUT_ABOVE_16(*r_dst - 1); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + if(res != 0xffff) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(cpu, offset); + USE_CYCLES(CYC_DBCC_F_NOEXP); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_DBCC_F_EXP); + return; + } + REG_PC += 2; +} + + +void m68k_op_dbge_16(m68ki_cpu_core *cpu) +{ + if(COND_NOT_GE()) + { + uint* r_dst = &DY; + uint res = MASK_OUT_ABOVE_16(*r_dst - 1); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + if(res != 0xffff) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(cpu, offset); + USE_CYCLES(CYC_DBCC_F_NOEXP); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_DBCC_F_EXP); + return; + } + REG_PC += 2; +} + + +void m68k_op_dblt_16(m68ki_cpu_core *cpu) +{ + if(COND_NOT_LT()) + { + uint* r_dst = &DY; + uint res = MASK_OUT_ABOVE_16(*r_dst - 1); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + if(res != 0xffff) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(cpu, offset); + USE_CYCLES(CYC_DBCC_F_NOEXP); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_DBCC_F_EXP); + return; + } + REG_PC += 2; +} + + +void m68k_op_dbgt_16(m68ki_cpu_core *cpu) +{ + if(COND_NOT_GT()) + { + uint* r_dst = &DY; + uint res = MASK_OUT_ABOVE_16(*r_dst - 1); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + if(res != 0xffff) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(cpu, offset); + USE_CYCLES(CYC_DBCC_F_NOEXP); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_DBCC_F_EXP); + return; + } + REG_PC += 2; +} + + +void m68k_op_dble_16(m68ki_cpu_core *cpu) +{ + if(COND_NOT_LE()) + { + uint* r_dst = &DY; + uint res = MASK_OUT_ABOVE_16(*r_dst - 1); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + if(res != 0xffff) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(cpu, offset); + USE_CYCLES(CYC_DBCC_F_NOEXP); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_DBCC_F_EXP); + return; + } + REG_PC += 2; +} + + +void m68k_op_divs_16_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + sint src = MAKE_INT_16(DY); + sint quotient; + sint remainder; + + if(src != 0) + { + if((uint32)*r_dst == 0x80000000 && src == -1) + { + FLAG_Z = 0; + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = 0; + return; + } + + quotient = MAKE_INT_32(*r_dst) / src; + remainder = MAKE_INT_32(*r_dst) % src; + + if(quotient == MAKE_INT_16(quotient)) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); +} + + +void m68k_op_divs_16_ai(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + sint src = MAKE_INT_16(OPER_AY_AI_16(cpu)); + sint quotient; + sint remainder; + + if(src != 0) + { + if((uint32)*r_dst == 0x80000000 && src == -1) + { + FLAG_Z = 0; + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = 0; + return; + } + + quotient = MAKE_INT_32(*r_dst) / src; + remainder = MAKE_INT_32(*r_dst) % src; + + if(quotient == MAKE_INT_16(quotient)) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); +} + + +void m68k_op_divs_16_pi(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + sint src = MAKE_INT_16(OPER_AY_PI_16(cpu)); + sint quotient; + sint remainder; + + if(src != 0) + { + if((uint32)*r_dst == 0x80000000 && src == -1) + { + FLAG_Z = 0; + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = 0; + return; + } + + quotient = MAKE_INT_32(*r_dst) / src; + remainder = MAKE_INT_32(*r_dst) % src; + + if(quotient == MAKE_INT_16(quotient)) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); +} + + +void m68k_op_divs_16_pd(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + sint src = MAKE_INT_16(OPER_AY_PD_16(cpu)); + sint quotient; + sint remainder; + + if(src != 0) + { + if((uint32)*r_dst == 0x80000000 && src == -1) + { + FLAG_Z = 0; + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = 0; + return; + } + + quotient = MAKE_INT_32(*r_dst) / src; + remainder = MAKE_INT_32(*r_dst) % src; + + if(quotient == MAKE_INT_16(quotient)) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); +} + + +void m68k_op_divs_16_di(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + sint src = MAKE_INT_16(OPER_AY_DI_16(cpu)); + sint quotient; + sint remainder; + + if(src != 0) + { + if((uint32)*r_dst == 0x80000000 && src == -1) + { + FLAG_Z = 0; + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = 0; + return; + } + + quotient = MAKE_INT_32(*r_dst) / src; + remainder = MAKE_INT_32(*r_dst) % src; + + if(quotient == MAKE_INT_16(quotient)) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); +} + + +void m68k_op_divs_16_ix(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + sint src = MAKE_INT_16(OPER_AY_IX_16(cpu)); + sint quotient; + sint remainder; + + if(src != 0) + { + if((uint32)*r_dst == 0x80000000 && src == -1) + { + FLAG_Z = 0; + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = 0; + return; + } + + quotient = MAKE_INT_32(*r_dst) / src; + remainder = MAKE_INT_32(*r_dst) % src; + + if(quotient == MAKE_INT_16(quotient)) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); +} + + +void m68k_op_divs_16_aw(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + sint src = MAKE_INT_16(OPER_AW_16(cpu)); + sint quotient; + sint remainder; + + if(src != 0) + { + if((uint32)*r_dst == 0x80000000 && src == -1) + { + FLAG_Z = 0; + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = 0; + return; + } + + quotient = MAKE_INT_32(*r_dst) / src; + remainder = MAKE_INT_32(*r_dst) % src; + + if(quotient == MAKE_INT_16(quotient)) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); +} + + +void m68k_op_divs_16_al(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + sint src = MAKE_INT_16(OPER_AL_16(cpu)); + sint quotient; + sint remainder; + + if(src != 0) + { + if((uint32)*r_dst == 0x80000000 && src == -1) + { + FLAG_Z = 0; + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = 0; + return; + } + + quotient = MAKE_INT_32(*r_dst) / src; + remainder = MAKE_INT_32(*r_dst) % src; + + if(quotient == MAKE_INT_16(quotient)) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); +} + + +void m68k_op_divs_16_pcdi(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + sint src = MAKE_INT_16(OPER_PCDI_16(cpu)); + sint quotient; + sint remainder; + + if(src != 0) + { + if((uint32)*r_dst == 0x80000000 && src == -1) + { + FLAG_Z = 0; + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = 0; + return; + } + + quotient = MAKE_INT_32(*r_dst) / src; + remainder = MAKE_INT_32(*r_dst) % src; + + if(quotient == MAKE_INT_16(quotient)) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); +} + + +void m68k_op_divs_16_pcix(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + sint src = MAKE_INT_16(OPER_PCIX_16(cpu)); + sint quotient; + sint remainder; + + if(src != 0) + { + if((uint32)*r_dst == 0x80000000 && src == -1) + { + FLAG_Z = 0; + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = 0; + return; + } + + quotient = MAKE_INT_32(*r_dst) / src; + remainder = MAKE_INT_32(*r_dst) % src; + + if(quotient == MAKE_INT_16(quotient)) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); +} + + +void m68k_op_divs_16_i(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + sint src = MAKE_INT_16(OPER_I_16()); + sint quotient; + sint remainder; + + if(src != 0) + { + if((uint32)*r_dst == 0x80000000 && src == -1) + { + FLAG_Z = 0; + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = 0; + return; + } + + quotient = MAKE_INT_32(*r_dst) / src; + remainder = MAKE_INT_32(*r_dst) % src; + + if(quotient == MAKE_INT_16(quotient)) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); +} + + +void m68k_op_divu_16_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_16(DY); + + if(src != 0) + { + uint quotient = *r_dst / src; + uint remainder = *r_dst % src; + + if(quotient < 0x10000) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); +} + + +void m68k_op_divu_16_ai(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_AI_16(cpu); + + if(src != 0) + { + uint quotient = *r_dst / src; + uint remainder = *r_dst % src; + + if(quotient < 0x10000) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); +} + + +void m68k_op_divu_16_pi(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_PI_16(cpu); + + if(src != 0) + { + uint quotient = *r_dst / src; + uint remainder = *r_dst % src; + + if(quotient < 0x10000) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); +} + + +void m68k_op_divu_16_pd(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_PD_16(cpu); + + if(src != 0) + { + uint quotient = *r_dst / src; + uint remainder = *r_dst % src; + + if(quotient < 0x10000) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); +} + + +void m68k_op_divu_16_di(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_DI_16(cpu); + + if(src != 0) + { + uint quotient = *r_dst / src; + uint remainder = *r_dst % src; + + if(quotient < 0x10000) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); +} + + +void m68k_op_divu_16_ix(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_IX_16(cpu); + + if(src != 0) + { + uint quotient = *r_dst / src; + uint remainder = *r_dst % src; + + if(quotient < 0x10000) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); +} + + +void m68k_op_divu_16_aw(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AW_16(cpu); + + if(src != 0) + { + uint quotient = *r_dst / src; + uint remainder = *r_dst % src; + + if(quotient < 0x10000) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); +} + + +void m68k_op_divu_16_al(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AL_16(cpu); + + if(src != 0) + { + uint quotient = *r_dst / src; + uint remainder = *r_dst % src; + + if(quotient < 0x10000) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); +} + + +void m68k_op_divu_16_pcdi(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_PCDI_16(cpu); + + if(src != 0) + { + uint quotient = *r_dst / src; + uint remainder = *r_dst % src; + + if(quotient < 0x10000) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); +} + + +void m68k_op_divu_16_pcix(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_PCIX_16(cpu); + + if(src != 0) + { + uint quotient = *r_dst / src; + uint remainder = *r_dst % src; + + if(quotient < 0x10000) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); +} + + +void m68k_op_divu_16_i(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_I_16(); + + if(src != 0) + { + uint quotient = *r_dst / src; + uint remainder = *r_dst % src; + + if(quotient < 0x10000) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); +} + + +void m68k_op_divl_32_d(m68ki_cpu_core *cpu) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 divisor = DY; + uint64 dividend = 0; + uint64 quotient = 0; + uint64 remainder = 0; + + if(divisor != 0) + { + if(BIT_A(word2)) /* 64 bit */ + { + dividend = REG_D[word2 & 7]; + dividend <<= 32; + dividend |= REG_D[(word2 >> 12) & 7]; + + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)dividend / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)dividend % (sint64)((sint32)divisor)); + if((sint64)quotient != (sint64)((sint32)quotient)) + { + FLAG_V = VFLAG_SET; + return; + } + } + else /* unsigned */ + { + quotient = dividend / divisor; + if(quotient > 0xffffffff) + { + FLAG_V = VFLAG_SET; + return; + } + remainder = dividend % divisor; + } + } + else /* 32 bit */ + { + dividend = REG_D[(word2 >> 12) & 7]; + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)((sint32)dividend) / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)((sint32)dividend) % (sint64)((sint32)divisor)); + } + else /* unsigned */ + { + quotient = dividend / divisor; + remainder = dividend % divisor; + } + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(cpu); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint divisor = DY; + uint dividend_hi = REG_D[word2 & 7]; + uint dividend_lo = REG_D[(word2 >> 12) & 7]; + uint quotient = 0; + uint remainder = 0; + uint dividend_neg = 0; + uint divisor_neg = 0; + sint i; + uint overflow; + + if(divisor != 0) + { + /* quad / long : long quotient, long remainder */ + if(BIT_A(word2)) + { + if(BIT_B(word2)) /* signed */ + { + /* special case in signed divide */ + if(dividend_hi == 0 && dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + REG_D[word2 & 7] = 0; + REG_D[(word2 >> 12) & 7] = 0x80000000; + + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + if(GET_MSB_32(dividend_hi)) + { + dividend_neg = 1; + dividend_hi = (uint)MASK_OUT_ABOVE_32((-(sint)dividend_hi) - (dividend_lo != 0)); + dividend_lo = (uint)MASK_OUT_ABOVE_32(-(sint)dividend_lo); + } + if(GET_MSB_32(divisor)) + { + divisor_neg = 1; + divisor = (uint)MASK_OUT_ABOVE_32(-(sint)divisor); + + } + } + + /* if the upper long is greater than the divisor, we're overflowing. */ + if(dividend_hi >= divisor) + { + FLAG_V = VFLAG_SET; + return; + } + + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + remainder = (remainder << 1) + ((dividend_hi >> i) & 1); + if(remainder >= divisor) + { + remainder -= divisor; + quotient++; + } + } + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + overflow = GET_MSB_32(remainder); + remainder = (remainder << 1) + ((dividend_lo >> i) & 1); + if(remainder >= divisor || overflow) + { + remainder -= divisor; + quotient++; + } + } + + if(BIT_B(word2)) /* signed */ + { + if(quotient > 0x7fffffff) + { + FLAG_V = VFLAG_SET; + return; + } + if(dividend_neg) + { + remainder = (uint)MASK_OUT_ABOVE_32(-(sint)remainder); + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + if(divisor_neg) + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + + /* long / long: long quotient, maybe long remainder */ + if(BIT_B(word2)) /* signed */ + { + /* Special case in divide */ + if(dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + REG_D[(word2 >> 12) & 7] = 0x80000000; + REG_D[word2 & 7] = 0; + return; + } + REG_D[word2 & 7] = MAKE_INT_32(dividend_lo) % MAKE_INT_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MAKE_INT_32(dividend_lo) / MAKE_INT_32(divisor); + } + else + { + REG_D[word2 & 7] = MASK_OUT_ABOVE_32(dividend_lo) % MASK_OUT_ABOVE_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(dividend_lo) / MASK_OUT_ABOVE_32(divisor); + } + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(cpu); + +#endif +} + + +void m68k_op_divl_32_ai(m68ki_cpu_core *cpu) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 divisor = OPER_AY_AI_32(cpu); + uint64 dividend = 0; + uint64 quotient = 0; + uint64 remainder = 0; + + if(divisor != 0) + { + if(BIT_A(word2)) /* 64 bit */ + { + dividend = REG_D[word2 & 7]; + dividend <<= 32; + dividend |= REG_D[(word2 >> 12) & 7]; + + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)dividend / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)dividend % (sint64)((sint32)divisor)); + if((sint64)quotient != (sint64)((sint32)quotient)) + { + FLAG_V = VFLAG_SET; + return; + } + } + else /* unsigned */ + { + quotient = dividend / divisor; + if(quotient > 0xffffffff) + { + FLAG_V = VFLAG_SET; + return; + } + remainder = dividend % divisor; + } + } + else /* 32 bit */ + { + dividend = REG_D[(word2 >> 12) & 7]; + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)((sint32)dividend) / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)((sint32)dividend) % (sint64)((sint32)divisor)); + } + else /* unsigned */ + { + quotient = dividend / divisor; + remainder = dividend % divisor; + } + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(cpu); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint divisor = OPER_AY_AI_32(cpu); + uint dividend_hi = REG_D[word2 & 7]; + uint dividend_lo = REG_D[(word2 >> 12) & 7]; + uint quotient = 0; + uint remainder = 0; + uint dividend_neg = 0; + uint divisor_neg = 0; + sint i; + uint overflow; + + if(divisor != 0) + { + /* quad / long : long quotient, long remainder */ + if(BIT_A(word2)) + { + if(BIT_B(word2)) /* signed */ + { + /* special case in signed divide */ + if(dividend_hi == 0 && dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + REG_D[word2 & 7] = 0; + REG_D[(word2 >> 12) & 7] = 0x80000000; + + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + if(GET_MSB_32(dividend_hi)) + { + dividend_neg = 1; + dividend_hi = (uint)MASK_OUT_ABOVE_32((-(sint)dividend_hi) - (dividend_lo != 0)); + dividend_lo = (uint)MASK_OUT_ABOVE_32(-(sint)dividend_lo); + } + if(GET_MSB_32(divisor)) + { + divisor_neg = 1; + divisor = (uint)MASK_OUT_ABOVE_32(-(sint)divisor); + + } + } + + /* if the upper long is greater than the divisor, we're overflowing. */ + if(dividend_hi >= divisor) + { + FLAG_V = VFLAG_SET; + return; + } + + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + remainder = (remainder << 1) + ((dividend_hi >> i) & 1); + if(remainder >= divisor) + { + remainder -= divisor; + quotient++; + } + } + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + overflow = GET_MSB_32(remainder); + remainder = (remainder << 1) + ((dividend_lo >> i) & 1); + if(remainder >= divisor || overflow) + { + remainder -= divisor; + quotient++; + } + } + + if(BIT_B(word2)) /* signed */ + { + if(quotient > 0x7fffffff) + { + FLAG_V = VFLAG_SET; + return; + } + if(dividend_neg) + { + remainder = (uint)MASK_OUT_ABOVE_32(-(sint)remainder); + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + if(divisor_neg) + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + + /* long / long: long quotient, maybe long remainder */ + if(BIT_B(word2)) /* signed */ + { + /* Special case in divide */ + if(dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + REG_D[(word2 >> 12) & 7] = 0x80000000; + REG_D[word2 & 7] = 0; + return; + } + REG_D[word2 & 7] = MAKE_INT_32(dividend_lo) % MAKE_INT_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MAKE_INT_32(dividend_lo) / MAKE_INT_32(divisor); + } + else + { + REG_D[word2 & 7] = MASK_OUT_ABOVE_32(dividend_lo) % MASK_OUT_ABOVE_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(dividend_lo) / MASK_OUT_ABOVE_32(divisor); + } + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(cpu); + +#endif +} + + +void m68k_op_divl_32_pi(m68ki_cpu_core *cpu) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 divisor = OPER_AY_PI_32(cpu); + uint64 dividend = 0; + uint64 quotient = 0; + uint64 remainder = 0; + + if(divisor != 0) + { + if(BIT_A(word2)) /* 64 bit */ + { + dividend = REG_D[word2 & 7]; + dividend <<= 32; + dividend |= REG_D[(word2 >> 12) & 7]; + + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)dividend / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)dividend % (sint64)((sint32)divisor)); + if((sint64)quotient != (sint64)((sint32)quotient)) + { + FLAG_V = VFLAG_SET; + return; + } + } + else /* unsigned */ + { + quotient = dividend / divisor; + if(quotient > 0xffffffff) + { + FLAG_V = VFLAG_SET; + return; + } + remainder = dividend % divisor; + } + } + else /* 32 bit */ + { + dividend = REG_D[(word2 >> 12) & 7]; + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)((sint32)dividend) / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)((sint32)dividend) % (sint64)((sint32)divisor)); + } + else /* unsigned */ + { + quotient = dividend / divisor; + remainder = dividend % divisor; + } + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(cpu); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint divisor = OPER_AY_PI_32(cpu); + uint dividend_hi = REG_D[word2 & 7]; + uint dividend_lo = REG_D[(word2 >> 12) & 7]; + uint quotient = 0; + uint remainder = 0; + uint dividend_neg = 0; + uint divisor_neg = 0; + sint i; + uint overflow; + + if(divisor != 0) + { + /* quad / long : long quotient, long remainder */ + if(BIT_A(word2)) + { + if(BIT_B(word2)) /* signed */ + { + /* special case in signed divide */ + if(dividend_hi == 0 && dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + REG_D[word2 & 7] = 0; + REG_D[(word2 >> 12) & 7] = 0x80000000; + + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + if(GET_MSB_32(dividend_hi)) + { + dividend_neg = 1; + dividend_hi = (uint)MASK_OUT_ABOVE_32((-(sint)dividend_hi) - (dividend_lo != 0)); + dividend_lo = (uint)MASK_OUT_ABOVE_32(-(sint)dividend_lo); + } + if(GET_MSB_32(divisor)) + { + divisor_neg = 1; + divisor = (uint)MASK_OUT_ABOVE_32(-(sint)divisor); + + } + } + + /* if the upper long is greater than the divisor, we're overflowing. */ + if(dividend_hi >= divisor) + { + FLAG_V = VFLAG_SET; + return; + } + + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + remainder = (remainder << 1) + ((dividend_hi >> i) & 1); + if(remainder >= divisor) + { + remainder -= divisor; + quotient++; + } + } + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + overflow = GET_MSB_32(remainder); + remainder = (remainder << 1) + ((dividend_lo >> i) & 1); + if(remainder >= divisor || overflow) + { + remainder -= divisor; + quotient++; + } + } + + if(BIT_B(word2)) /* signed */ + { + if(quotient > 0x7fffffff) + { + FLAG_V = VFLAG_SET; + return; + } + if(dividend_neg) + { + remainder = (uint)MASK_OUT_ABOVE_32(-(sint)remainder); + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + if(divisor_neg) + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + + /* long / long: long quotient, maybe long remainder */ + if(BIT_B(word2)) /* signed */ + { + /* Special case in divide */ + if(dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + REG_D[(word2 >> 12) & 7] = 0x80000000; + REG_D[word2 & 7] = 0; + return; + } + REG_D[word2 & 7] = MAKE_INT_32(dividend_lo) % MAKE_INT_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MAKE_INT_32(dividend_lo) / MAKE_INT_32(divisor); + } + else + { + REG_D[word2 & 7] = MASK_OUT_ABOVE_32(dividend_lo) % MASK_OUT_ABOVE_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(dividend_lo) / MASK_OUT_ABOVE_32(divisor); + } + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(cpu); + +#endif +} + + +void m68k_op_divl_32_pd(m68ki_cpu_core *cpu) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 divisor = OPER_AY_PD_32(cpu); + uint64 dividend = 0; + uint64 quotient = 0; + uint64 remainder = 0; + + if(divisor != 0) + { + if(BIT_A(word2)) /* 64 bit */ + { + dividend = REG_D[word2 & 7]; + dividend <<= 32; + dividend |= REG_D[(word2 >> 12) & 7]; + + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)dividend / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)dividend % (sint64)((sint32)divisor)); + if((sint64)quotient != (sint64)((sint32)quotient)) + { + FLAG_V = VFLAG_SET; + return; + } + } + else /* unsigned */ + { + quotient = dividend / divisor; + if(quotient > 0xffffffff) + { + FLAG_V = VFLAG_SET; + return; + } + remainder = dividend % divisor; + } + } + else /* 32 bit */ + { + dividend = REG_D[(word2 >> 12) & 7]; + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)((sint32)dividend) / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)((sint32)dividend) % (sint64)((sint32)divisor)); + } + else /* unsigned */ + { + quotient = dividend / divisor; + remainder = dividend % divisor; + } + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(cpu); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint divisor = OPER_AY_PD_32(cpu); + uint dividend_hi = REG_D[word2 & 7]; + uint dividend_lo = REG_D[(word2 >> 12) & 7]; + uint quotient = 0; + uint remainder = 0; + uint dividend_neg = 0; + uint divisor_neg = 0; + sint i; + uint overflow; + + if(divisor != 0) + { + /* quad / long : long quotient, long remainder */ + if(BIT_A(word2)) + { + if(BIT_B(word2)) /* signed */ + { + /* special case in signed divide */ + if(dividend_hi == 0 && dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + REG_D[word2 & 7] = 0; + REG_D[(word2 >> 12) & 7] = 0x80000000; + + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + if(GET_MSB_32(dividend_hi)) + { + dividend_neg = 1; + dividend_hi = (uint)MASK_OUT_ABOVE_32((-(sint)dividend_hi) - (dividend_lo != 0)); + dividend_lo = (uint)MASK_OUT_ABOVE_32(-(sint)dividend_lo); + } + if(GET_MSB_32(divisor)) + { + divisor_neg = 1; + divisor = (uint)MASK_OUT_ABOVE_32(-(sint)divisor); + + } + } + + /* if the upper long is greater than the divisor, we're overflowing. */ + if(dividend_hi >= divisor) + { + FLAG_V = VFLAG_SET; + return; + } + + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + remainder = (remainder << 1) + ((dividend_hi >> i) & 1); + if(remainder >= divisor) + { + remainder -= divisor; + quotient++; + } + } + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + overflow = GET_MSB_32(remainder); + remainder = (remainder << 1) + ((dividend_lo >> i) & 1); + if(remainder >= divisor || overflow) + { + remainder -= divisor; + quotient++; + } + } + + if(BIT_B(word2)) /* signed */ + { + if(quotient > 0x7fffffff) + { + FLAG_V = VFLAG_SET; + return; + } + if(dividend_neg) + { + remainder = (uint)MASK_OUT_ABOVE_32(-(sint)remainder); + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + if(divisor_neg) + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + + /* long / long: long quotient, maybe long remainder */ + if(BIT_B(word2)) /* signed */ + { + /* Special case in divide */ + if(dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + REG_D[(word2 >> 12) & 7] = 0x80000000; + REG_D[word2 & 7] = 0; + return; + } + REG_D[word2 & 7] = MAKE_INT_32(dividend_lo) % MAKE_INT_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MAKE_INT_32(dividend_lo) / MAKE_INT_32(divisor); + } + else + { + REG_D[word2 & 7] = MASK_OUT_ABOVE_32(dividend_lo) % MASK_OUT_ABOVE_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(dividend_lo) / MASK_OUT_ABOVE_32(divisor); + } + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(cpu); + +#endif +} + + +void m68k_op_divl_32_di(m68ki_cpu_core *cpu) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 divisor = OPER_AY_DI_32(cpu); + uint64 dividend = 0; + uint64 quotient = 0; + uint64 remainder = 0; + + if(divisor != 0) + { + if(BIT_A(word2)) /* 64 bit */ + { + dividend = REG_D[word2 & 7]; + dividend <<= 32; + dividend |= REG_D[(word2 >> 12) & 7]; + + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)dividend / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)dividend % (sint64)((sint32)divisor)); + if((sint64)quotient != (sint64)((sint32)quotient)) + { + FLAG_V = VFLAG_SET; + return; + } + } + else /* unsigned */ + { + quotient = dividend / divisor; + if(quotient > 0xffffffff) + { + FLAG_V = VFLAG_SET; + return; + } + remainder = dividend % divisor; + } + } + else /* 32 bit */ + { + dividend = REG_D[(word2 >> 12) & 7]; + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)((sint32)dividend) / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)((sint32)dividend) % (sint64)((sint32)divisor)); + } + else /* unsigned */ + { + quotient = dividend / divisor; + remainder = dividend % divisor; + } + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(cpu); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint divisor = OPER_AY_DI_32(cpu); + uint dividend_hi = REG_D[word2 & 7]; + uint dividend_lo = REG_D[(word2 >> 12) & 7]; + uint quotient = 0; + uint remainder = 0; + uint dividend_neg = 0; + uint divisor_neg = 0; + sint i; + uint overflow; + + if(divisor != 0) + { + /* quad / long : long quotient, long remainder */ + if(BIT_A(word2)) + { + if(BIT_B(word2)) /* signed */ + { + /* special case in signed divide */ + if(dividend_hi == 0 && dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + REG_D[word2 & 7] = 0; + REG_D[(word2 >> 12) & 7] = 0x80000000; + + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + if(GET_MSB_32(dividend_hi)) + { + dividend_neg = 1; + dividend_hi = (uint)MASK_OUT_ABOVE_32((-(sint)dividend_hi) - (dividend_lo != 0)); + dividend_lo = (uint)MASK_OUT_ABOVE_32(-(sint)dividend_lo); + } + if(GET_MSB_32(divisor)) + { + divisor_neg = 1; + divisor = (uint)MASK_OUT_ABOVE_32(-(sint)divisor); + + } + } + + /* if the upper long is greater than the divisor, we're overflowing. */ + if(dividend_hi >= divisor) + { + FLAG_V = VFLAG_SET; + return; + } + + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + remainder = (remainder << 1) + ((dividend_hi >> i) & 1); + if(remainder >= divisor) + { + remainder -= divisor; + quotient++; + } + } + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + overflow = GET_MSB_32(remainder); + remainder = (remainder << 1) + ((dividend_lo >> i) & 1); + if(remainder >= divisor || overflow) + { + remainder -= divisor; + quotient++; + } + } + + if(BIT_B(word2)) /* signed */ + { + if(quotient > 0x7fffffff) + { + FLAG_V = VFLAG_SET; + return; + } + if(dividend_neg) + { + remainder = (uint)MASK_OUT_ABOVE_32(-(sint)remainder); + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + if(divisor_neg) + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + + /* long / long: long quotient, maybe long remainder */ + if(BIT_B(word2)) /* signed */ + { + /* Special case in divide */ + if(dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + REG_D[(word2 >> 12) & 7] = 0x80000000; + REG_D[word2 & 7] = 0; + return; + } + REG_D[word2 & 7] = MAKE_INT_32(dividend_lo) % MAKE_INT_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MAKE_INT_32(dividend_lo) / MAKE_INT_32(divisor); + } + else + { + REG_D[word2 & 7] = MASK_OUT_ABOVE_32(dividend_lo) % MASK_OUT_ABOVE_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(dividend_lo) / MASK_OUT_ABOVE_32(divisor); + } + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(cpu); + +#endif +} + + +void m68k_op_divl_32_ix(m68ki_cpu_core *cpu) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 divisor = OPER_AY_IX_32(cpu); + uint64 dividend = 0; + uint64 quotient = 0; + uint64 remainder = 0; + + if(divisor != 0) + { + if(BIT_A(word2)) /* 64 bit */ + { + dividend = REG_D[word2 & 7]; + dividend <<= 32; + dividend |= REG_D[(word2 >> 12) & 7]; + + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)dividend / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)dividend % (sint64)((sint32)divisor)); + if((sint64)quotient != (sint64)((sint32)quotient)) + { + FLAG_V = VFLAG_SET; + return; + } + } + else /* unsigned */ + { + quotient = dividend / divisor; + if(quotient > 0xffffffff) + { + FLAG_V = VFLAG_SET; + return; + } + remainder = dividend % divisor; + } + } + else /* 32 bit */ + { + dividend = REG_D[(word2 >> 12) & 7]; + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)((sint32)dividend) / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)((sint32)dividend) % (sint64)((sint32)divisor)); + } + else /* unsigned */ + { + quotient = dividend / divisor; + remainder = dividend % divisor; + } + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(cpu); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint divisor = OPER_AY_IX_32(cpu); + uint dividend_hi = REG_D[word2 & 7]; + uint dividend_lo = REG_D[(word2 >> 12) & 7]; + uint quotient = 0; + uint remainder = 0; + uint dividend_neg = 0; + uint divisor_neg = 0; + sint i; + uint overflow; + + if(divisor != 0) + { + /* quad / long : long quotient, long remainder */ + if(BIT_A(word2)) + { + if(BIT_B(word2)) /* signed */ + { + /* special case in signed divide */ + if(dividend_hi == 0 && dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + REG_D[word2 & 7] = 0; + REG_D[(word2 >> 12) & 7] = 0x80000000; + + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + if(GET_MSB_32(dividend_hi)) + { + dividend_neg = 1; + dividend_hi = (uint)MASK_OUT_ABOVE_32((-(sint)dividend_hi) - (dividend_lo != 0)); + dividend_lo = (uint)MASK_OUT_ABOVE_32(-(sint)dividend_lo); + } + if(GET_MSB_32(divisor)) + { + divisor_neg = 1; + divisor = (uint)MASK_OUT_ABOVE_32(-(sint)divisor); + + } + } + + /* if the upper long is greater than the divisor, we're overflowing. */ + if(dividend_hi >= divisor) + { + FLAG_V = VFLAG_SET; + return; + } + + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + remainder = (remainder << 1) + ((dividend_hi >> i) & 1); + if(remainder >= divisor) + { + remainder -= divisor; + quotient++; + } + } + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + overflow = GET_MSB_32(remainder); + remainder = (remainder << 1) + ((dividend_lo >> i) & 1); + if(remainder >= divisor || overflow) + { + remainder -= divisor; + quotient++; + } + } + + if(BIT_B(word2)) /* signed */ + { + if(quotient > 0x7fffffff) + { + FLAG_V = VFLAG_SET; + return; + } + if(dividend_neg) + { + remainder = (uint)MASK_OUT_ABOVE_32(-(sint)remainder); + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + if(divisor_neg) + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + + /* long / long: long quotient, maybe long remainder */ + if(BIT_B(word2)) /* signed */ + { + /* Special case in divide */ + if(dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + REG_D[(word2 >> 12) & 7] = 0x80000000; + REG_D[word2 & 7] = 0; + return; + } + REG_D[word2 & 7] = MAKE_INT_32(dividend_lo) % MAKE_INT_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MAKE_INT_32(dividend_lo) / MAKE_INT_32(divisor); + } + else + { + REG_D[word2 & 7] = MASK_OUT_ABOVE_32(dividend_lo) % MASK_OUT_ABOVE_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(dividend_lo) / MASK_OUT_ABOVE_32(divisor); + } + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(cpu); + +#endif +} + + +void m68k_op_divl_32_aw(m68ki_cpu_core *cpu) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 divisor = OPER_AW_32(cpu); + uint64 dividend = 0; + uint64 quotient = 0; + uint64 remainder = 0; + + if(divisor != 0) + { + if(BIT_A(word2)) /* 64 bit */ + { + dividend = REG_D[word2 & 7]; + dividend <<= 32; + dividend |= REG_D[(word2 >> 12) & 7]; + + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)dividend / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)dividend % (sint64)((sint32)divisor)); + if((sint64)quotient != (sint64)((sint32)quotient)) + { + FLAG_V = VFLAG_SET; + return; + } + } + else /* unsigned */ + { + quotient = dividend / divisor; + if(quotient > 0xffffffff) + { + FLAG_V = VFLAG_SET; + return; + } + remainder = dividend % divisor; + } + } + else /* 32 bit */ + { + dividend = REG_D[(word2 >> 12) & 7]; + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)((sint32)dividend) / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)((sint32)dividend) % (sint64)((sint32)divisor)); + } + else /* unsigned */ + { + quotient = dividend / divisor; + remainder = dividend % divisor; + } + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(cpu); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint divisor = OPER_AW_32(cpu); + uint dividend_hi = REG_D[word2 & 7]; + uint dividend_lo = REG_D[(word2 >> 12) & 7]; + uint quotient = 0; + uint remainder = 0; + uint dividend_neg = 0; + uint divisor_neg = 0; + sint i; + uint overflow; + + if(divisor != 0) + { + /* quad / long : long quotient, long remainder */ + if(BIT_A(word2)) + { + if(BIT_B(word2)) /* signed */ + { + /* special case in signed divide */ + if(dividend_hi == 0 && dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + REG_D[word2 & 7] = 0; + REG_D[(word2 >> 12) & 7] = 0x80000000; + + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + if(GET_MSB_32(dividend_hi)) + { + dividend_neg = 1; + dividend_hi = (uint)MASK_OUT_ABOVE_32((-(sint)dividend_hi) - (dividend_lo != 0)); + dividend_lo = (uint)MASK_OUT_ABOVE_32(-(sint)dividend_lo); + } + if(GET_MSB_32(divisor)) + { + divisor_neg = 1; + divisor = (uint)MASK_OUT_ABOVE_32(-(sint)divisor); + + } + } + + /* if the upper long is greater than the divisor, we're overflowing. */ + if(dividend_hi >= divisor) + { + FLAG_V = VFLAG_SET; + return; + } + + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + remainder = (remainder << 1) + ((dividend_hi >> i) & 1); + if(remainder >= divisor) + { + remainder -= divisor; + quotient++; + } + } + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + overflow = GET_MSB_32(remainder); + remainder = (remainder << 1) + ((dividend_lo >> i) & 1); + if(remainder >= divisor || overflow) + { + remainder -= divisor; + quotient++; + } + } + + if(BIT_B(word2)) /* signed */ + { + if(quotient > 0x7fffffff) + { + FLAG_V = VFLAG_SET; + return; + } + if(dividend_neg) + { + remainder = (uint)MASK_OUT_ABOVE_32(-(sint)remainder); + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + if(divisor_neg) + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + + /* long / long: long quotient, maybe long remainder */ + if(BIT_B(word2)) /* signed */ + { + /* Special case in divide */ + if(dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + REG_D[(word2 >> 12) & 7] = 0x80000000; + REG_D[word2 & 7] = 0; + return; + } + REG_D[word2 & 7] = MAKE_INT_32(dividend_lo) % MAKE_INT_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MAKE_INT_32(dividend_lo) / MAKE_INT_32(divisor); + } + else + { + REG_D[word2 & 7] = MASK_OUT_ABOVE_32(dividend_lo) % MASK_OUT_ABOVE_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(dividend_lo) / MASK_OUT_ABOVE_32(divisor); + } + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(cpu); + +#endif +} + + +void m68k_op_divl_32_al(m68ki_cpu_core *cpu) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 divisor = OPER_AL_32(cpu); + uint64 dividend = 0; + uint64 quotient = 0; + uint64 remainder = 0; + + if(divisor != 0) + { + if(BIT_A(word2)) /* 64 bit */ + { + dividend = REG_D[word2 & 7]; + dividend <<= 32; + dividend |= REG_D[(word2 >> 12) & 7]; + + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)dividend / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)dividend % (sint64)((sint32)divisor)); + if((sint64)quotient != (sint64)((sint32)quotient)) + { + FLAG_V = VFLAG_SET; + return; + } + } + else /* unsigned */ + { + quotient = dividend / divisor; + if(quotient > 0xffffffff) + { + FLAG_V = VFLAG_SET; + return; + } + remainder = dividend % divisor; + } + } + else /* 32 bit */ + { + dividend = REG_D[(word2 >> 12) & 7]; + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)((sint32)dividend) / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)((sint32)dividend) % (sint64)((sint32)divisor)); + } + else /* unsigned */ + { + quotient = dividend / divisor; + remainder = dividend % divisor; + } + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(cpu); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint divisor = OPER_AL_32(cpu); + uint dividend_hi = REG_D[word2 & 7]; + uint dividend_lo = REG_D[(word2 >> 12) & 7]; + uint quotient = 0; + uint remainder = 0; + uint dividend_neg = 0; + uint divisor_neg = 0; + sint i; + uint overflow; + + if(divisor != 0) + { + /* quad / long : long quotient, long remainder */ + if(BIT_A(word2)) + { + if(BIT_B(word2)) /* signed */ + { + /* special case in signed divide */ + if(dividend_hi == 0 && dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + REG_D[word2 & 7] = 0; + REG_D[(word2 >> 12) & 7] = 0x80000000; + + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + if(GET_MSB_32(dividend_hi)) + { + dividend_neg = 1; + dividend_hi = (uint)MASK_OUT_ABOVE_32((-(sint)dividend_hi) - (dividend_lo != 0)); + dividend_lo = (uint)MASK_OUT_ABOVE_32(-(sint)dividend_lo); + } + if(GET_MSB_32(divisor)) + { + divisor_neg = 1; + divisor = (uint)MASK_OUT_ABOVE_32(-(sint)divisor); + + } + } + + /* if the upper long is greater than the divisor, we're overflowing. */ + if(dividend_hi >= divisor) + { + FLAG_V = VFLAG_SET; + return; + } + + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + remainder = (remainder << 1) + ((dividend_hi >> i) & 1); + if(remainder >= divisor) + { + remainder -= divisor; + quotient++; + } + } + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + overflow = GET_MSB_32(remainder); + remainder = (remainder << 1) + ((dividend_lo >> i) & 1); + if(remainder >= divisor || overflow) + { + remainder -= divisor; + quotient++; + } + } + + if(BIT_B(word2)) /* signed */ + { + if(quotient > 0x7fffffff) + { + FLAG_V = VFLAG_SET; + return; + } + if(dividend_neg) + { + remainder = (uint)MASK_OUT_ABOVE_32(-(sint)remainder); + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + if(divisor_neg) + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + + /* long / long: long quotient, maybe long remainder */ + if(BIT_B(word2)) /* signed */ + { + /* Special case in divide */ + if(dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + REG_D[(word2 >> 12) & 7] = 0x80000000; + REG_D[word2 & 7] = 0; + return; + } + REG_D[word2 & 7] = MAKE_INT_32(dividend_lo) % MAKE_INT_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MAKE_INT_32(dividend_lo) / MAKE_INT_32(divisor); + } + else + { + REG_D[word2 & 7] = MASK_OUT_ABOVE_32(dividend_lo) % MASK_OUT_ABOVE_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(dividend_lo) / MASK_OUT_ABOVE_32(divisor); + } + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(cpu); + +#endif +} + + +void m68k_op_divl_32_pcdi(m68ki_cpu_core *cpu) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 divisor = OPER_PCDI_32(cpu); + uint64 dividend = 0; + uint64 quotient = 0; + uint64 remainder = 0; + + if(divisor != 0) + { + if(BIT_A(word2)) /* 64 bit */ + { + dividend = REG_D[word2 & 7]; + dividend <<= 32; + dividend |= REG_D[(word2 >> 12) & 7]; + + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)dividend / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)dividend % (sint64)((sint32)divisor)); + if((sint64)quotient != (sint64)((sint32)quotient)) + { + FLAG_V = VFLAG_SET; + return; + } + } + else /* unsigned */ + { + quotient = dividend / divisor; + if(quotient > 0xffffffff) + { + FLAG_V = VFLAG_SET; + return; + } + remainder = dividend % divisor; + } + } + else /* 32 bit */ + { + dividend = REG_D[(word2 >> 12) & 7]; + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)((sint32)dividend) / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)((sint32)dividend) % (sint64)((sint32)divisor)); + } + else /* unsigned */ + { + quotient = dividend / divisor; + remainder = dividend % divisor; + } + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(cpu); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint divisor = OPER_PCDI_32(cpu); + uint dividend_hi = REG_D[word2 & 7]; + uint dividend_lo = REG_D[(word2 >> 12) & 7]; + uint quotient = 0; + uint remainder = 0; + uint dividend_neg = 0; + uint divisor_neg = 0; + sint i; + uint overflow; + + if(divisor != 0) + { + /* quad / long : long quotient, long remainder */ + if(BIT_A(word2)) + { + if(BIT_B(word2)) /* signed */ + { + /* special case in signed divide */ + if(dividend_hi == 0 && dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + REG_D[word2 & 7] = 0; + REG_D[(word2 >> 12) & 7] = 0x80000000; + + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + if(GET_MSB_32(dividend_hi)) + { + dividend_neg = 1; + dividend_hi = (uint)MASK_OUT_ABOVE_32((-(sint)dividend_hi) - (dividend_lo != 0)); + dividend_lo = (uint)MASK_OUT_ABOVE_32(-(sint)dividend_lo); + } + if(GET_MSB_32(divisor)) + { + divisor_neg = 1; + divisor = (uint)MASK_OUT_ABOVE_32(-(sint)divisor); + + } + } + + /* if the upper long is greater than the divisor, we're overflowing. */ + if(dividend_hi >= divisor) + { + FLAG_V = VFLAG_SET; + return; + } + + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + remainder = (remainder << 1) + ((dividend_hi >> i) & 1); + if(remainder >= divisor) + { + remainder -= divisor; + quotient++; + } + } + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + overflow = GET_MSB_32(remainder); + remainder = (remainder << 1) + ((dividend_lo >> i) & 1); + if(remainder >= divisor || overflow) + { + remainder -= divisor; + quotient++; + } + } + + if(BIT_B(word2)) /* signed */ + { + if(quotient > 0x7fffffff) + { + FLAG_V = VFLAG_SET; + return; + } + if(dividend_neg) + { + remainder = (uint)MASK_OUT_ABOVE_32(-(sint)remainder); + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + if(divisor_neg) + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + + /* long / long: long quotient, maybe long remainder */ + if(BIT_B(word2)) /* signed */ + { + /* Special case in divide */ + if(dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + REG_D[(word2 >> 12) & 7] = 0x80000000; + REG_D[word2 & 7] = 0; + return; + } + REG_D[word2 & 7] = MAKE_INT_32(dividend_lo) % MAKE_INT_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MAKE_INT_32(dividend_lo) / MAKE_INT_32(divisor); + } + else + { + REG_D[word2 & 7] = MASK_OUT_ABOVE_32(dividend_lo) % MASK_OUT_ABOVE_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(dividend_lo) / MASK_OUT_ABOVE_32(divisor); + } + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(cpu); + +#endif +} + + +void m68k_op_divl_32_pcix(m68ki_cpu_core *cpu) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 divisor = OPER_PCIX_32(cpu); + uint64 dividend = 0; + uint64 quotient = 0; + uint64 remainder = 0; + + if(divisor != 0) + { + if(BIT_A(word2)) /* 64 bit */ + { + dividend = REG_D[word2 & 7]; + dividend <<= 32; + dividend |= REG_D[(word2 >> 12) & 7]; + + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)dividend / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)dividend % (sint64)((sint32)divisor)); + if((sint64)quotient != (sint64)((sint32)quotient)) + { + FLAG_V = VFLAG_SET; + return; + } + } + else /* unsigned */ + { + quotient = dividend / divisor; + if(quotient > 0xffffffff) + { + FLAG_V = VFLAG_SET; + return; + } + remainder = dividend % divisor; + } + } + else /* 32 bit */ + { + dividend = REG_D[(word2 >> 12) & 7]; + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)((sint32)dividend) / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)((sint32)dividend) % (sint64)((sint32)divisor)); + } + else /* unsigned */ + { + quotient = dividend / divisor; + remainder = dividend % divisor; + } + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(cpu); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint divisor = OPER_PCIX_32(cpu); + uint dividend_hi = REG_D[word2 & 7]; + uint dividend_lo = REG_D[(word2 >> 12) & 7]; + uint quotient = 0; + uint remainder = 0; + uint dividend_neg = 0; + uint divisor_neg = 0; + sint i; + uint overflow; + + if(divisor != 0) + { + /* quad / long : long quotient, long remainder */ + if(BIT_A(word2)) + { + if(BIT_B(word2)) /* signed */ + { + /* special case in signed divide */ + if(dividend_hi == 0 && dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + REG_D[word2 & 7] = 0; + REG_D[(word2 >> 12) & 7] = 0x80000000; + + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + if(GET_MSB_32(dividend_hi)) + { + dividend_neg = 1; + dividend_hi = (uint)MASK_OUT_ABOVE_32((-(sint)dividend_hi) - (dividend_lo != 0)); + dividend_lo = (uint)MASK_OUT_ABOVE_32(-(sint)dividend_lo); + } + if(GET_MSB_32(divisor)) + { + divisor_neg = 1; + divisor = (uint)MASK_OUT_ABOVE_32(-(sint)divisor); + + } + } + + /* if the upper long is greater than the divisor, we're overflowing. */ + if(dividend_hi >= divisor) + { + FLAG_V = VFLAG_SET; + return; + } + + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + remainder = (remainder << 1) + ((dividend_hi >> i) & 1); + if(remainder >= divisor) + { + remainder -= divisor; + quotient++; + } + } + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + overflow = GET_MSB_32(remainder); + remainder = (remainder << 1) + ((dividend_lo >> i) & 1); + if(remainder >= divisor || overflow) + { + remainder -= divisor; + quotient++; + } + } + + if(BIT_B(word2)) /* signed */ + { + if(quotient > 0x7fffffff) + { + FLAG_V = VFLAG_SET; + return; + } + if(dividend_neg) + { + remainder = (uint)MASK_OUT_ABOVE_32(-(sint)remainder); + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + if(divisor_neg) + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + + /* long / long: long quotient, maybe long remainder */ + if(BIT_B(word2)) /* signed */ + { + /* Special case in divide */ + if(dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + REG_D[(word2 >> 12) & 7] = 0x80000000; + REG_D[word2 & 7] = 0; + return; + } + REG_D[word2 & 7] = MAKE_INT_32(dividend_lo) % MAKE_INT_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MAKE_INT_32(dividend_lo) / MAKE_INT_32(divisor); + } + else + { + REG_D[word2 & 7] = MASK_OUT_ABOVE_32(dividend_lo) % MASK_OUT_ABOVE_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(dividend_lo) / MASK_OUT_ABOVE_32(divisor); + } + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(cpu); + +#endif +} + + +void m68k_op_divl_32_i(m68ki_cpu_core *cpu) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 divisor = OPER_I_32(); + uint64 dividend = 0; + uint64 quotient = 0; + uint64 remainder = 0; + + if(divisor != 0) + { + if(BIT_A(word2)) /* 64 bit */ + { + dividend = REG_D[word2 & 7]; + dividend <<= 32; + dividend |= REG_D[(word2 >> 12) & 7]; + + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)dividend / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)dividend % (sint64)((sint32)divisor)); + if((sint64)quotient != (sint64)((sint32)quotient)) + { + FLAG_V = VFLAG_SET; + return; + } + } + else /* unsigned */ + { + quotient = dividend / divisor; + if(quotient > 0xffffffff) + { + FLAG_V = VFLAG_SET; + return; + } + remainder = dividend % divisor; + } + } + else /* 32 bit */ + { + dividend = REG_D[(word2 >> 12) & 7]; + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)((sint32)dividend) / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)((sint32)dividend) % (sint64)((sint32)divisor)); + } + else /* unsigned */ + { + quotient = dividend / divisor; + remainder = dividend % divisor; + } + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(cpu); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint divisor = OPER_I_32(); + uint dividend_hi = REG_D[word2 & 7]; + uint dividend_lo = REG_D[(word2 >> 12) & 7]; + uint quotient = 0; + uint remainder = 0; + uint dividend_neg = 0; + uint divisor_neg = 0; + sint i; + uint overflow; + + if(divisor != 0) + { + /* quad / long : long quotient, long remainder */ + if(BIT_A(word2)) + { + if(BIT_B(word2)) /* signed */ + { + /* special case in signed divide */ + if(dividend_hi == 0 && dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + REG_D[word2 & 7] = 0; + REG_D[(word2 >> 12) & 7] = 0x80000000; + + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + if(GET_MSB_32(dividend_hi)) + { + dividend_neg = 1; + dividend_hi = (uint)MASK_OUT_ABOVE_32((-(sint)dividend_hi) - (dividend_lo != 0)); + dividend_lo = (uint)MASK_OUT_ABOVE_32(-(sint)dividend_lo); + } + if(GET_MSB_32(divisor)) + { + divisor_neg = 1; + divisor = (uint)MASK_OUT_ABOVE_32(-(sint)divisor); + + } + } + + /* if the upper long is greater than the divisor, we're overflowing. */ + if(dividend_hi >= divisor) + { + FLAG_V = VFLAG_SET; + return; + } + + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + remainder = (remainder << 1) + ((dividend_hi >> i) & 1); + if(remainder >= divisor) + { + remainder -= divisor; + quotient++; + } + } + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + overflow = GET_MSB_32(remainder); + remainder = (remainder << 1) + ((dividend_lo >> i) & 1); + if(remainder >= divisor || overflow) + { + remainder -= divisor; + quotient++; + } + } + + if(BIT_B(word2)) /* signed */ + { + if(quotient > 0x7fffffff) + { + FLAG_V = VFLAG_SET; + return; + } + if(dividend_neg) + { + remainder = (uint)MASK_OUT_ABOVE_32(-(sint)remainder); + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + if(divisor_neg) + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + + /* long / long: long quotient, maybe long remainder */ + if(BIT_B(word2)) /* signed */ + { + /* Special case in divide */ + if(dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + REG_D[(word2 >> 12) & 7] = 0x80000000; + REG_D[word2 & 7] = 0; + return; + } + REG_D[word2 & 7] = MAKE_INT_32(dividend_lo) % MAKE_INT_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MAKE_INT_32(dividend_lo) / MAKE_INT_32(divisor); + } + else + { + REG_D[word2 & 7] = MASK_OUT_ABOVE_32(dividend_lo) % MASK_OUT_ABOVE_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(dividend_lo) / MASK_OUT_ABOVE_32(divisor); + } + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(cpu, EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(cpu); + +#endif +} + + +void m68k_op_eor_8_d(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_8(DY ^= MASK_OUT_ABOVE_8(DX)); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eor_8_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_8(); + uint res = MASK_OUT_ABOVE_8(DX ^ m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eor_8_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_8(); + uint res = MASK_OUT_ABOVE_8(DX ^ m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eor_8_pi7(m68ki_cpu_core *cpu) +{ + uint ea = EA_A7_PI_8(); + uint res = MASK_OUT_ABOVE_8(DX ^ m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eor_8_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_8(); + uint res = MASK_OUT_ABOVE_8(DX ^ m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eor_8_pd7(m68ki_cpu_core *cpu) +{ + uint ea = EA_A7_PD_8(); + uint res = MASK_OUT_ABOVE_8(DX ^ m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eor_8_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_8(); + uint res = MASK_OUT_ABOVE_8(DX ^ m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eor_8_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_8(); + uint res = MASK_OUT_ABOVE_8(DX ^ m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eor_8_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_8(); + uint res = MASK_OUT_ABOVE_8(DX ^ m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eor_8_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_8(); + uint res = MASK_OUT_ABOVE_8(DX ^ m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eor_16_d(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16(DY ^= MASK_OUT_ABOVE_16(DX)); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eor_16_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_16(); + uint res = MASK_OUT_ABOVE_16(DX ^ m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eor_16_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_16(); + uint res = MASK_OUT_ABOVE_16(DX ^ m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eor_16_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_16(); + uint res = MASK_OUT_ABOVE_16(DX ^ m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eor_16_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_16(); + uint res = MASK_OUT_ABOVE_16(DX ^ m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eor_16_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_16(); + uint res = MASK_OUT_ABOVE_16(DX ^ m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eor_16_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_16(); + uint res = MASK_OUT_ABOVE_16(DX ^ m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eor_16_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_16(); + uint res = MASK_OUT_ABOVE_16(DX ^ m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eor_32_d(m68ki_cpu_core *cpu) +{ + uint res = DY ^= DX; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eor_32_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_32(); + uint res = DX ^ m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eor_32_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_32(); + uint res = DX ^ m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eor_32_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_32(); + uint res = DX ^ m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eor_32_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_32(); + uint res = DX ^ m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eor_32_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_32(); + uint res = DX ^ m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eor_32_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_32(); + uint res = DX ^ m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eor_32_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_32(); + uint res = DX ^ m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eori_8_d(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_8(DY ^= OPER_I_8()); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eori_8_ai(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AY_AI_8(); + uint res = src ^ m68ki_read_8(ea); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eori_8_pi(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AY_PI_8(); + uint res = src ^ m68ki_read_8(ea); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eori_8_pi7(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_A7_PI_8(); + uint res = src ^ m68ki_read_8(ea); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eori_8_pd(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AY_PD_8(); + uint res = src ^ m68ki_read_8(ea); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eori_8_pd7(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_A7_PD_8(); + uint res = src ^ m68ki_read_8(ea); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eori_8_di(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AY_DI_8(); + uint res = src ^ m68ki_read_8(ea); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eori_8_ix(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AY_IX_8(); + uint res = src ^ m68ki_read_8(ea); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eori_8_aw(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AW_8(); + uint res = src ^ m68ki_read_8(ea); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eori_8_al(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AL_8(); + uint res = src ^ m68ki_read_8(ea); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eori_16_d(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16(DY ^= OPER_I_16()); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eori_16_ai(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AY_AI_16(); + uint res = src ^ m68ki_read_16(ea); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eori_16_pi(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AY_PI_16(); + uint res = src ^ m68ki_read_16(ea); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eori_16_pd(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AY_PD_16(); + uint res = src ^ m68ki_read_16(ea); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eori_16_di(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AY_DI_16(); + uint res = src ^ m68ki_read_16(ea); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eori_16_ix(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AY_IX_16(); + uint res = src ^ m68ki_read_16(ea); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eori_16_aw(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AW_16(); + uint res = src ^ m68ki_read_16(ea); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eori_16_al(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AL_16(); + uint res = src ^ m68ki_read_16(ea); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eori_32_d(m68ki_cpu_core *cpu) +{ + uint res = DY ^= OPER_I_32(); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eori_32_ai(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AY_AI_32(); + uint res = src ^ m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eori_32_pi(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AY_PI_32(); + uint res = src ^ m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eori_32_pd(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AY_PD_32(); + uint res = src ^ m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eori_32_di(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AY_DI_32(); + uint res = src ^ m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eori_32_ix(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AY_IX_32(); + uint res = src ^ m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eori_32_aw(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AW_32(); + uint res = src ^ m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eori_32_al(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AL_32(); + uint res = src ^ m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_eori_16_toc(m68ki_cpu_core *cpu) +{ + m68ki_set_ccr(cpu, m68ki_get_ccr() ^ OPER_I_16()); +} + + +void m68k_op_eori_16_tos(m68ki_cpu_core *cpu) +{ + if(FLAG_S) + { + uint src = OPER_I_16(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_set_sr(cpu, m68ki_get_sr() ^ src); + return; + } + m68ki_exception_privilege_violation(cpu); +} + + +void m68k_op_exg_32_dd(m68ki_cpu_core *cpu) +{ + uint* reg_a = &DX; + uint* reg_b = &DY; + uint tmp = *reg_a; + *reg_a = *reg_b; + *reg_b = tmp; +} + + +void m68k_op_exg_32_aa(m68ki_cpu_core *cpu) +{ + uint* reg_a = &AX; + uint* reg_b = &AY; + uint tmp = *reg_a; + *reg_a = *reg_b; + *reg_b = tmp; +} + + +void m68k_op_exg_32_da(m68ki_cpu_core *cpu) +{ + uint* reg_a = &DX; + uint* reg_b = &AY; + uint tmp = *reg_a; + *reg_a = *reg_b; + *reg_b = tmp; +} + + +void m68k_op_ext_16(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | MASK_OUT_ABOVE_8(*r_dst) | (GET_MSB_8(*r_dst) ? 0xff00 : 0); + + FLAG_N = NFLAG_16(*r_dst); + FLAG_Z = MASK_OUT_ABOVE_16(*r_dst); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_ext_32(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + + *r_dst = MASK_OUT_ABOVE_16(*r_dst) | (GET_MSB_16(*r_dst) ? 0xffff0000 : 0); + + FLAG_N = NFLAG_32(*r_dst); + FLAG_Z = *r_dst; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_extb_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint* r_dst = &DY; + + *r_dst = MASK_OUT_ABOVE_8(*r_dst) | (GET_MSB_8(*r_dst) ? 0xffffff00 : 0); + + FLAG_N = NFLAG_32(*r_dst); + FLAG_Z = *r_dst; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_illegal(m68ki_cpu_core *cpu) +{ + m68ki_exception_illegal(cpu); +} + + +void m68k_op_jmp_32_ai(m68ki_cpu_core *cpu) +{ + m68ki_jump(cpu, EA_AY_AI_32()); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(REG_PC == REG_PPC) + USE_ALL_CYCLES(); +} + + +void m68k_op_jmp_32_di(m68ki_cpu_core *cpu) +{ + m68ki_jump(cpu, EA_AY_DI_32()); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(REG_PC == REG_PPC) + USE_ALL_CYCLES(); +} + + +void m68k_op_jmp_32_ix(m68ki_cpu_core *cpu) +{ + m68ki_jump(cpu, EA_AY_IX_32()); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(REG_PC == REG_PPC) + USE_ALL_CYCLES(); +} + + +void m68k_op_jmp_32_aw(m68ki_cpu_core *cpu) +{ + m68ki_jump(cpu, EA_AW_32()); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(REG_PC == REG_PPC) + USE_ALL_CYCLES(); +} + + +void m68k_op_jmp_32_al(m68ki_cpu_core *cpu) +{ + m68ki_jump(cpu, EA_AL_32()); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(REG_PC == REG_PPC) + USE_ALL_CYCLES(); +} + + +void m68k_op_jmp_32_pcdi(m68ki_cpu_core *cpu) +{ + m68ki_jump(cpu, EA_PCDI_32()); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(REG_PC == REG_PPC) + USE_ALL_CYCLES(); +} + + +void m68k_op_jmp_32_pcix(m68ki_cpu_core *cpu) +{ + m68ki_jump(cpu, EA_PCIX_32()); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(REG_PC == REG_PPC) + USE_ALL_CYCLES(); +} + + +void m68k_op_jsr_32_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_32(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_push_32(cpu, REG_PC); + m68ki_jump(cpu, ea); +} + + +void m68k_op_jsr_32_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_32(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_push_32(cpu, REG_PC); + m68ki_jump(cpu, ea); +} + + +void m68k_op_jsr_32_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_32(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_push_32(cpu, REG_PC); + m68ki_jump(cpu, ea); +} + + +void m68k_op_jsr_32_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_32(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_push_32(cpu, REG_PC); + m68ki_jump(cpu, ea); +} + + +void m68k_op_jsr_32_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_32(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_push_32(cpu, REG_PC); + m68ki_jump(cpu, ea); +} + + +void m68k_op_jsr_32_pcdi(m68ki_cpu_core *cpu) +{ + uint ea = EA_PCDI_32(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_push_32(cpu, REG_PC); + m68ki_jump(cpu, ea); +} + + +void m68k_op_jsr_32_pcix(m68ki_cpu_core *cpu) +{ + uint ea = EA_PCIX_32(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_push_32(cpu, REG_PC); + m68ki_jump(cpu, ea); +} + + +void m68k_op_lea_32_ai(m68ki_cpu_core *cpu) +{ + AX = EA_AY_AI_32(); +} + + +void m68k_op_lea_32_di(m68ki_cpu_core *cpu) +{ + AX = EA_AY_DI_32(); +} + + +void m68k_op_lea_32_ix(m68ki_cpu_core *cpu) +{ + AX = EA_AY_IX_32(); +} + + +void m68k_op_lea_32_aw(m68ki_cpu_core *cpu) +{ + AX = EA_AW_32(); +} + + +void m68k_op_lea_32_al(m68ki_cpu_core *cpu) +{ + AX = EA_AL_32(); +} + + +void m68k_op_lea_32_pcdi(m68ki_cpu_core *cpu) +{ + AX = EA_PCDI_32(); +} + + +void m68k_op_lea_32_pcix(m68ki_cpu_core *cpu) +{ + AX = EA_PCIX_32(); +} + + +void m68k_op_link_16_a7(m68ki_cpu_core *cpu) +{ + REG_A[7] -= 4; + m68ki_write_32(REG_A[7], REG_A[7]); + REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + MAKE_INT_16(OPER_I_16())); +} + + +void m68k_op_link_16(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AY; + + m68ki_push_32(cpu, *r_dst); + *r_dst = REG_A[7]; + REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + MAKE_INT_16(OPER_I_16())); +} + + +void m68k_op_link_32_a7(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_A[7] -= 4; + m68ki_write_32(REG_A[7], REG_A[7]); + REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + OPER_I_32()); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_link_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint* r_dst = &AY; + + m68ki_push_32(cpu, *r_dst); + *r_dst = REG_A[7]; + REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + OPER_I_32()); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_lsr_8_s(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = src >> shift; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_CLEAR; + FLAG_Z = res; + FLAG_X = FLAG_C = src << (9-shift); + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_lsr_16_s(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = src >> shift; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_CLEAR; + FLAG_Z = res; + FLAG_X = FLAG_C = src << (9-shift); + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_lsr_32_s(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = *r_dst; + uint res = src >> shift; + + *r_dst = res; + + FLAG_N = NFLAG_CLEAR; + FLAG_Z = res; + FLAG_X = FLAG_C = src << (9-shift); + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_lsr_8_r(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = src >> shift; + + if(shift != 0) + { + USE_CYCLES(shift<<CYC_SHIFT); + + if(shift <= 8) + { + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + FLAG_X = FLAG_C = src << (9-shift); + FLAG_N = NFLAG_CLEAR; + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + *r_dst &= 0xffffff00; + FLAG_X = XFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_8(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_lsr_16_r(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = src >> shift; + + if(shift != 0) + { + USE_CYCLES(shift<<CYC_SHIFT); + + if(shift <= 16) + { + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + FLAG_C = FLAG_X = (src >> (shift - 1))<<8; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + *r_dst &= 0xffff0000; + FLAG_X = XFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_16(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_lsr_32_r(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = *r_dst; + uint res = src >> shift; + + if(shift != 0) + { + USE_CYCLES(shift<<CYC_SHIFT); + + if(shift < 32) + { + *r_dst = res; + FLAG_C = FLAG_X = (src >> (shift - 1))<<8; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + *r_dst = 0; + FLAG_X = FLAG_C = (shift == 32 ? GET_MSB_32(src)>>23 : 0); + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_32(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_lsr_16_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_16(); + uint src = m68ki_read_16(ea); + uint res = src >> 1; + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_CLEAR; + FLAG_Z = res; + FLAG_C = FLAG_X = src << 8; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_lsr_16_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_16(); + uint src = m68ki_read_16(ea); + uint res = src >> 1; + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_CLEAR; + FLAG_Z = res; + FLAG_C = FLAG_X = src << 8; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_lsr_16_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_16(); + uint src = m68ki_read_16(ea); + uint res = src >> 1; + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_CLEAR; + FLAG_Z = res; + FLAG_C = FLAG_X = src << 8; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_lsr_16_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_16(); + uint src = m68ki_read_16(ea); + uint res = src >> 1; + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_CLEAR; + FLAG_Z = res; + FLAG_C = FLAG_X = src << 8; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_lsr_16_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_16(); + uint src = m68ki_read_16(ea); + uint res = src >> 1; + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_CLEAR; + FLAG_Z = res; + FLAG_C = FLAG_X = src << 8; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_lsr_16_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_16(); + uint src = m68ki_read_16(ea); + uint res = src >> 1; + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_CLEAR; + FLAG_Z = res; + FLAG_C = FLAG_X = src << 8; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_lsr_16_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_16(); + uint src = m68ki_read_16(ea); + uint res = src >> 1; + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_CLEAR; + FLAG_Z = res; + FLAG_C = FLAG_X = src << 8; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_lsl_8_s(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = MASK_OUT_ABOVE_8(src << shift); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_X = FLAG_C = src << shift; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_lsl_16_s(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = MASK_OUT_ABOVE_16(src << shift); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_X = FLAG_C = src >> (8-shift); + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_lsl_32_s(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32(src << shift); + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_X = FLAG_C = src >> (24-shift); + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_lsl_8_r(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = MASK_OUT_ABOVE_8(src << shift); + + if(shift != 0) + { + USE_CYCLES(shift<<CYC_SHIFT); + + if(shift <= 8) + { + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + FLAG_X = FLAG_C = src << shift; + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + *r_dst &= 0xffffff00; + FLAG_X = XFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_8(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_lsl_16_r(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = MASK_OUT_ABOVE_16(src << shift); + + if(shift != 0) + { + USE_CYCLES(shift<<CYC_SHIFT); + + if(shift <= 16) + { + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + FLAG_X = FLAG_C = (src << shift) >> 8; + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + *r_dst &= 0xffff0000; + FLAG_X = XFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_16(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_lsl_32_r(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32(src << shift); + + if(shift != 0) + { + USE_CYCLES(shift<<CYC_SHIFT); + + if(shift < 32) + { + *r_dst = res; + FLAG_X = FLAG_C = (src >> (32 - shift)) << 8; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + *r_dst = 0; + FLAG_X = FLAG_C = ((shift == 32 ? src & 1 : 0))<<8; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_32(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_lsl_16_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_16(); + uint src = m68ki_read_16(ea); + uint res = MASK_OUT_ABOVE_16(src << 1); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_X = FLAG_C = src >> 7; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_lsl_16_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_16(); + uint src = m68ki_read_16(ea); + uint res = MASK_OUT_ABOVE_16(src << 1); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_X = FLAG_C = src >> 7; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_lsl_16_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_16(); + uint src = m68ki_read_16(ea); + uint res = MASK_OUT_ABOVE_16(src << 1); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_X = FLAG_C = src >> 7; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_lsl_16_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_16(); + uint src = m68ki_read_16(ea); + uint res = MASK_OUT_ABOVE_16(src << 1); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_X = FLAG_C = src >> 7; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_lsl_16_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_16(); + uint src = m68ki_read_16(ea); + uint res = MASK_OUT_ABOVE_16(src << 1); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_X = FLAG_C = src >> 7; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_lsl_16_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_16(); + uint src = m68ki_read_16(ea); + uint res = MASK_OUT_ABOVE_16(src << 1); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_X = FLAG_C = src >> 7; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_lsl_16_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_16(); + uint src = m68ki_read_16(ea); + uint res = MASK_OUT_ABOVE_16(src << 1); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_X = FLAG_C = src >> 7; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_move_8_d_d(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_d_ai(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_AI_8(cpu); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_d_pi(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PI_8(cpu); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_d_pi7(m68ki_cpu_core *cpu) +{ + uint res = OPER_A7_PI_8(cpu); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_d_pd(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PD_8(cpu); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_d_pd7(m68ki_cpu_core *cpu) +{ + uint res = OPER_A7_PD_8(cpu); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_d_di(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_DI_8(cpu); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_d_ix(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_IX_8(cpu); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_d_aw(m68ki_cpu_core *cpu) +{ + uint res = OPER_AW_8(cpu); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_d_al(m68ki_cpu_core *cpu) +{ + uint res = OPER_AL_8(cpu); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_d_pcdi(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCDI_8(cpu); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_d_pcix(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCIX_8(cpu); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_d_i(m68ki_cpu_core *cpu) +{ + uint res = OPER_I_8(); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_ai_d(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_AX_AI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_ai_ai(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_AI_8(cpu); + uint ea = EA_AX_AI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_ai_pi(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PI_8(cpu); + uint ea = EA_AX_AI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_ai_pi7(m68ki_cpu_core *cpu) +{ + uint res = OPER_A7_PI_8(cpu); + uint ea = EA_AX_AI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_ai_pd(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PD_8(cpu); + uint ea = EA_AX_AI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_ai_pd7(m68ki_cpu_core *cpu) +{ + uint res = OPER_A7_PD_8(cpu); + uint ea = EA_AX_AI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_ai_di(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_DI_8(cpu); + uint ea = EA_AX_AI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_ai_ix(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_IX_8(cpu); + uint ea = EA_AX_AI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_ai_aw(m68ki_cpu_core *cpu) +{ + uint res = OPER_AW_8(cpu); + uint ea = EA_AX_AI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_ai_al(m68ki_cpu_core *cpu) +{ + uint res = OPER_AL_8(cpu); + uint ea = EA_AX_AI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_ai_pcdi(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCDI_8(cpu); + uint ea = EA_AX_AI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_ai_pcix(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCIX_8(cpu); + uint ea = EA_AX_AI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_ai_i(m68ki_cpu_core *cpu) +{ + uint res = OPER_I_8(); + uint ea = EA_AX_AI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pi7_d(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_A7_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pi_d(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_AX_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pi7_ai(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_AI_8(cpu); + uint ea = EA_A7_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pi7_pi(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PI_8(cpu); + uint ea = EA_A7_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pi7_pi7(m68ki_cpu_core *cpu) +{ + uint res = OPER_A7_PI_8(cpu); + uint ea = EA_A7_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pi7_pd(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PD_8(cpu); + uint ea = EA_A7_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pi7_pd7(m68ki_cpu_core *cpu) +{ + uint res = OPER_A7_PD_8(cpu); + uint ea = EA_A7_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pi7_di(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_DI_8(cpu); + uint ea = EA_A7_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pi7_ix(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_IX_8(cpu); + uint ea = EA_A7_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pi7_aw(m68ki_cpu_core *cpu) +{ + uint res = OPER_AW_8(cpu); + uint ea = EA_A7_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pi7_al(m68ki_cpu_core *cpu) +{ + uint res = OPER_AL_8(cpu); + uint ea = EA_A7_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pi7_pcdi(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCDI_8(cpu); + uint ea = EA_A7_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pi7_pcix(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCIX_8(cpu); + uint ea = EA_A7_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pi7_i(m68ki_cpu_core *cpu) +{ + uint res = OPER_I_8(); + uint ea = EA_A7_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pi_ai(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_AI_8(cpu); + uint ea = EA_AX_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pi_pi(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PI_8(cpu); + uint ea = EA_AX_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pi_pi7(m68ki_cpu_core *cpu) +{ + uint res = OPER_A7_PI_8(cpu); + uint ea = EA_AX_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pi_pd(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PD_8(cpu); + uint ea = EA_AX_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pi_pd7(m68ki_cpu_core *cpu) +{ + uint res = OPER_A7_PD_8(cpu); + uint ea = EA_AX_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pi_di(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_DI_8(cpu); + uint ea = EA_AX_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pi_ix(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_IX_8(cpu); + uint ea = EA_AX_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pi_aw(m68ki_cpu_core *cpu) +{ + uint res = OPER_AW_8(cpu); + uint ea = EA_AX_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pi_al(m68ki_cpu_core *cpu) +{ + uint res = OPER_AL_8(cpu); + uint ea = EA_AX_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pi_pcdi(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCDI_8(cpu); + uint ea = EA_AX_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pi_pcix(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCIX_8(cpu); + uint ea = EA_AX_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pi_i(m68ki_cpu_core *cpu) +{ + uint res = OPER_I_8(); + uint ea = EA_AX_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pd7_d(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_A7_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pd_d(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_AX_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pd7_ai(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_AI_8(cpu); + uint ea = EA_A7_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pd7_pi(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PI_8(cpu); + uint ea = EA_A7_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pd7_pi7(m68ki_cpu_core *cpu) +{ + uint res = OPER_A7_PI_8(cpu); + uint ea = EA_A7_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pd7_pd(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PD_8(cpu); + uint ea = EA_A7_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pd7_pd7(m68ki_cpu_core *cpu) +{ + uint res = OPER_A7_PD_8(cpu); + uint ea = EA_A7_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pd7_di(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_DI_8(cpu); + uint ea = EA_A7_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pd7_ix(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_IX_8(cpu); + uint ea = EA_A7_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pd7_aw(m68ki_cpu_core *cpu) +{ + uint res = OPER_AW_8(cpu); + uint ea = EA_A7_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pd7_al(m68ki_cpu_core *cpu) +{ + uint res = OPER_AL_8(cpu); + uint ea = EA_A7_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pd7_pcdi(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCDI_8(cpu); + uint ea = EA_A7_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pd7_pcix(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCIX_8(cpu); + uint ea = EA_A7_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pd7_i(m68ki_cpu_core *cpu) +{ + uint res = OPER_I_8(); + uint ea = EA_A7_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pd_ai(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_AI_8(cpu); + uint ea = EA_AX_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pd_pi(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PI_8(cpu); + uint ea = EA_AX_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pd_pi7(m68ki_cpu_core *cpu) +{ + uint res = OPER_A7_PI_8(cpu); + uint ea = EA_AX_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pd_pd(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PD_8(cpu); + uint ea = EA_AX_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pd_pd7(m68ki_cpu_core *cpu) +{ + uint res = OPER_A7_PD_8(cpu); + uint ea = EA_AX_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pd_di(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_DI_8(cpu); + uint ea = EA_AX_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pd_ix(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_IX_8(cpu); + uint ea = EA_AX_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pd_aw(m68ki_cpu_core *cpu) +{ + uint res = OPER_AW_8(cpu); + uint ea = EA_AX_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pd_al(m68ki_cpu_core *cpu) +{ + uint res = OPER_AL_8(cpu); + uint ea = EA_AX_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pd_pcdi(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCDI_8(cpu); + uint ea = EA_AX_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pd_pcix(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCIX_8(cpu); + uint ea = EA_AX_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_pd_i(m68ki_cpu_core *cpu) +{ + uint res = OPER_I_8(); + uint ea = EA_AX_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_di_d(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_AX_DI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_di_ai(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_AI_8(cpu); + uint ea = EA_AX_DI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_di_pi(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PI_8(cpu); + uint ea = EA_AX_DI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_di_pi7(m68ki_cpu_core *cpu) +{ + uint res = OPER_A7_PI_8(cpu); + uint ea = EA_AX_DI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_di_pd(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PD_8(cpu); + uint ea = EA_AX_DI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_di_pd7(m68ki_cpu_core *cpu) +{ + uint res = OPER_A7_PD_8(cpu); + uint ea = EA_AX_DI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_di_di(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_DI_8(cpu); + uint ea = EA_AX_DI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_di_ix(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_IX_8(cpu); + uint ea = EA_AX_DI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_di_aw(m68ki_cpu_core *cpu) +{ + uint res = OPER_AW_8(cpu); + uint ea = EA_AX_DI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_di_al(m68ki_cpu_core *cpu) +{ + uint res = OPER_AL_8(cpu); + uint ea = EA_AX_DI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_di_pcdi(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCDI_8(cpu); + uint ea = EA_AX_DI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_di_pcix(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCIX_8(cpu); + uint ea = EA_AX_DI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_di_i(m68ki_cpu_core *cpu) +{ + uint res = OPER_I_8(); + uint ea = EA_AX_DI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_ix_d(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_AX_IX_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_ix_ai(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_AI_8(cpu); + uint ea = EA_AX_IX_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_ix_pi(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PI_8(cpu); + uint ea = EA_AX_IX_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_ix_pi7(m68ki_cpu_core *cpu) +{ + uint res = OPER_A7_PI_8(cpu); + uint ea = EA_AX_IX_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_ix_pd(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PD_8(cpu); + uint ea = EA_AX_IX_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_ix_pd7(m68ki_cpu_core *cpu) +{ + uint res = OPER_A7_PD_8(cpu); + uint ea = EA_AX_IX_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_ix_di(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_DI_8(cpu); + uint ea = EA_AX_IX_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_ix_ix(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_IX_8(cpu); + uint ea = EA_AX_IX_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_ix_aw(m68ki_cpu_core *cpu) +{ + uint res = OPER_AW_8(cpu); + uint ea = EA_AX_IX_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_ix_al(m68ki_cpu_core *cpu) +{ + uint res = OPER_AL_8(cpu); + uint ea = EA_AX_IX_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_ix_pcdi(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCDI_8(cpu); + uint ea = EA_AX_IX_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_ix_pcix(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCIX_8(cpu); + uint ea = EA_AX_IX_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_ix_i(m68ki_cpu_core *cpu) +{ + uint res = OPER_I_8(); + uint ea = EA_AX_IX_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_aw_d(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_AW_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_aw_ai(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_AI_8(cpu); + uint ea = EA_AW_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_aw_pi(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PI_8(cpu); + uint ea = EA_AW_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_aw_pi7(m68ki_cpu_core *cpu) +{ + uint res = OPER_A7_PI_8(cpu); + uint ea = EA_AW_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_aw_pd(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PD_8(cpu); + uint ea = EA_AW_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_aw_pd7(m68ki_cpu_core *cpu) +{ + uint res = OPER_A7_PD_8(cpu); + uint ea = EA_AW_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_aw_di(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_DI_8(cpu); + uint ea = EA_AW_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_aw_ix(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_IX_8(cpu); + uint ea = EA_AW_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_aw_aw(m68ki_cpu_core *cpu) +{ + uint res = OPER_AW_8(cpu); + uint ea = EA_AW_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_aw_al(m68ki_cpu_core *cpu) +{ + uint res = OPER_AL_8(cpu); + uint ea = EA_AW_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_aw_pcdi(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCDI_8(cpu); + uint ea = EA_AW_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_aw_pcix(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCIX_8(cpu); + uint ea = EA_AW_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_aw_i(m68ki_cpu_core *cpu) +{ + uint res = OPER_I_8(); + uint ea = EA_AW_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_al_d(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_AL_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_al_ai(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_AI_8(cpu); + uint ea = EA_AL_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_al_pi(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PI_8(cpu); + uint ea = EA_AL_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_al_pi7(m68ki_cpu_core *cpu) +{ + uint res = OPER_A7_PI_8(cpu); + uint ea = EA_AL_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_al_pd(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PD_8(cpu); + uint ea = EA_AL_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_al_pd7(m68ki_cpu_core *cpu) +{ + uint res = OPER_A7_PD_8(cpu); + uint ea = EA_AL_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_al_di(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_DI_8(cpu); + uint ea = EA_AL_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_al_ix(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_IX_8(cpu); + uint ea = EA_AL_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_al_aw(m68ki_cpu_core *cpu) +{ + uint res = OPER_AW_8(cpu); + uint ea = EA_AL_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_al_al(m68ki_cpu_core *cpu) +{ + uint res = OPER_AL_8(cpu); + uint ea = EA_AL_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_al_pcdi(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCDI_8(cpu); + uint ea = EA_AL_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_al_pcix(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCIX_8(cpu); + uint ea = EA_AL_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_8_al_i(m68ki_cpu_core *cpu) +{ + uint res = OPER_I_8(); + uint ea = EA_AL_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_d_d(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_d_a(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_d_ai(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_AI_16(cpu); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_d_pi(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PI_16(cpu); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_d_pd(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PD_16(cpu); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_d_di(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_DI_16(cpu); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_d_ix(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_IX_16(cpu); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_d_aw(m68ki_cpu_core *cpu) +{ + uint res = OPER_AW_16(cpu); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_d_al(m68ki_cpu_core *cpu) +{ + uint res = OPER_AL_16(cpu); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_d_pcdi(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCDI_16(cpu); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_d_pcix(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCIX_16(cpu); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_d_i(m68ki_cpu_core *cpu) +{ + uint res = OPER_I_16(); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_ai_d(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint ea = EA_AX_AI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_ai_a(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint ea = EA_AX_AI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_ai_ai(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_AI_16(cpu); + uint ea = EA_AX_AI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_ai_pi(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PI_16(cpu); + uint ea = EA_AX_AI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_ai_pd(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PD_16(cpu); + uint ea = EA_AX_AI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_ai_di(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_DI_16(cpu); + uint ea = EA_AX_AI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_ai_ix(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_IX_16(cpu); + uint ea = EA_AX_AI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_ai_aw(m68ki_cpu_core *cpu) +{ + uint res = OPER_AW_16(cpu); + uint ea = EA_AX_AI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_ai_al(m68ki_cpu_core *cpu) +{ + uint res = OPER_AL_16(cpu); + uint ea = EA_AX_AI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_ai_pcdi(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCDI_16(cpu); + uint ea = EA_AX_AI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_ai_pcix(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCIX_16(cpu); + uint ea = EA_AX_AI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_ai_i(m68ki_cpu_core *cpu) +{ + uint res = OPER_I_16(); + uint ea = EA_AX_AI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_pi_d(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint ea = EA_AX_PI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_pi_a(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint ea = EA_AX_PI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_pi_ai(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_AI_16(cpu); + uint ea = EA_AX_PI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_pi_pi(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PI_16(cpu); + uint ea = EA_AX_PI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_pi_pd(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PD_16(cpu); + uint ea = EA_AX_PI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_pi_di(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_DI_16(cpu); + uint ea = EA_AX_PI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_pi_ix(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_IX_16(cpu); + uint ea = EA_AX_PI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_pi_aw(m68ki_cpu_core *cpu) +{ + uint res = OPER_AW_16(cpu); + uint ea = EA_AX_PI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_pi_al(m68ki_cpu_core *cpu) +{ + uint res = OPER_AL_16(cpu); + uint ea = EA_AX_PI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_pi_pcdi(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCDI_16(cpu); + uint ea = EA_AX_PI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_pi_pcix(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCIX_16(cpu); + uint ea = EA_AX_PI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_pi_i(m68ki_cpu_core *cpu) +{ + uint res = OPER_I_16(); + uint ea = EA_AX_PI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_pd_d(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint ea = EA_AX_PD_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_pd_a(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint ea = EA_AX_PD_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_pd_ai(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_AI_16(cpu); + uint ea = EA_AX_PD_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_pd_pi(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PI_16(cpu); + uint ea = EA_AX_PD_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_pd_pd(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PD_16(cpu); + uint ea = EA_AX_PD_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_pd_di(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_DI_16(cpu); + uint ea = EA_AX_PD_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_pd_ix(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_IX_16(cpu); + uint ea = EA_AX_PD_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_pd_aw(m68ki_cpu_core *cpu) +{ + uint res = OPER_AW_16(cpu); + uint ea = EA_AX_PD_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_pd_al(m68ki_cpu_core *cpu) +{ + uint res = OPER_AL_16(cpu); + uint ea = EA_AX_PD_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_pd_pcdi(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCDI_16(cpu); + uint ea = EA_AX_PD_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_pd_pcix(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCIX_16(cpu); + uint ea = EA_AX_PD_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_pd_i(m68ki_cpu_core *cpu) +{ + uint res = OPER_I_16(); + uint ea = EA_AX_PD_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_di_d(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint ea = EA_AX_DI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_di_a(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint ea = EA_AX_DI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_di_ai(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_AI_16(cpu); + uint ea = EA_AX_DI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_di_pi(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PI_16(cpu); + uint ea = EA_AX_DI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_di_pd(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PD_16(cpu); + uint ea = EA_AX_DI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_di_di(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_DI_16(cpu); + uint ea = EA_AX_DI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_di_ix(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_IX_16(cpu); + uint ea = EA_AX_DI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_di_aw(m68ki_cpu_core *cpu) +{ + uint res = OPER_AW_16(cpu); + uint ea = EA_AX_DI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_di_al(m68ki_cpu_core *cpu) +{ + uint res = OPER_AL_16(cpu); + uint ea = EA_AX_DI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_di_pcdi(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCDI_16(cpu); + uint ea = EA_AX_DI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_di_pcix(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCIX_16(cpu); + uint ea = EA_AX_DI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_di_i(m68ki_cpu_core *cpu) +{ + uint res = OPER_I_16(); + uint ea = EA_AX_DI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_ix_d(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint ea = EA_AX_IX_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_ix_a(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint ea = EA_AX_IX_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_ix_ai(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_AI_16(cpu); + uint ea = EA_AX_IX_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_ix_pi(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PI_16(cpu); + uint ea = EA_AX_IX_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_ix_pd(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PD_16(cpu); + uint ea = EA_AX_IX_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_ix_di(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_DI_16(cpu); + uint ea = EA_AX_IX_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_ix_ix(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_IX_16(cpu); + uint ea = EA_AX_IX_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_ix_aw(m68ki_cpu_core *cpu) +{ + uint res = OPER_AW_16(cpu); + uint ea = EA_AX_IX_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_ix_al(m68ki_cpu_core *cpu) +{ + uint res = OPER_AL_16(cpu); + uint ea = EA_AX_IX_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_ix_pcdi(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCDI_16(cpu); + uint ea = EA_AX_IX_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_ix_pcix(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCIX_16(cpu); + uint ea = EA_AX_IX_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_ix_i(m68ki_cpu_core *cpu) +{ + uint res = OPER_I_16(); + uint ea = EA_AX_IX_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_aw_d(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint ea = EA_AW_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_aw_a(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint ea = EA_AW_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_aw_ai(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_AI_16(cpu); + uint ea = EA_AW_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_aw_pi(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PI_16(cpu); + uint ea = EA_AW_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_aw_pd(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PD_16(cpu); + uint ea = EA_AW_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_aw_di(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_DI_16(cpu); + uint ea = EA_AW_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_aw_ix(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_IX_16(cpu); + uint ea = EA_AW_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_aw_aw(m68ki_cpu_core *cpu) +{ + uint res = OPER_AW_16(cpu); + uint ea = EA_AW_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_aw_al(m68ki_cpu_core *cpu) +{ + uint res = OPER_AL_16(cpu); + uint ea = EA_AW_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_aw_pcdi(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCDI_16(cpu); + uint ea = EA_AW_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_aw_pcix(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCIX_16(cpu); + uint ea = EA_AW_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_aw_i(m68ki_cpu_core *cpu) +{ + uint res = OPER_I_16(); + uint ea = EA_AW_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_al_d(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint ea = EA_AL_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_al_a(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint ea = EA_AL_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_al_ai(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_AI_16(cpu); + uint ea = EA_AL_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_al_pi(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PI_16(cpu); + uint ea = EA_AL_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_al_pd(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PD_16(cpu); + uint ea = EA_AL_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_al_di(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_DI_16(cpu); + uint ea = EA_AL_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_al_ix(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_IX_16(cpu); + uint ea = EA_AL_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_al_aw(m68ki_cpu_core *cpu) +{ + uint res = OPER_AW_16(cpu); + uint ea = EA_AL_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_al_al(m68ki_cpu_core *cpu) +{ + uint res = OPER_AL_16(cpu); + uint ea = EA_AL_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_al_pcdi(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCDI_16(cpu); + uint ea = EA_AL_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_al_pcix(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCIX_16(cpu); + uint ea = EA_AL_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_16_al_i(m68ki_cpu_core *cpu) +{ + uint res = OPER_I_16(); + uint ea = EA_AL_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_d_d(m68ki_cpu_core *cpu) +{ + uint res = DY; + uint* r_dst = &DX; + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_d_a(m68ki_cpu_core *cpu) +{ + uint res = AY; + uint* r_dst = &DX; + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_d_ai(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_AI_32(cpu); + uint* r_dst = &DX; + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_d_pi(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PI_32(cpu); + uint* r_dst = &DX; + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_d_pd(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PD_32(cpu); + uint* r_dst = &DX; + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_d_di(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_DI_32(cpu); + uint* r_dst = &DX; + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_d_ix(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_IX_32(cpu); + uint* r_dst = &DX; + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_d_aw(m68ki_cpu_core *cpu) +{ + uint res = OPER_AW_32(cpu); + uint* r_dst = &DX; + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_d_al(m68ki_cpu_core *cpu) +{ + uint res = OPER_AL_32(cpu); + uint* r_dst = &DX; + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_d_pcdi(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCDI_32(cpu); + uint* r_dst = &DX; + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_d_pcix(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCIX_32(cpu); + uint* r_dst = &DX; + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_d_i(m68ki_cpu_core *cpu) +{ + uint res = OPER_I_32(); + uint* r_dst = &DX; + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_ai_d(m68ki_cpu_core *cpu) +{ + uint res = DY; + uint ea = EA_AX_AI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_ai_a(m68ki_cpu_core *cpu) +{ + uint res = AY; + uint ea = EA_AX_AI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_ai_ai(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_AI_32(cpu); + uint ea = EA_AX_AI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_ai_pi(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PI_32(cpu); + uint ea = EA_AX_AI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_ai_pd(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PD_32(cpu); + uint ea = EA_AX_AI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_ai_di(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_DI_32(cpu); + uint ea = EA_AX_AI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_ai_ix(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_IX_32(cpu); + uint ea = EA_AX_AI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_ai_aw(m68ki_cpu_core *cpu) +{ + uint res = OPER_AW_32(cpu); + uint ea = EA_AX_AI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_ai_al(m68ki_cpu_core *cpu) +{ + uint res = OPER_AL_32(cpu); + uint ea = EA_AX_AI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_ai_pcdi(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCDI_32(cpu); + uint ea = EA_AX_AI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_ai_pcix(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCIX_32(cpu); + uint ea = EA_AX_AI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_ai_i(m68ki_cpu_core *cpu) +{ + uint res = OPER_I_32(); + uint ea = EA_AX_AI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_pi_d(m68ki_cpu_core *cpu) +{ + uint res = DY; + uint ea = EA_AX_PI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_pi_a(m68ki_cpu_core *cpu) +{ + uint res = AY; + uint ea = EA_AX_PI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_pi_ai(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_AI_32(cpu); + uint ea = EA_AX_PI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_pi_pi(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PI_32(cpu); + uint ea = EA_AX_PI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_pi_pd(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PD_32(cpu); + uint ea = EA_AX_PI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_pi_di(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_DI_32(cpu); + uint ea = EA_AX_PI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_pi_ix(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_IX_32(cpu); + uint ea = EA_AX_PI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_pi_aw(m68ki_cpu_core *cpu) +{ + uint res = OPER_AW_32(cpu); + uint ea = EA_AX_PI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_pi_al(m68ki_cpu_core *cpu) +{ + uint res = OPER_AL_32(cpu); + uint ea = EA_AX_PI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_pi_pcdi(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCDI_32(cpu); + uint ea = EA_AX_PI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_pi_pcix(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCIX_32(cpu); + uint ea = EA_AX_PI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_pi_i(m68ki_cpu_core *cpu) +{ + uint res = OPER_I_32(); + uint ea = EA_AX_PI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_pd_d(m68ki_cpu_core *cpu) +{ + uint res = DY; + uint ea = EA_AX_PD_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_pd_a(m68ki_cpu_core *cpu) +{ + uint res = AY; + uint ea = EA_AX_PD_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_pd_ai(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_AI_32(cpu); + uint ea = EA_AX_PD_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_pd_pi(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PI_32(cpu); + uint ea = EA_AX_PD_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_pd_pd(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PD_32(cpu); + uint ea = EA_AX_PD_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_pd_di(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_DI_32(cpu); + uint ea = EA_AX_PD_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_pd_ix(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_IX_32(cpu); + uint ea = EA_AX_PD_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_pd_aw(m68ki_cpu_core *cpu) +{ + uint res = OPER_AW_32(cpu); + uint ea = EA_AX_PD_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_pd_al(m68ki_cpu_core *cpu) +{ + uint res = OPER_AL_32(cpu); + uint ea = EA_AX_PD_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_pd_pcdi(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCDI_32(cpu); + uint ea = EA_AX_PD_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_pd_pcix(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCIX_32(cpu); + uint ea = EA_AX_PD_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_pd_i(m68ki_cpu_core *cpu) +{ + uint res = OPER_I_32(); + uint ea = EA_AX_PD_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_di_d(m68ki_cpu_core *cpu) +{ + uint res = DY; + uint ea = EA_AX_DI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_di_a(m68ki_cpu_core *cpu) +{ + uint res = AY; + uint ea = EA_AX_DI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_di_ai(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_AI_32(cpu); + uint ea = EA_AX_DI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_di_pi(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PI_32(cpu); + uint ea = EA_AX_DI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_di_pd(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PD_32(cpu); + uint ea = EA_AX_DI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_di_di(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_DI_32(cpu); + uint ea = EA_AX_DI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_di_ix(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_IX_32(cpu); + uint ea = EA_AX_DI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_di_aw(m68ki_cpu_core *cpu) +{ + uint res = OPER_AW_32(cpu); + uint ea = EA_AX_DI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_di_al(m68ki_cpu_core *cpu) +{ + uint res = OPER_AL_32(cpu); + uint ea = EA_AX_DI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_di_pcdi(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCDI_32(cpu); + uint ea = EA_AX_DI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_di_pcix(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCIX_32(cpu); + uint ea = EA_AX_DI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_di_i(m68ki_cpu_core *cpu) +{ + uint res = OPER_I_32(); + uint ea = EA_AX_DI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_ix_d(m68ki_cpu_core *cpu) +{ + uint res = DY; + uint ea = EA_AX_IX_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_ix_a(m68ki_cpu_core *cpu) +{ + uint res = AY; + uint ea = EA_AX_IX_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_ix_ai(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_AI_32(cpu); + uint ea = EA_AX_IX_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_ix_pi(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PI_32(cpu); + uint ea = EA_AX_IX_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_ix_pd(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PD_32(cpu); + uint ea = EA_AX_IX_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_ix_di(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_DI_32(cpu); + uint ea = EA_AX_IX_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_ix_ix(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_IX_32(cpu); + uint ea = EA_AX_IX_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_ix_aw(m68ki_cpu_core *cpu) +{ + uint res = OPER_AW_32(cpu); + uint ea = EA_AX_IX_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_ix_al(m68ki_cpu_core *cpu) +{ + uint res = OPER_AL_32(cpu); + uint ea = EA_AX_IX_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_ix_pcdi(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCDI_32(cpu); + uint ea = EA_AX_IX_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_ix_pcix(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCIX_32(cpu); + uint ea = EA_AX_IX_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_ix_i(m68ki_cpu_core *cpu) +{ + uint res = OPER_I_32(); + uint ea = EA_AX_IX_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_aw_d(m68ki_cpu_core *cpu) +{ + uint res = DY; + uint ea = EA_AW_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_aw_a(m68ki_cpu_core *cpu) +{ + uint res = AY; + uint ea = EA_AW_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_aw_ai(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_AI_32(cpu); + uint ea = EA_AW_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_aw_pi(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PI_32(cpu); + uint ea = EA_AW_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_aw_pd(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PD_32(cpu); + uint ea = EA_AW_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_aw_di(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_DI_32(cpu); + uint ea = EA_AW_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_aw_ix(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_IX_32(cpu); + uint ea = EA_AW_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_aw_aw(m68ki_cpu_core *cpu) +{ + uint res = OPER_AW_32(cpu); + uint ea = EA_AW_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_aw_al(m68ki_cpu_core *cpu) +{ + uint res = OPER_AL_32(cpu); + uint ea = EA_AW_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_aw_pcdi(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCDI_32(cpu); + uint ea = EA_AW_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_aw_pcix(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCIX_32(cpu); + uint ea = EA_AW_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_aw_i(m68ki_cpu_core *cpu) +{ + uint res = OPER_I_32(); + uint ea = EA_AW_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_al_d(m68ki_cpu_core *cpu) +{ + uint res = DY; + uint ea = EA_AL_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_al_a(m68ki_cpu_core *cpu) +{ + uint res = AY; + uint ea = EA_AL_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_al_ai(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_AI_32(cpu); + uint ea = EA_AL_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_al_pi(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PI_32(cpu); + uint ea = EA_AL_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_al_pd(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PD_32(cpu); + uint ea = EA_AL_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_al_di(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_DI_32(cpu); + uint ea = EA_AL_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_al_ix(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_IX_32(cpu); + uint ea = EA_AL_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_al_aw(m68ki_cpu_core *cpu) +{ + uint res = OPER_AW_32(cpu); + uint ea = EA_AL_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_al_al(m68ki_cpu_core *cpu) +{ + uint res = OPER_AL_32(cpu); + uint ea = EA_AL_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_al_pcdi(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCDI_32(cpu); + uint ea = EA_AL_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_al_pcix(m68ki_cpu_core *cpu) +{ + uint res = OPER_PCIX_32(cpu); + uint ea = EA_AL_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_move_32_al_i(m68ki_cpu_core *cpu) +{ + uint res = OPER_I_32(); + uint ea = EA_AL_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_movea_16_d(m68ki_cpu_core *cpu) +{ + AX = MAKE_INT_16(DY); +} + + +void m68k_op_movea_16_a(m68ki_cpu_core *cpu) +{ + AX = MAKE_INT_16(AY); +} + + +void m68k_op_movea_16_ai(m68ki_cpu_core *cpu) +{ + AX = MAKE_INT_16(OPER_AY_AI_16(cpu)); +} + + +void m68k_op_movea_16_pi(m68ki_cpu_core *cpu) +{ + AX = MAKE_INT_16(OPER_AY_PI_16(cpu)); +} + + +void m68k_op_movea_16_pd(m68ki_cpu_core *cpu) +{ + AX = MAKE_INT_16(OPER_AY_PD_16(cpu)); +} + + +void m68k_op_movea_16_di(m68ki_cpu_core *cpu) +{ + AX = MAKE_INT_16(OPER_AY_DI_16(cpu)); +} + + +void m68k_op_movea_16_ix(m68ki_cpu_core *cpu) +{ + AX = MAKE_INT_16(OPER_AY_IX_16(cpu)); +} + + +void m68k_op_movea_16_aw(m68ki_cpu_core *cpu) +{ + AX = MAKE_INT_16(OPER_AW_16(cpu)); +} + + +void m68k_op_movea_16_al(m68ki_cpu_core *cpu) +{ + AX = MAKE_INT_16(OPER_AL_16(cpu)); +} + + +void m68k_op_movea_16_pcdi(m68ki_cpu_core *cpu) +{ + AX = MAKE_INT_16(OPER_PCDI_16(cpu)); +} + + +void m68k_op_movea_16_pcix(m68ki_cpu_core *cpu) +{ + AX = MAKE_INT_16(OPER_PCIX_16(cpu)); +} + + +void m68k_op_movea_16_i(m68ki_cpu_core *cpu) +{ + AX = MAKE_INT_16(OPER_I_16()); +} + + +void m68k_op_movea_32_d(m68ki_cpu_core *cpu) +{ + AX = DY; +} + + +void m68k_op_movea_32_a(m68ki_cpu_core *cpu) +{ + AX = AY; +} + + +void m68k_op_movea_32_ai(m68ki_cpu_core *cpu) +{ + AX = OPER_AY_AI_32(cpu); +} + + +void m68k_op_movea_32_pi(m68ki_cpu_core *cpu) +{ + AX = OPER_AY_PI_32(cpu); +} + + +void m68k_op_movea_32_pd(m68ki_cpu_core *cpu) +{ + AX = OPER_AY_PD_32(cpu); +} + + +void m68k_op_movea_32_di(m68ki_cpu_core *cpu) +{ + AX = OPER_AY_DI_32(cpu); +} + + +void m68k_op_movea_32_ix(m68ki_cpu_core *cpu) +{ + AX = OPER_AY_IX_32(cpu); +} + + +void m68k_op_movea_32_aw(m68ki_cpu_core *cpu) +{ + AX = OPER_AW_32(cpu); +} + + +void m68k_op_movea_32_al(m68ki_cpu_core *cpu) +{ + AX = OPER_AL_32(cpu); +} + + +void m68k_op_movea_32_pcdi(m68ki_cpu_core *cpu) +{ + AX = OPER_PCDI_32(cpu); +} + + +void m68k_op_movea_32_pcix(m68ki_cpu_core *cpu) +{ + AX = OPER_PCIX_32(cpu); +} + + +void m68k_op_movea_32_i(m68ki_cpu_core *cpu) +{ + AX = OPER_I_32(); +} + + +void m68k_op_move_16_frc_d(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + DY = MASK_OUT_BELOW_16(DY) | m68ki_get_ccr(); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_move_16_frc_ai(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + m68ki_write_16(EA_AY_AI_16(), m68ki_get_ccr()); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_move_16_frc_pi(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + m68ki_write_16(EA_AY_PI_16(), m68ki_get_ccr()); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_move_16_frc_pd(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + m68ki_write_16(EA_AY_PD_16(), m68ki_get_ccr()); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_move_16_frc_di(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + m68ki_write_16(EA_AY_DI_16(), m68ki_get_ccr()); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_move_16_frc_ix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + m68ki_write_16(EA_AY_IX_16(), m68ki_get_ccr()); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_move_16_frc_aw(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + m68ki_write_16(EA_AW_16(), m68ki_get_ccr()); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_move_16_frc_al(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + m68ki_write_16(EA_AL_16(), m68ki_get_ccr()); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_move_16_toc_d(m68ki_cpu_core *cpu) +{ + m68ki_set_ccr(cpu, DY); +} + + +void m68k_op_move_16_toc_ai(m68ki_cpu_core *cpu) +{ + m68ki_set_ccr(cpu, OPER_AY_AI_16(cpu)); +} + + +void m68k_op_move_16_toc_pi(m68ki_cpu_core *cpu) +{ + m68ki_set_ccr(cpu, OPER_AY_PI_16(cpu)); +} + + +void m68k_op_move_16_toc_pd(m68ki_cpu_core *cpu) +{ + m68ki_set_ccr(cpu, OPER_AY_PD_16(cpu)); +} + + +void m68k_op_move_16_toc_di(m68ki_cpu_core *cpu) +{ + m68ki_set_ccr(cpu, OPER_AY_DI_16(cpu)); +} + + +void m68k_op_move_16_toc_ix(m68ki_cpu_core *cpu) +{ + m68ki_set_ccr(cpu, OPER_AY_IX_16(cpu)); +} + + +void m68k_op_move_16_toc_aw(m68ki_cpu_core *cpu) +{ + m68ki_set_ccr(cpu, OPER_AW_16(cpu)); +} + + +void m68k_op_move_16_toc_al(m68ki_cpu_core *cpu) +{ + m68ki_set_ccr(cpu, OPER_AL_16(cpu)); +} + + +void m68k_op_move_16_toc_pcdi(m68ki_cpu_core *cpu) +{ + m68ki_set_ccr(cpu, OPER_PCDI_16(cpu)); +} + + +void m68k_op_move_16_toc_pcix(m68ki_cpu_core *cpu) +{ + m68ki_set_ccr(cpu, OPER_PCIX_16(cpu)); +} + + +void m68k_op_move_16_toc_i(m68ki_cpu_core *cpu) +{ + m68ki_set_ccr(cpu, OPER_I_16()); +} + + +void m68k_op_move_16_frs_d(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_000(CPU_TYPE) || FLAG_S) /* NS990408 */ + { + DY = MASK_OUT_BELOW_16(DY) | m68ki_get_sr(); + return; + } + m68ki_exception_privilege_violation(cpu); +} + + +void m68k_op_move_16_frs_ai(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_000(CPU_TYPE) || FLAG_S) /* NS990408 */ + { + uint ea = EA_AY_AI_16(); + m68ki_write_16(ea, m68ki_get_sr()); + return; + } + m68ki_exception_privilege_violation(cpu); +} + + +void m68k_op_move_16_frs_pi(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_000(CPU_TYPE) || FLAG_S) /* NS990408 */ + { + uint ea = EA_AY_PI_16(); + m68ki_write_16(ea, m68ki_get_sr()); + return; + } + m68ki_exception_privilege_violation(cpu); +} + + +void m68k_op_move_16_frs_pd(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_000(CPU_TYPE) || FLAG_S) /* NS990408 */ + { + uint ea = EA_AY_PD_16(); + m68ki_write_16(ea, m68ki_get_sr()); + return; + } + m68ki_exception_privilege_violation(cpu); +} + + +void m68k_op_move_16_frs_di(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_000(CPU_TYPE) || FLAG_S) /* NS990408 */ + { + uint ea = EA_AY_DI_16(); + m68ki_write_16(ea, m68ki_get_sr()); + return; + } + m68ki_exception_privilege_violation(cpu); +} + + +void m68k_op_move_16_frs_ix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_000(CPU_TYPE) || FLAG_S) /* NS990408 */ + { + uint ea = EA_AY_IX_16(); + m68ki_write_16(ea, m68ki_get_sr()); + return; + } + m68ki_exception_privilege_violation(cpu); +} + + +void m68k_op_move_16_frs_aw(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_000(CPU_TYPE) || FLAG_S) /* NS990408 */ + { + uint ea = EA_AW_16(); + m68ki_write_16(ea, m68ki_get_sr()); + return; + } + m68ki_exception_privilege_violation(cpu); +} + + +void m68k_op_move_16_frs_al(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_000(CPU_TYPE) || FLAG_S) /* NS990408 */ + { + uint ea = EA_AL_16(); + m68ki_write_16(ea, m68ki_get_sr()); + return; + } + m68ki_exception_privilege_violation(cpu); +} + + +void m68k_op_move_16_tos_d(m68ki_cpu_core *cpu) +{ + if(FLAG_S) + { + m68ki_set_sr(cpu, DY); + return; + } + m68ki_exception_privilege_violation(cpu); +} + + +void m68k_op_move_16_tos_ai(m68ki_cpu_core *cpu) +{ + if(FLAG_S) + { + uint new_sr = OPER_AY_AI_16(cpu); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_set_sr(cpu, new_sr); + return; + } + m68ki_exception_privilege_violation(cpu); +} + + +void m68k_op_move_16_tos_pi(m68ki_cpu_core *cpu) +{ + if(FLAG_S) + { + uint new_sr = OPER_AY_PI_16(cpu); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_set_sr(cpu, new_sr); + return; + } + m68ki_exception_privilege_violation(cpu); +} + + +void m68k_op_move_16_tos_pd(m68ki_cpu_core *cpu) +{ + if(FLAG_S) + { + uint new_sr = OPER_AY_PD_16(cpu); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_set_sr(cpu, new_sr); + return; + } + m68ki_exception_privilege_violation(cpu); +} + + +void m68k_op_move_16_tos_di(m68ki_cpu_core *cpu) +{ + if(FLAG_S) + { + uint new_sr = OPER_AY_DI_16(cpu); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_set_sr(cpu, new_sr); + return; + } + m68ki_exception_privilege_violation(cpu); +} + + +void m68k_op_move_16_tos_ix(m68ki_cpu_core *cpu) +{ + if(FLAG_S) + { + uint new_sr = OPER_AY_IX_16(cpu); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_set_sr(cpu, new_sr); + return; + } + m68ki_exception_privilege_violation(cpu); +} + + +void m68k_op_move_16_tos_aw(m68ki_cpu_core *cpu) +{ + if(FLAG_S) + { + uint new_sr = OPER_AW_16(cpu); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_set_sr(cpu, new_sr); + return; + } + m68ki_exception_privilege_violation(cpu); +} + + +void m68k_op_move_16_tos_al(m68ki_cpu_core *cpu) +{ + if(FLAG_S) + { + uint new_sr = OPER_AL_16(cpu); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_set_sr(cpu, new_sr); + return; + } + m68ki_exception_privilege_violation(cpu); +} + + +void m68k_op_move_16_tos_pcdi(m68ki_cpu_core *cpu) +{ + if(FLAG_S) + { + uint new_sr = OPER_PCDI_16(cpu); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_set_sr(cpu, new_sr); + return; + } + m68ki_exception_privilege_violation(cpu); +} + + +void m68k_op_move_16_tos_pcix(m68ki_cpu_core *cpu) +{ + if(FLAG_S) + { + uint new_sr = OPER_PCIX_16(cpu); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_set_sr(cpu, new_sr); + return; + } + m68ki_exception_privilege_violation(cpu); +} + + +void m68k_op_move_16_tos_i(m68ki_cpu_core *cpu) +{ + if(FLAG_S) + { + uint new_sr = OPER_I_16(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_set_sr(cpu, new_sr); + return; + } + m68ki_exception_privilege_violation(cpu); +} + + +void m68k_op_move_32_fru(m68ki_cpu_core *cpu) +{ + if(FLAG_S) + { + AY = REG_USP; + return; + } + m68ki_exception_privilege_violation(cpu); +} + + +void m68k_op_move_32_tou(m68ki_cpu_core *cpu) +{ + if(FLAG_S) + { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + REG_USP = AY; + return; + } + m68ki_exception_privilege_violation(cpu); +} + + +void m68k_op_movec_32_cr(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + switch (word2 & 0xfff) + { + case 0x000: /* SFC */ + REG_DA[(word2 >> 12) & 15] = REG_SFC; + return; + case 0x001: /* DFC */ + REG_DA[(word2 >> 12) & 15] = REG_DFC; + return; + case 0x002: /* CACR */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_DA[(word2 >> 12) & 15] = REG_CACR; + return; + } + return; + case 0x800: /* USP */ + REG_DA[(word2 >> 12) & 15] = REG_USP; + return; + case 0x801: /* VBR */ + REG_DA[(word2 >> 12) & 15] = REG_VBR; + return; + case 0x802: /* CAAR */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_DA[(word2 >> 12) & 15] = REG_CAAR; + return; + } + m68ki_exception_illegal(cpu); + break; + case 0x803: /* MSP */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_DA[(word2 >> 12) & 15] = FLAG_M ? REG_SP : REG_MSP; + return; + } + m68ki_exception_illegal(cpu); + return; + case 0x804: /* ISP */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_DA[(word2 >> 12) & 15] = FLAG_M ? REG_ISP : REG_SP; + return; + } + m68ki_exception_illegal(cpu); + return; + default: + m68ki_exception_illegal(cpu); + return; + } + } + m68ki_exception_privilege_violation(cpu); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_movec_32_rc(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + switch (word2 & 0xfff) + { + case 0x000: /* SFC */ + REG_SFC = REG_DA[(word2 >> 12) & 15] & 7; + return; + case 0x001: /* DFC */ + REG_DFC = REG_DA[(word2 >> 12) & 15] & 7; + return; + case 0x002: /* CACR */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_CACR = REG_DA[(word2 >> 12) & 15]; + return; + } + m68ki_exception_illegal(cpu); + return; + case 0x800: /* USP */ + REG_USP = REG_DA[(word2 >> 12) & 15]; + return; + case 0x801: /* VBR */ + REG_VBR = REG_DA[(word2 >> 12) & 15]; + return; + case 0x802: /* CAAR */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_CAAR = REG_DA[(word2 >> 12) & 15]; + return; + } + m68ki_exception_illegal(cpu); + return; + case 0x803: /* MSP */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* we are in supervisor mode so just check for M flag */ + if(!FLAG_M) + { + REG_MSP = REG_DA[(word2 >> 12) & 15]; + return; + } + REG_SP = REG_DA[(word2 >> 12) & 15]; + return; + } + m68ki_exception_illegal(cpu); + return; + case 0x804: /* ISP */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(!FLAG_M) + { + REG_SP = REG_DA[(word2 >> 12) & 15]; + return; + } + REG_ISP = REG_DA[(word2 >> 12) & 15]; + return; + } + m68ki_exception_illegal(cpu); + return; + default: + m68ki_exception_illegal(cpu); + return; + } + } + m68ki_exception_privilege_violation(cpu); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_movem_16_re_pd(m68ki_cpu_core *cpu) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = AY; + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + ea -= 2; + m68ki_write_16(ea, MASK_OUT_ABOVE_16(REG_DA[15-i])); + count++; + } + AY = ea; + + USE_CYCLES(count<<CYC_MOVEM_W); +} + + +void m68k_op_movem_16_re_ai(m68ki_cpu_core *cpu) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = EA_AY_AI_16(); + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + m68ki_write_16(ea, MASK_OUT_ABOVE_16(REG_DA[i])); + ea += 2; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_W); +} + + +void m68k_op_movem_16_re_di(m68ki_cpu_core *cpu) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = EA_AY_DI_16(); + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + m68ki_write_16(ea, MASK_OUT_ABOVE_16(REG_DA[i])); + ea += 2; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_W); +} + + +void m68k_op_movem_16_re_ix(m68ki_cpu_core *cpu) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = EA_AY_IX_16(); + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + m68ki_write_16(ea, MASK_OUT_ABOVE_16(REG_DA[i])); + ea += 2; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_W); +} + + +void m68k_op_movem_16_re_aw(m68ki_cpu_core *cpu) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = EA_AW_16(); + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + m68ki_write_16(ea, MASK_OUT_ABOVE_16(REG_DA[i])); + ea += 2; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_W); +} + + +void m68k_op_movem_16_re_al(m68ki_cpu_core *cpu) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = EA_AL_16(); + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + m68ki_write_16(ea, MASK_OUT_ABOVE_16(REG_DA[i])); + ea += 2; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_W); +} + + +void m68k_op_movem_32_re_pd(m68ki_cpu_core *cpu) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = AY; + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + ea -= 4; + m68ki_write_32(ea, REG_DA[15-i]); + count++; + } + AY = ea; + + USE_CYCLES(count<<CYC_MOVEM_L); +} + + +void m68k_op_movem_32_re_ai(m68ki_cpu_core *cpu) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = EA_AY_AI_32(); + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + m68ki_write_32(ea, REG_DA[i]); + ea += 4; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_L); +} + + +void m68k_op_movem_32_re_di(m68ki_cpu_core *cpu) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = EA_AY_DI_32(); + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + m68ki_write_32(ea, REG_DA[i]); + ea += 4; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_L); +} + + +void m68k_op_movem_32_re_ix(m68ki_cpu_core *cpu) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = EA_AY_IX_32(); + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + m68ki_write_32(ea, REG_DA[i]); + ea += 4; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_L); +} + + +void m68k_op_movem_32_re_aw(m68ki_cpu_core *cpu) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = EA_AW_32(); + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + m68ki_write_32(ea, REG_DA[i]); + ea += 4; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_L); +} + + +void m68k_op_movem_32_re_al(m68ki_cpu_core *cpu) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = EA_AL_32(); + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + m68ki_write_32(ea, REG_DA[i]); + ea += 4; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_L); +} + + +void m68k_op_movem_16_er_pi(m68ki_cpu_core *cpu) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = AY; + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + REG_DA[i] = MAKE_INT_16(MASK_OUT_ABOVE_16(m68ki_read_16(ea))); + ea += 2; + count++; + } + AY = ea; + + USE_CYCLES(count<<CYC_MOVEM_W); +} + + +void m68k_op_movem_16_er_pcdi(m68ki_cpu_core *cpu) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = EA_PCDI_16(); + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + REG_DA[i] = MAKE_INT_16(MASK_OUT_ABOVE_16(m68ki_read_pcrel_16(ea))); + ea += 2; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_W); +} + + +void m68k_op_movem_16_er_pcix(m68ki_cpu_core *cpu) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = EA_PCIX_16(); + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + REG_DA[i] = MAKE_INT_16(MASK_OUT_ABOVE_16(m68ki_read_pcrel_16(ea))); + ea += 2; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_W); +} + + +void m68k_op_movem_16_er_ai(m68ki_cpu_core *cpu) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = EA_AY_AI_16(); + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + REG_DA[i] = MAKE_INT_16(MASK_OUT_ABOVE_16(m68ki_read_16(ea))); + ea += 2; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_W); +} + + +void m68k_op_movem_16_er_di(m68ki_cpu_core *cpu) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = EA_AY_DI_16(); + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + REG_DA[i] = MAKE_INT_16(MASK_OUT_ABOVE_16(m68ki_read_16(ea))); + ea += 2; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_W); +} + + +void m68k_op_movem_16_er_ix(m68ki_cpu_core *cpu) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = EA_AY_IX_16(); + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + REG_DA[i] = MAKE_INT_16(MASK_OUT_ABOVE_16(m68ki_read_16(ea))); + ea += 2; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_W); +} + + +void m68k_op_movem_16_er_aw(m68ki_cpu_core *cpu) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = EA_AW_16(); + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + REG_DA[i] = MAKE_INT_16(MASK_OUT_ABOVE_16(m68ki_read_16(ea))); + ea += 2; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_W); +} + + +void m68k_op_movem_16_er_al(m68ki_cpu_core *cpu) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = EA_AL_16(); + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + REG_DA[i] = MAKE_INT_16(MASK_OUT_ABOVE_16(m68ki_read_16(ea))); + ea += 2; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_W); +} + + +void m68k_op_movem_32_er_pi(m68ki_cpu_core *cpu) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = AY; + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + REG_DA[i] = m68ki_read_32(ea); + ea += 4; + count++; + } + AY = ea; + + USE_CYCLES(count<<CYC_MOVEM_L); +} + + +void m68k_op_movem_32_er_pcdi(m68ki_cpu_core *cpu) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = EA_PCDI_32(); + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + REG_DA[i] = m68ki_read_pcrel_32(ea); + ea += 4; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_L); +} + + +void m68k_op_movem_32_er_pcix(m68ki_cpu_core *cpu) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = EA_PCIX_32(); + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + REG_DA[i] = m68ki_read_pcrel_32(ea); + ea += 4; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_L); +} + + +void m68k_op_movem_32_er_ai(m68ki_cpu_core *cpu) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = EA_AY_AI_32(); + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + REG_DA[i] = m68ki_read_32(ea); + ea += 4; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_L); +} + + +void m68k_op_movem_32_er_di(m68ki_cpu_core *cpu) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = EA_AY_DI_32(); + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + REG_DA[i] = m68ki_read_32(ea); + ea += 4; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_L); +} + + +void m68k_op_movem_32_er_ix(m68ki_cpu_core *cpu) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = EA_AY_IX_32(); + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + REG_DA[i] = m68ki_read_32(ea); + ea += 4; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_L); +} + + +void m68k_op_movem_32_er_aw(m68ki_cpu_core *cpu) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = EA_AW_32(); + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + REG_DA[i] = m68ki_read_32(ea); + ea += 4; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_L); +} + + +void m68k_op_movem_32_er_al(m68ki_cpu_core *cpu) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = EA_AL_32(); + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + REG_DA[i] = m68ki_read_32(ea); + ea += 4; + count++; + } + + USE_CYCLES(count<<CYC_MOVEM_L); +} + + +void m68k_op_movep_16_re(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_16(); + uint src = DX; + + m68ki_write_8(ea, MASK_OUT_ABOVE_8(src >> 8)); + m68ki_write_8(ea += 2, MASK_OUT_ABOVE_8(src)); +} + + +void m68k_op_movep_32_re(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_32(); + uint src = DX; + + m68ki_write_8(ea, MASK_OUT_ABOVE_8(src >> 24)); + m68ki_write_8(ea += 2, MASK_OUT_ABOVE_8(src >> 16)); + m68ki_write_8(ea += 2, MASK_OUT_ABOVE_8(src >> 8)); + m68ki_write_8(ea += 2, MASK_OUT_ABOVE_8(src)); +} + + +void m68k_op_movep_16_er(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_16(); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | ((m68ki_read_8(ea) << 8) + m68ki_read_8(ea + 2)); +} + + +void m68k_op_movep_32_er(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_32(); + + DX = (m68ki_read_8(ea) << 24) + (m68ki_read_8(ea + 2) << 16) + + (m68ki_read_8(ea + 4) << 8) + m68ki_read_8(ea + 6); +} + + +void m68k_op_moves_8_ai(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = EA_AY_AI_8(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_8_fc(cpu, ea, REG_DFC, MASK_OUT_ABOVE_8(REG_DA[(word2 >> 12) & 15])); + return; + } + if(BIT_F(word2)) /* Memory to address register */ + { + REG_A[(word2 >> 12) & 7] = MAKE_INT_8(m68ki_read_8_fc(cpu, ea, REG_SFC)); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to data register */ + REG_D[(word2 >> 12) & 7] = MASK_OUT_BELOW_8(REG_D[(word2 >> 12) & 7]) | m68ki_read_8_fc(cpu, ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(cpu); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_moves_8_pi(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = EA_AY_PI_8(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_8_fc(cpu, ea, REG_DFC, MASK_OUT_ABOVE_8(REG_DA[(word2 >> 12) & 15])); + return; + } + if(BIT_F(word2)) /* Memory to address register */ + { + REG_A[(word2 >> 12) & 7] = MAKE_INT_8(m68ki_read_8_fc(cpu, ea, REG_SFC)); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to data register */ + REG_D[(word2 >> 12) & 7] = MASK_OUT_BELOW_8(REG_D[(word2 >> 12) & 7]) | m68ki_read_8_fc(cpu, ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(cpu); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_moves_8_pi7(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = EA_A7_PI_8(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_8_fc(cpu, ea, REG_DFC, MASK_OUT_ABOVE_8(REG_DA[(word2 >> 12) & 15])); + return; + } + if(BIT_F(word2)) /* Memory to address register */ + { + REG_A[(word2 >> 12) & 7] = MAKE_INT_8(m68ki_read_8_fc(cpu, ea, REG_SFC)); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to data register */ + REG_D[(word2 >> 12) & 7] = MASK_OUT_BELOW_8(REG_D[(word2 >> 12) & 7]) | m68ki_read_8_fc(cpu, ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(cpu); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_moves_8_pd(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = EA_AY_PD_8(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_8_fc(cpu, ea, REG_DFC, MASK_OUT_ABOVE_8(REG_DA[(word2 >> 12) & 15])); + return; + } + if(BIT_F(word2)) /* Memory to address register */ + { + REG_A[(word2 >> 12) & 7] = MAKE_INT_8(m68ki_read_8_fc(cpu, ea, REG_SFC)); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to data register */ + REG_D[(word2 >> 12) & 7] = MASK_OUT_BELOW_8(REG_D[(word2 >> 12) & 7]) | m68ki_read_8_fc(cpu, ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(cpu); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_moves_8_pd7(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = EA_A7_PD_8(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_8_fc(cpu, ea, REG_DFC, MASK_OUT_ABOVE_8(REG_DA[(word2 >> 12) & 15])); + return; + } + if(BIT_F(word2)) /* Memory to address register */ + { + REG_A[(word2 >> 12) & 7] = MAKE_INT_8(m68ki_read_8_fc(cpu, ea, REG_SFC)); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to data register */ + REG_D[(word2 >> 12) & 7] = MASK_OUT_BELOW_8(REG_D[(word2 >> 12) & 7]) | m68ki_read_8_fc(cpu, ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(cpu); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_moves_8_di(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = EA_AY_DI_8(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_8_fc(cpu, ea, REG_DFC, MASK_OUT_ABOVE_8(REG_DA[(word2 >> 12) & 15])); + return; + } + if(BIT_F(word2)) /* Memory to address register */ + { + REG_A[(word2 >> 12) & 7] = MAKE_INT_8(m68ki_read_8_fc(cpu, ea, REG_SFC)); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to data register */ + REG_D[(word2 >> 12) & 7] = MASK_OUT_BELOW_8(REG_D[(word2 >> 12) & 7]) | m68ki_read_8_fc(cpu, ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(cpu); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_moves_8_ix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = EA_AY_IX_8(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_8_fc(cpu, ea, REG_DFC, MASK_OUT_ABOVE_8(REG_DA[(word2 >> 12) & 15])); + return; + } + if(BIT_F(word2)) /* Memory to address register */ + { + REG_A[(word2 >> 12) & 7] = MAKE_INT_8(m68ki_read_8_fc(cpu, ea, REG_SFC)); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to data register */ + REG_D[(word2 >> 12) & 7] = MASK_OUT_BELOW_8(REG_D[(word2 >> 12) & 7]) | m68ki_read_8_fc(cpu, ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(cpu); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_moves_8_aw(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = EA_AW_8(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_8_fc(cpu, ea, REG_DFC, MASK_OUT_ABOVE_8(REG_DA[(word2 >> 12) & 15])); + return; + } + if(BIT_F(word2)) /* Memory to address register */ + { + REG_A[(word2 >> 12) & 7] = MAKE_INT_8(m68ki_read_8_fc(cpu, ea, REG_SFC)); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to data register */ + REG_D[(word2 >> 12) & 7] = MASK_OUT_BELOW_8(REG_D[(word2 >> 12) & 7]) | m68ki_read_8_fc(cpu, ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(cpu); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_moves_8_al(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = EA_AL_8(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_8_fc(cpu, ea, REG_DFC, MASK_OUT_ABOVE_8(REG_DA[(word2 >> 12) & 15])); + return; + } + if(BIT_F(word2)) /* Memory to address register */ + { + REG_A[(word2 >> 12) & 7] = MAKE_INT_8(m68ki_read_8_fc(cpu, ea, REG_SFC)); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to data register */ + REG_D[(word2 >> 12) & 7] = MASK_OUT_BELOW_8(REG_D[(word2 >> 12) & 7]) | m68ki_read_8_fc(cpu, ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(cpu); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_moves_16_ai(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = EA_AY_AI_16(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_16_fc(cpu, ea, REG_DFC, MASK_OUT_ABOVE_16(REG_DA[(word2 >> 12) & 15])); + return; + } + if(BIT_F(word2)) /* Memory to address register */ + { + REG_A[(word2 >> 12) & 7] = MAKE_INT_16(m68ki_read_16_fc(cpu, ea, REG_SFC)); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to data register */ + REG_D[(word2 >> 12) & 7] = MASK_OUT_BELOW_16(REG_D[(word2 >> 12) & 7]) | m68ki_read_16_fc(cpu, ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(cpu); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_moves_16_pi(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = EA_AY_PI_16(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_16_fc(cpu, ea, REG_DFC, MASK_OUT_ABOVE_16(REG_DA[(word2 >> 12) & 15])); + return; + } + if(BIT_F(word2)) /* Memory to address register */ + { + REG_A[(word2 >> 12) & 7] = MAKE_INT_16(m68ki_read_16_fc(cpu, ea, REG_SFC)); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to data register */ + REG_D[(word2 >> 12) & 7] = MASK_OUT_BELOW_16(REG_D[(word2 >> 12) & 7]) | m68ki_read_16_fc(cpu, ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(cpu); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_moves_16_pd(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = EA_AY_PD_16(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_16_fc(cpu, ea, REG_DFC, MASK_OUT_ABOVE_16(REG_DA[(word2 >> 12) & 15])); + return; + } + if(BIT_F(word2)) /* Memory to address register */ + { + REG_A[(word2 >> 12) & 7] = MAKE_INT_16(m68ki_read_16_fc(cpu, ea, REG_SFC)); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to data register */ + REG_D[(word2 >> 12) & 7] = MASK_OUT_BELOW_16(REG_D[(word2 >> 12) & 7]) | m68ki_read_16_fc(cpu, ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(cpu); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_moves_16_di(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = EA_AY_DI_16(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_16_fc(cpu, ea, REG_DFC, MASK_OUT_ABOVE_16(REG_DA[(word2 >> 12) & 15])); + return; + } + if(BIT_F(word2)) /* Memory to address register */ + { + REG_A[(word2 >> 12) & 7] = MAKE_INT_16(m68ki_read_16_fc(cpu, ea, REG_SFC)); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to data register */ + REG_D[(word2 >> 12) & 7] = MASK_OUT_BELOW_16(REG_D[(word2 >> 12) & 7]) | m68ki_read_16_fc(cpu, ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(cpu); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_moves_16_ix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = EA_AY_IX_16(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_16_fc(cpu, ea, REG_DFC, MASK_OUT_ABOVE_16(REG_DA[(word2 >> 12) & 15])); + return; + } + if(BIT_F(word2)) /* Memory to address register */ + { + REG_A[(word2 >> 12) & 7] = MAKE_INT_16(m68ki_read_16_fc(cpu, ea, REG_SFC)); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to data register */ + REG_D[(word2 >> 12) & 7] = MASK_OUT_BELOW_16(REG_D[(word2 >> 12) & 7]) | m68ki_read_16_fc(cpu, ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(cpu); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_moves_16_aw(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = EA_AW_16(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_16_fc(cpu, ea, REG_DFC, MASK_OUT_ABOVE_16(REG_DA[(word2 >> 12) & 15])); + return; + } + if(BIT_F(word2)) /* Memory to address register */ + { + REG_A[(word2 >> 12) & 7] = MAKE_INT_16(m68ki_read_16_fc(cpu, ea, REG_SFC)); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to data register */ + REG_D[(word2 >> 12) & 7] = MASK_OUT_BELOW_16(REG_D[(word2 >> 12) & 7]) | m68ki_read_16_fc(cpu, ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(cpu); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_moves_16_al(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = EA_AL_16(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_16_fc(cpu, ea, REG_DFC, MASK_OUT_ABOVE_16(REG_DA[(word2 >> 12) & 15])); + return; + } + if(BIT_F(word2)) /* Memory to address register */ + { + REG_A[(word2 >> 12) & 7] = MAKE_INT_16(m68ki_read_16_fc(cpu, ea, REG_SFC)); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to data register */ + REG_D[(word2 >> 12) & 7] = MASK_OUT_BELOW_16(REG_D[(word2 >> 12) & 7]) | m68ki_read_16_fc(cpu, ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(cpu); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_moves_32_ai(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = EA_AY_AI_32(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_32_fc(cpu, ea, REG_DFC, REG_DA[(word2 >> 12) & 15]); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to register */ + REG_DA[(word2 >> 12) & 15] = m68ki_read_32_fc(cpu, ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(cpu); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_moves_32_pi(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = EA_AY_PI_32(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_32_fc(cpu, ea, REG_DFC, REG_DA[(word2 >> 12) & 15]); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to register */ + REG_DA[(word2 >> 12) & 15] = m68ki_read_32_fc(cpu, ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(cpu); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_moves_32_pd(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = EA_AY_PD_32(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_32_fc(cpu, ea, REG_DFC, REG_DA[(word2 >> 12) & 15]); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to register */ + REG_DA[(word2 >> 12) & 15] = m68ki_read_32_fc(cpu, ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(cpu); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_moves_32_di(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = EA_AY_DI_32(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_32_fc(cpu, ea, REG_DFC, REG_DA[(word2 >> 12) & 15]); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to register */ + REG_DA[(word2 >> 12) & 15] = m68ki_read_32_fc(cpu, ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(cpu); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_moves_32_ix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = EA_AY_IX_32(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_32_fc(cpu, ea, REG_DFC, REG_DA[(word2 >> 12) & 15]); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to register */ + REG_DA[(word2 >> 12) & 15] = m68ki_read_32_fc(cpu, ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(cpu); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_moves_32_aw(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = EA_AW_32(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_32_fc(cpu, ea, REG_DFC, REG_DA[(word2 >> 12) & 15]); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to register */ + REG_DA[(word2 >> 12) & 15] = m68ki_read_32_fc(cpu, ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(cpu); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_moves_32_al(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = EA_AL_32(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_32_fc(cpu, ea, REG_DFC, REG_DA[(word2 >> 12) & 15]); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to register */ + REG_DA[(word2 >> 12) & 15] = m68ki_read_32_fc(cpu, ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(cpu); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_moveq_32(m68ki_cpu_core *cpu) +{ + uint res = DX = MAKE_INT_8(MASK_OUT_ABOVE_8(REG_IR)); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_muls_16_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(DY) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_muls_16_ai(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(OPER_AY_AI_16(cpu)) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_muls_16_pi(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(OPER_AY_PI_16(cpu)) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_muls_16_pd(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(OPER_AY_PD_16(cpu)) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_muls_16_di(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(OPER_AY_DI_16(cpu)) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_muls_16_ix(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(OPER_AY_IX_16(cpu)) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_muls_16_aw(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(OPER_AW_16(cpu)) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_muls_16_al(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(OPER_AL_16(cpu)) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_muls_16_pcdi(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(OPER_PCDI_16(cpu)) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_muls_16_pcix(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(OPER_PCIX_16(cpu)) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_muls_16_i(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(OPER_I_16()) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_mulu_16_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint res = MASK_OUT_ABOVE_16(DY) * MASK_OUT_ABOVE_16(*r_dst); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_mulu_16_ai(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint res = OPER_AY_AI_16(cpu) * MASK_OUT_ABOVE_16(*r_dst); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_mulu_16_pi(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint res = OPER_AY_PI_16(cpu) * MASK_OUT_ABOVE_16(*r_dst); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_mulu_16_pd(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint res = OPER_AY_PD_16(cpu) * MASK_OUT_ABOVE_16(*r_dst); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_mulu_16_di(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint res = OPER_AY_DI_16(cpu) * MASK_OUT_ABOVE_16(*r_dst); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_mulu_16_ix(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint res = OPER_AY_IX_16(cpu) * MASK_OUT_ABOVE_16(*r_dst); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_mulu_16_aw(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint res = OPER_AW_16(cpu) * MASK_OUT_ABOVE_16(*r_dst); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_mulu_16_al(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint res = OPER_AL_16(cpu) * MASK_OUT_ABOVE_16(*r_dst); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_mulu_16_pcdi(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint res = OPER_PCDI_16(cpu) * MASK_OUT_ABOVE_16(*r_dst); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_mulu_16_pcix(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint res = OPER_PCIX_16(cpu) * MASK_OUT_ABOVE_16(*r_dst); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_mulu_16_i(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint res = OPER_I_16() * MASK_OUT_ABOVE_16(*r_dst); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_mull_32_d(m68ki_cpu_core *cpu) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 src = DY; + uint64 dst = REG_D[(word2 >> 12) & 7]; + uint64 res; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + res = (sint64)((sint32)src) * (sint64)((sint32)dst); + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = ((sint64)res != (sint32)res)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + + res = src * dst; + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = (res > 0xffffffff)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + m68ki_exception_illegal(cpu); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint src = DY; + uint dst = REG_D[(word2 >> 12) & 7]; + uint neg = GET_MSB_32(src ^ dst); + uint src1; + uint src2; + uint dst1; + uint dst2; + uint r1; + uint r2; + uint r3; + uint r4; + uint lo; + uint hi; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + if(GET_MSB_32(src)) + src = (uint)MASK_OUT_ABOVE_32(-(sint)src); + if(GET_MSB_32(dst)) + dst = (uint)MASK_OUT_ABOVE_32(-(sint)dst); + } + + src1 = MASK_OUT_ABOVE_16(src); + src2 = src>>16; + dst1 = MASK_OUT_ABOVE_16(dst); + dst2 = dst>>16; + + + r1 = src1 * dst1; + r2 = src1 * dst2; + r3 = src2 * dst1; + r4 = src2 * dst2; + + lo = r1 + (MASK_OUT_ABOVE_16(r2)<<16) + (MASK_OUT_ABOVE_16(r3)<<16); + hi = r4 + (r2>>16) + (r3>>16) + (((r1>>16) + MASK_OUT_ABOVE_16(r2) + MASK_OUT_ABOVE_16(r3)) >> 16); + + if(BIT_B(word2) && neg) + { + hi = (uint)MASK_OUT_ABOVE_32((-(sint)hi) - (lo != 0)); + lo = (uint)MASK_OUT_ABOVE_32(-(sint)lo); + } + + if(BIT_A(word2)) + { + REG_D[word2 & 7] = hi; + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(hi); + FLAG_Z = hi | lo; + FLAG_V = VFLAG_CLEAR; + return; + } + + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(lo); + FLAG_Z = lo; + if(BIT_B(word2)) + FLAG_V = (!((GET_MSB_32(lo) && hi == 0xffffffff) || (!GET_MSB_32(lo) && !hi)))<<7; + else + FLAG_V = (hi != 0) << 7; + return; + } + m68ki_exception_illegal(cpu); + +#endif +} + + +void m68k_op_mull_32_ai(m68ki_cpu_core *cpu) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 src = OPER_AY_AI_32(cpu); + uint64 dst = REG_D[(word2 >> 12) & 7]; + uint64 res; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + res = (sint64)((sint32)src) * (sint64)((sint32)dst); + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = ((sint64)res != (sint32)res)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + + res = src * dst; + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = (res > 0xffffffff)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + m68ki_exception_illegal(cpu); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint src = OPER_AY_AI_32(cpu); + uint dst = REG_D[(word2 >> 12) & 7]; + uint neg = GET_MSB_32(src ^ dst); + uint src1; + uint src2; + uint dst1; + uint dst2; + uint r1; + uint r2; + uint r3; + uint r4; + uint lo; + uint hi; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + if(GET_MSB_32(src)) + src = (uint)MASK_OUT_ABOVE_32(-(sint)src); + if(GET_MSB_32(dst)) + dst = (uint)MASK_OUT_ABOVE_32(-(sint)dst); + } + + src1 = MASK_OUT_ABOVE_16(src); + src2 = src>>16; + dst1 = MASK_OUT_ABOVE_16(dst); + dst2 = dst>>16; + + + r1 = src1 * dst1; + r2 = src1 * dst2; + r3 = src2 * dst1; + r4 = src2 * dst2; + + lo = r1 + (MASK_OUT_ABOVE_16(r2)<<16) + (MASK_OUT_ABOVE_16(r3)<<16); + hi = r4 + (r2>>16) + (r3>>16) + (((r1>>16) + MASK_OUT_ABOVE_16(r2) + MASK_OUT_ABOVE_16(r3)) >> 16); + + if(BIT_B(word2) && neg) + { + hi = (uint)MASK_OUT_ABOVE_32((-(sint)hi) - (lo != 0)); + lo = (uint)MASK_OUT_ABOVE_32(-(sint)lo); + } + + if(BIT_A(word2)) + { + REG_D[word2 & 7] = hi; + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(hi); + FLAG_Z = hi | lo; + FLAG_V = VFLAG_CLEAR; + return; + } + + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(lo); + FLAG_Z = lo; + if(BIT_B(word2)) + FLAG_V = (!((GET_MSB_32(lo) && hi == 0xffffffff) || (!GET_MSB_32(lo) && !hi)))<<7; + else + FLAG_V = (hi != 0) << 7; + return; + } + m68ki_exception_illegal(cpu); + +#endif +} + + +void m68k_op_mull_32_pi(m68ki_cpu_core *cpu) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 src = OPER_AY_PI_32(cpu); + uint64 dst = REG_D[(word2 >> 12) & 7]; + uint64 res; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + res = (sint64)((sint32)src) * (sint64)((sint32)dst); + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = ((sint64)res != (sint32)res)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + + res = src * dst; + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = (res > 0xffffffff)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + m68ki_exception_illegal(cpu); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint src = OPER_AY_PI_32(cpu); + uint dst = REG_D[(word2 >> 12) & 7]; + uint neg = GET_MSB_32(src ^ dst); + uint src1; + uint src2; + uint dst1; + uint dst2; + uint r1; + uint r2; + uint r3; + uint r4; + uint lo; + uint hi; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + if(GET_MSB_32(src)) + src = (uint)MASK_OUT_ABOVE_32(-(sint)src); + if(GET_MSB_32(dst)) + dst = (uint)MASK_OUT_ABOVE_32(-(sint)dst); + } + + src1 = MASK_OUT_ABOVE_16(src); + src2 = src>>16; + dst1 = MASK_OUT_ABOVE_16(dst); + dst2 = dst>>16; + + + r1 = src1 * dst1; + r2 = src1 * dst2; + r3 = src2 * dst1; + r4 = src2 * dst2; + + lo = r1 + (MASK_OUT_ABOVE_16(r2)<<16) + (MASK_OUT_ABOVE_16(r3)<<16); + hi = r4 + (r2>>16) + (r3>>16) + (((r1>>16) + MASK_OUT_ABOVE_16(r2) + MASK_OUT_ABOVE_16(r3)) >> 16); + + if(BIT_B(word2) && neg) + { + hi = (uint)MASK_OUT_ABOVE_32((-(sint)hi) - (lo != 0)); + lo = (uint)MASK_OUT_ABOVE_32(-(sint)lo); + } + + if(BIT_A(word2)) + { + REG_D[word2 & 7] = hi; + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(hi); + FLAG_Z = hi | lo; + FLAG_V = VFLAG_CLEAR; + return; + } + + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(lo); + FLAG_Z = lo; + if(BIT_B(word2)) + FLAG_V = (!((GET_MSB_32(lo) && hi == 0xffffffff) || (!GET_MSB_32(lo) && !hi)))<<7; + else + FLAG_V = (hi != 0) << 7; + return; + } + m68ki_exception_illegal(cpu); + +#endif +} + + +void m68k_op_mull_32_pd(m68ki_cpu_core *cpu) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 src = OPER_AY_PD_32(cpu); + uint64 dst = REG_D[(word2 >> 12) & 7]; + uint64 res; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + res = (sint64)((sint32)src) * (sint64)((sint32)dst); + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = ((sint64)res != (sint32)res)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + + res = src * dst; + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = (res > 0xffffffff)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + m68ki_exception_illegal(cpu); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint src = OPER_AY_PD_32(cpu); + uint dst = REG_D[(word2 >> 12) & 7]; + uint neg = GET_MSB_32(src ^ dst); + uint src1; + uint src2; + uint dst1; + uint dst2; + uint r1; + uint r2; + uint r3; + uint r4; + uint lo; + uint hi; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + if(GET_MSB_32(src)) + src = (uint)MASK_OUT_ABOVE_32(-(sint)src); + if(GET_MSB_32(dst)) + dst = (uint)MASK_OUT_ABOVE_32(-(sint)dst); + } + + src1 = MASK_OUT_ABOVE_16(src); + src2 = src>>16; + dst1 = MASK_OUT_ABOVE_16(dst); + dst2 = dst>>16; + + + r1 = src1 * dst1; + r2 = src1 * dst2; + r3 = src2 * dst1; + r4 = src2 * dst2; + + lo = r1 + (MASK_OUT_ABOVE_16(r2)<<16) + (MASK_OUT_ABOVE_16(r3)<<16); + hi = r4 + (r2>>16) + (r3>>16) + (((r1>>16) + MASK_OUT_ABOVE_16(r2) + MASK_OUT_ABOVE_16(r3)) >> 16); + + if(BIT_B(word2) && neg) + { + hi = (uint)MASK_OUT_ABOVE_32((-(sint)hi) - (lo != 0)); + lo = (uint)MASK_OUT_ABOVE_32(-(sint)lo); + } + + if(BIT_A(word2)) + { + REG_D[word2 & 7] = hi; + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(hi); + FLAG_Z = hi | lo; + FLAG_V = VFLAG_CLEAR; + return; + } + + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(lo); + FLAG_Z = lo; + if(BIT_B(word2)) + FLAG_V = (!((GET_MSB_32(lo) && hi == 0xffffffff) || (!GET_MSB_32(lo) && !hi)))<<7; + else + FLAG_V = (hi != 0) << 7; + return; + } + m68ki_exception_illegal(cpu); + +#endif +} + + +void m68k_op_mull_32_di(m68ki_cpu_core *cpu) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 src = OPER_AY_DI_32(cpu); + uint64 dst = REG_D[(word2 >> 12) & 7]; + uint64 res; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + res = (sint64)((sint32)src) * (sint64)((sint32)dst); + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = ((sint64)res != (sint32)res)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + + res = src * dst; + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = (res > 0xffffffff)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + m68ki_exception_illegal(cpu); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint src = OPER_AY_DI_32(cpu); + uint dst = REG_D[(word2 >> 12) & 7]; + uint neg = GET_MSB_32(src ^ dst); + uint src1; + uint src2; + uint dst1; + uint dst2; + uint r1; + uint r2; + uint r3; + uint r4; + uint lo; + uint hi; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + if(GET_MSB_32(src)) + src = (uint)MASK_OUT_ABOVE_32(-(sint)src); + if(GET_MSB_32(dst)) + dst = (uint)MASK_OUT_ABOVE_32(-(sint)dst); + } + + src1 = MASK_OUT_ABOVE_16(src); + src2 = src>>16; + dst1 = MASK_OUT_ABOVE_16(dst); + dst2 = dst>>16; + + + r1 = src1 * dst1; + r2 = src1 * dst2; + r3 = src2 * dst1; + r4 = src2 * dst2; + + lo = r1 + (MASK_OUT_ABOVE_16(r2)<<16) + (MASK_OUT_ABOVE_16(r3)<<16); + hi = r4 + (r2>>16) + (r3>>16) + (((r1>>16) + MASK_OUT_ABOVE_16(r2) + MASK_OUT_ABOVE_16(r3)) >> 16); + + if(BIT_B(word2) && neg) + { + hi = (uint)MASK_OUT_ABOVE_32((-(sint)hi) - (lo != 0)); + lo = (uint)MASK_OUT_ABOVE_32(-(sint)lo); + } + + if(BIT_A(word2)) + { + REG_D[word2 & 7] = hi; + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(hi); + FLAG_Z = hi | lo; + FLAG_V = VFLAG_CLEAR; + return; + } + + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(lo); + FLAG_Z = lo; + if(BIT_B(word2)) + FLAG_V = (!((GET_MSB_32(lo) && hi == 0xffffffff) || (!GET_MSB_32(lo) && !hi)))<<7; + else + FLAG_V = (hi != 0) << 7; + return; + } + m68ki_exception_illegal(cpu); + +#endif +} + + +void m68k_op_mull_32_ix(m68ki_cpu_core *cpu) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 src = OPER_AY_IX_32(cpu); + uint64 dst = REG_D[(word2 >> 12) & 7]; + uint64 res; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + res = (sint64)((sint32)src) * (sint64)((sint32)dst); + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = ((sint64)res != (sint32)res)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + + res = src * dst; + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = (res > 0xffffffff)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + m68ki_exception_illegal(cpu); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint src = OPER_AY_IX_32(cpu); + uint dst = REG_D[(word2 >> 12) & 7]; + uint neg = GET_MSB_32(src ^ dst); + uint src1; + uint src2; + uint dst1; + uint dst2; + uint r1; + uint r2; + uint r3; + uint r4; + uint lo; + uint hi; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + if(GET_MSB_32(src)) + src = (uint)MASK_OUT_ABOVE_32(-(sint)src); + if(GET_MSB_32(dst)) + dst = (uint)MASK_OUT_ABOVE_32(-(sint)dst); + } + + src1 = MASK_OUT_ABOVE_16(src); + src2 = src>>16; + dst1 = MASK_OUT_ABOVE_16(dst); + dst2 = dst>>16; + + + r1 = src1 * dst1; + r2 = src1 * dst2; + r3 = src2 * dst1; + r4 = src2 * dst2; + + lo = r1 + (MASK_OUT_ABOVE_16(r2)<<16) + (MASK_OUT_ABOVE_16(r3)<<16); + hi = r4 + (r2>>16) + (r3>>16) + (((r1>>16) + MASK_OUT_ABOVE_16(r2) + MASK_OUT_ABOVE_16(r3)) >> 16); + + if(BIT_B(word2) && neg) + { + hi = (uint)MASK_OUT_ABOVE_32((-(sint)hi) - (lo != 0)); + lo = (uint)MASK_OUT_ABOVE_32(-(sint)lo); + } + + if(BIT_A(word2)) + { + REG_D[word2 & 7] = hi; + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(hi); + FLAG_Z = hi | lo; + FLAG_V = VFLAG_CLEAR; + return; + } + + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(lo); + FLAG_Z = lo; + if(BIT_B(word2)) + FLAG_V = (!((GET_MSB_32(lo) && hi == 0xffffffff) || (!GET_MSB_32(lo) && !hi)))<<7; + else + FLAG_V = (hi != 0) << 7; + return; + } + m68ki_exception_illegal(cpu); + +#endif +} + + +void m68k_op_mull_32_aw(m68ki_cpu_core *cpu) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 src = OPER_AW_32(cpu); + uint64 dst = REG_D[(word2 >> 12) & 7]; + uint64 res; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + res = (sint64)((sint32)src) * (sint64)((sint32)dst); + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = ((sint64)res != (sint32)res)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + + res = src * dst; + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = (res > 0xffffffff)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + m68ki_exception_illegal(cpu); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint src = OPER_AW_32(cpu); + uint dst = REG_D[(word2 >> 12) & 7]; + uint neg = GET_MSB_32(src ^ dst); + uint src1; + uint src2; + uint dst1; + uint dst2; + uint r1; + uint r2; + uint r3; + uint r4; + uint lo; + uint hi; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + if(GET_MSB_32(src)) + src = (uint)MASK_OUT_ABOVE_32(-(sint)src); + if(GET_MSB_32(dst)) + dst = (uint)MASK_OUT_ABOVE_32(-(sint)dst); + } + + src1 = MASK_OUT_ABOVE_16(src); + src2 = src>>16; + dst1 = MASK_OUT_ABOVE_16(dst); + dst2 = dst>>16; + + + r1 = src1 * dst1; + r2 = src1 * dst2; + r3 = src2 * dst1; + r4 = src2 * dst2; + + lo = r1 + (MASK_OUT_ABOVE_16(r2)<<16) + (MASK_OUT_ABOVE_16(r3)<<16); + hi = r4 + (r2>>16) + (r3>>16) + (((r1>>16) + MASK_OUT_ABOVE_16(r2) + MASK_OUT_ABOVE_16(r3)) >> 16); + + if(BIT_B(word2) && neg) + { + hi = (uint)MASK_OUT_ABOVE_32((-(sint)hi) - (lo != 0)); + lo = (uint)MASK_OUT_ABOVE_32(-(sint)lo); + } + + if(BIT_A(word2)) + { + REG_D[word2 & 7] = hi; + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(hi); + FLAG_Z = hi | lo; + FLAG_V = VFLAG_CLEAR; + return; + } + + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(lo); + FLAG_Z = lo; + if(BIT_B(word2)) + FLAG_V = (!((GET_MSB_32(lo) && hi == 0xffffffff) || (!GET_MSB_32(lo) && !hi)))<<7; + else + FLAG_V = (hi != 0) << 7; + return; + } + m68ki_exception_illegal(cpu); + +#endif +} + + +void m68k_op_mull_32_al(m68ki_cpu_core *cpu) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 src = OPER_AL_32(cpu); + uint64 dst = REG_D[(word2 >> 12) & 7]; + uint64 res; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + res = (sint64)((sint32)src) * (sint64)((sint32)dst); + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = ((sint64)res != (sint32)res)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + + res = src * dst; + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = (res > 0xffffffff)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + m68ki_exception_illegal(cpu); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint src = OPER_AL_32(cpu); + uint dst = REG_D[(word2 >> 12) & 7]; + uint neg = GET_MSB_32(src ^ dst); + uint src1; + uint src2; + uint dst1; + uint dst2; + uint r1; + uint r2; + uint r3; + uint r4; + uint lo; + uint hi; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + if(GET_MSB_32(src)) + src = (uint)MASK_OUT_ABOVE_32(-(sint)src); + if(GET_MSB_32(dst)) + dst = (uint)MASK_OUT_ABOVE_32(-(sint)dst); + } + + src1 = MASK_OUT_ABOVE_16(src); + src2 = src>>16; + dst1 = MASK_OUT_ABOVE_16(dst); + dst2 = dst>>16; + + + r1 = src1 * dst1; + r2 = src1 * dst2; + r3 = src2 * dst1; + r4 = src2 * dst2; + + lo = r1 + (MASK_OUT_ABOVE_16(r2)<<16) + (MASK_OUT_ABOVE_16(r3)<<16); + hi = r4 + (r2>>16) + (r3>>16) + (((r1>>16) + MASK_OUT_ABOVE_16(r2) + MASK_OUT_ABOVE_16(r3)) >> 16); + + if(BIT_B(word2) && neg) + { + hi = (uint)MASK_OUT_ABOVE_32((-(sint)hi) - (lo != 0)); + lo = (uint)MASK_OUT_ABOVE_32(-(sint)lo); + } + + if(BIT_A(word2)) + { + REG_D[word2 & 7] = hi; + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(hi); + FLAG_Z = hi | lo; + FLAG_V = VFLAG_CLEAR; + return; + } + + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(lo); + FLAG_Z = lo; + if(BIT_B(word2)) + FLAG_V = (!((GET_MSB_32(lo) && hi == 0xffffffff) || (!GET_MSB_32(lo) && !hi)))<<7; + else + FLAG_V = (hi != 0) << 7; + return; + } + m68ki_exception_illegal(cpu); + +#endif +} + + +void m68k_op_mull_32_pcdi(m68ki_cpu_core *cpu) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 src = OPER_PCDI_32(cpu); + uint64 dst = REG_D[(word2 >> 12) & 7]; + uint64 res; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + res = (sint64)((sint32)src) * (sint64)((sint32)dst); + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = ((sint64)res != (sint32)res)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + + res = src * dst; + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = (res > 0xffffffff)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + m68ki_exception_illegal(cpu); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint src = OPER_PCDI_32(cpu); + uint dst = REG_D[(word2 >> 12) & 7]; + uint neg = GET_MSB_32(src ^ dst); + uint src1; + uint src2; + uint dst1; + uint dst2; + uint r1; + uint r2; + uint r3; + uint r4; + uint lo; + uint hi; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + if(GET_MSB_32(src)) + src = (uint)MASK_OUT_ABOVE_32(-(sint)src); + if(GET_MSB_32(dst)) + dst = (uint)MASK_OUT_ABOVE_32(-(sint)dst); + } + + src1 = MASK_OUT_ABOVE_16(src); + src2 = src>>16; + dst1 = MASK_OUT_ABOVE_16(dst); + dst2 = dst>>16; + + + r1 = src1 * dst1; + r2 = src1 * dst2; + r3 = src2 * dst1; + r4 = src2 * dst2; + + lo = r1 + (MASK_OUT_ABOVE_16(r2)<<16) + (MASK_OUT_ABOVE_16(r3)<<16); + hi = r4 + (r2>>16) + (r3>>16) + (((r1>>16) + MASK_OUT_ABOVE_16(r2) + MASK_OUT_ABOVE_16(r3)) >> 16); + + if(BIT_B(word2) && neg) + { + hi = (uint)MASK_OUT_ABOVE_32((-(sint)hi) - (lo != 0)); + lo = (uint)MASK_OUT_ABOVE_32(-(sint)lo); + } + + if(BIT_A(word2)) + { + REG_D[word2 & 7] = hi; + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(hi); + FLAG_Z = hi | lo; + FLAG_V = VFLAG_CLEAR; + return; + } + + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(lo); + FLAG_Z = lo; + if(BIT_B(word2)) + FLAG_V = (!((GET_MSB_32(lo) && hi == 0xffffffff) || (!GET_MSB_32(lo) && !hi)))<<7; + else + FLAG_V = (hi != 0) << 7; + return; + } + m68ki_exception_illegal(cpu); + +#endif +} + + +void m68k_op_mull_32_pcix(m68ki_cpu_core *cpu) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 src = OPER_PCIX_32(cpu); + uint64 dst = REG_D[(word2 >> 12) & 7]; + uint64 res; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + res = (sint64)((sint32)src) * (sint64)((sint32)dst); + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = ((sint64)res != (sint32)res)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + + res = src * dst; + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = (res > 0xffffffff)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + m68ki_exception_illegal(cpu); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint src = OPER_PCIX_32(cpu); + uint dst = REG_D[(word2 >> 12) & 7]; + uint neg = GET_MSB_32(src ^ dst); + uint src1; + uint src2; + uint dst1; + uint dst2; + uint r1; + uint r2; + uint r3; + uint r4; + uint lo; + uint hi; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + if(GET_MSB_32(src)) + src = (uint)MASK_OUT_ABOVE_32(-(sint)src); + if(GET_MSB_32(dst)) + dst = (uint)MASK_OUT_ABOVE_32(-(sint)dst); + } + + src1 = MASK_OUT_ABOVE_16(src); + src2 = src>>16; + dst1 = MASK_OUT_ABOVE_16(dst); + dst2 = dst>>16; + + + r1 = src1 * dst1; + r2 = src1 * dst2; + r3 = src2 * dst1; + r4 = src2 * dst2; + + lo = r1 + (MASK_OUT_ABOVE_16(r2)<<16) + (MASK_OUT_ABOVE_16(r3)<<16); + hi = r4 + (r2>>16) + (r3>>16) + (((r1>>16) + MASK_OUT_ABOVE_16(r2) + MASK_OUT_ABOVE_16(r3)) >> 16); + + if(BIT_B(word2) && neg) + { + hi = (uint)MASK_OUT_ABOVE_32((-(sint)hi) - (lo != 0)); + lo = (uint)MASK_OUT_ABOVE_32(-(sint)lo); + } + + if(BIT_A(word2)) + { + REG_D[word2 & 7] = hi; + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(hi); + FLAG_Z = hi | lo; + FLAG_V = VFLAG_CLEAR; + return; + } + + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(lo); + FLAG_Z = lo; + if(BIT_B(word2)) + FLAG_V = (!((GET_MSB_32(lo) && hi == 0xffffffff) || (!GET_MSB_32(lo) && !hi)))<<7; + else + FLAG_V = (hi != 0) << 7; + return; + } + m68ki_exception_illegal(cpu); + +#endif +} + + +void m68k_op_mull_32_i(m68ki_cpu_core *cpu) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 src = OPER_I_32(); + uint64 dst = REG_D[(word2 >> 12) & 7]; + uint64 res; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + res = (sint64)((sint32)src) * (sint64)((sint32)dst); + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = ((sint64)res != (sint32)res)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + + res = src * dst; + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = (res > 0xffffffff)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + m68ki_exception_illegal(cpu); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint src = OPER_I_32(); + uint dst = REG_D[(word2 >> 12) & 7]; + uint neg = GET_MSB_32(src ^ dst); + uint src1; + uint src2; + uint dst1; + uint dst2; + uint r1; + uint r2; + uint r3; + uint r4; + uint lo; + uint hi; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + if(GET_MSB_32(src)) + src = (uint)MASK_OUT_ABOVE_32(-(sint)src); + if(GET_MSB_32(dst)) + dst = (uint)MASK_OUT_ABOVE_32(-(sint)dst); + } + + src1 = MASK_OUT_ABOVE_16(src); + src2 = src>>16; + dst1 = MASK_OUT_ABOVE_16(dst); + dst2 = dst>>16; + + + r1 = src1 * dst1; + r2 = src1 * dst2; + r3 = src2 * dst1; + r4 = src2 * dst2; + + lo = r1 + (MASK_OUT_ABOVE_16(r2)<<16) + (MASK_OUT_ABOVE_16(r3)<<16); + hi = r4 + (r2>>16) + (r3>>16) + (((r1>>16) + MASK_OUT_ABOVE_16(r2) + MASK_OUT_ABOVE_16(r3)) >> 16); + + if(BIT_B(word2) && neg) + { + hi = (uint)MASK_OUT_ABOVE_32((-(sint)hi) - (lo != 0)); + lo = (uint)MASK_OUT_ABOVE_32(-(sint)lo); + } + + if(BIT_A(word2)) + { + REG_D[word2 & 7] = hi; + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(hi); + FLAG_Z = hi | lo; + FLAG_V = VFLAG_CLEAR; + return; + } + + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(lo); + FLAG_Z = lo; + if(BIT_B(word2)) + FLAG_V = (!((GET_MSB_32(lo) && hi == 0xffffffff) || (!GET_MSB_32(lo) && !hi)))<<7; + else + FLAG_V = (hi != 0) << 7; + return; + } + m68ki_exception_illegal(cpu); + +#endif +} + + +/* ======================================================================== */ +/* ============================== END OF FILE ============================= */ +/* ======================================================================== */ + + diff --git a/plugins/ao/eng_ssf/m68kopnz.c b/plugins/ao/eng_ssf/m68kopnz.c new file mode 100644 index 00000000..35a6ed16 --- /dev/null +++ b/plugins/ao/eng_ssf/m68kopnz.c @@ -0,0 +1,8781 @@ +#include "ao.h" +#include "m68kcpu.h" + +/* ======================================================================== */ +/* ========================= INSTRUCTION HANDLERS ========================= */ +/* ======================================================================== */ + + +void m68k_op_nbcd_8_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint dst = *r_dst; + uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1()); + + if(res != 0x9a) + { + FLAG_V = ~res; /* Undefined V behavior */ + + if((res & 0x0f) == 0xa) + res = (res & 0xf0) + 0x10; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_Z |= res; + FLAG_C = CFLAG_SET; + FLAG_X = XFLAG_SET; + } + else + { + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_X = XFLAG_CLEAR; + } + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ +} + + +void m68k_op_nbcd_8_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_8(); + uint dst = m68ki_read_8(ea); + uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1()); + + if(res != 0x9a) + { + FLAG_V = ~res; /* Undefined V behavior */ + + if((res & 0x0f) == 0xa) + res = (res & 0xf0) + 0x10; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + + m68ki_write_8(ea, MASK_OUT_ABOVE_8(res)); + + FLAG_Z |= res; + FLAG_C = CFLAG_SET; + FLAG_X = XFLAG_SET; + } + else + { + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_X = XFLAG_CLEAR; + } + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ +} + + +void m68k_op_nbcd_8_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_8(); + uint dst = m68ki_read_8(ea); + uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1()); + + if(res != 0x9a) + { + FLAG_V = ~res; /* Undefined V behavior */ + + if((res & 0x0f) == 0xa) + res = (res & 0xf0) + 0x10; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + + m68ki_write_8(ea, MASK_OUT_ABOVE_8(res)); + + FLAG_Z |= res; + FLAG_C = CFLAG_SET; + FLAG_X = XFLAG_SET; + } + else + { + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_X = XFLAG_CLEAR; + } + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ +} + + +void m68k_op_nbcd_8_pi7(m68ki_cpu_core *cpu) +{ + uint ea = EA_A7_PI_8(); + uint dst = m68ki_read_8(ea); + uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1()); + + if(res != 0x9a) + { + FLAG_V = ~res; /* Undefined V behavior */ + + if((res & 0x0f) == 0xa) + res = (res & 0xf0) + 0x10; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + + m68ki_write_8(ea, MASK_OUT_ABOVE_8(res)); + + FLAG_Z |= res; + FLAG_C = CFLAG_SET; + FLAG_X = XFLAG_SET; + } + else + { + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_X = XFLAG_CLEAR; + } + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ +} + + +void m68k_op_nbcd_8_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1()); + + if(res != 0x9a) + { + FLAG_V = ~res; /* Undefined V behavior */ + + if((res & 0x0f) == 0xa) + res = (res & 0xf0) + 0x10; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + + m68ki_write_8(ea, MASK_OUT_ABOVE_8(res)); + + FLAG_Z |= res; + FLAG_C = CFLAG_SET; + FLAG_X = XFLAG_SET; + } + else + { + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_X = XFLAG_CLEAR; + } + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ +} + + +void m68k_op_nbcd_8_pd7(m68ki_cpu_core *cpu) +{ + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1()); + + if(res != 0x9a) + { + FLAG_V = ~res; /* Undefined V behavior */ + + if((res & 0x0f) == 0xa) + res = (res & 0xf0) + 0x10; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + + m68ki_write_8(ea, MASK_OUT_ABOVE_8(res)); + + FLAG_Z |= res; + FLAG_C = CFLAG_SET; + FLAG_X = XFLAG_SET; + } + else + { + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_X = XFLAG_CLEAR; + } + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ +} + + +void m68k_op_nbcd_8_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_8(); + uint dst = m68ki_read_8(ea); + uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1()); + + if(res != 0x9a) + { + FLAG_V = ~res; /* Undefined V behavior */ + + if((res & 0x0f) == 0xa) + res = (res & 0xf0) + 0x10; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + + m68ki_write_8(ea, MASK_OUT_ABOVE_8(res)); + + FLAG_Z |= res; + FLAG_C = CFLAG_SET; + FLAG_X = XFLAG_SET; + } + else + { + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_X = XFLAG_CLEAR; + } + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ +} + + +void m68k_op_nbcd_8_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_8(); + uint dst = m68ki_read_8(ea); + uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1()); + + if(res != 0x9a) + { + FLAG_V = ~res; /* Undefined V behavior */ + + if((res & 0x0f) == 0xa) + res = (res & 0xf0) + 0x10; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + + m68ki_write_8(ea, MASK_OUT_ABOVE_8(res)); + + FLAG_Z |= res; + FLAG_C = CFLAG_SET; + FLAG_X = XFLAG_SET; + } + else + { + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_X = XFLAG_CLEAR; + } + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ +} + + +void m68k_op_nbcd_8_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_8(); + uint dst = m68ki_read_8(ea); + uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1()); + + if(res != 0x9a) + { + FLAG_V = ~res; /* Undefined V behavior */ + + if((res & 0x0f) == 0xa) + res = (res & 0xf0) + 0x10; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + + m68ki_write_8(ea, MASK_OUT_ABOVE_8(res)); + + FLAG_Z |= res; + FLAG_C = CFLAG_SET; + FLAG_X = XFLAG_SET; + } + else + { + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_X = XFLAG_CLEAR; + } + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ +} + + +void m68k_op_nbcd_8_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_8(); + uint dst = m68ki_read_8(ea); + uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1()); + + if(res != 0x9a) + { + FLAG_V = ~res; /* Undefined V behavior */ + + if((res & 0x0f) == 0xa) + res = (res & 0xf0) + 0x10; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + + m68ki_write_8(ea, MASK_OUT_ABOVE_8(res)); + + FLAG_Z |= res; + FLAG_C = CFLAG_SET; + FLAG_X = XFLAG_SET; + } + else + { + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_X = XFLAG_CLEAR; + } + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ +} + + +void m68k_op_neg_8_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint res = 0 - MASK_OUT_ABOVE_8(*r_dst); + + FLAG_N = NFLAG_8(res); + FLAG_C = FLAG_X = CFLAG_8(res); + FLAG_V = *r_dst & res; + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_neg_8_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_8(); + uint src = m68ki_read_8(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_8(res); + FLAG_C = FLAG_X = CFLAG_8(res); + FLAG_V = src & res; + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_neg_8_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_8(); + uint src = m68ki_read_8(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_8(res); + FLAG_C = FLAG_X = CFLAG_8(res); + FLAG_V = src & res; + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_neg_8_pi7(m68ki_cpu_core *cpu) +{ + uint ea = EA_A7_PI_8(); + uint src = m68ki_read_8(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_8(res); + FLAG_C = FLAG_X = CFLAG_8(res); + FLAG_V = src & res; + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_neg_8_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_8(); + uint src = m68ki_read_8(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_8(res); + FLAG_C = FLAG_X = CFLAG_8(res); + FLAG_V = src & res; + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_neg_8_pd7(m68ki_cpu_core *cpu) +{ + uint ea = EA_A7_PD_8(); + uint src = m68ki_read_8(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_8(res); + FLAG_C = FLAG_X = CFLAG_8(res); + FLAG_V = src & res; + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_neg_8_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_8(); + uint src = m68ki_read_8(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_8(res); + FLAG_C = FLAG_X = CFLAG_8(res); + FLAG_V = src & res; + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_neg_8_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_8(); + uint src = m68ki_read_8(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_8(res); + FLAG_C = FLAG_X = CFLAG_8(res); + FLAG_V = src & res; + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_neg_8_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_8(); + uint src = m68ki_read_8(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_8(res); + FLAG_C = FLAG_X = CFLAG_8(res); + FLAG_V = src & res; + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_neg_8_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_8(); + uint src = m68ki_read_8(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_8(res); + FLAG_C = FLAG_X = CFLAG_8(res); + FLAG_V = src & res; + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_neg_16_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint res = 0 - MASK_OUT_ABOVE_16(*r_dst); + + FLAG_N = NFLAG_16(res); + FLAG_C = FLAG_X = CFLAG_16(res); + FLAG_V = (*r_dst & res)>>8; + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +void m68k_op_neg_16_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_16(); + uint src = m68ki_read_16(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_16(res); + FLAG_C = FLAG_X = CFLAG_16(res); + FLAG_V = (src & res)>>8; + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_neg_16_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_16(); + uint src = m68ki_read_16(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_16(res); + FLAG_C = FLAG_X = CFLAG_16(res); + FLAG_V = (src & res)>>8; + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_neg_16_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_16(); + uint src = m68ki_read_16(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_16(res); + FLAG_C = FLAG_X = CFLAG_16(res); + FLAG_V = (src & res)>>8; + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_neg_16_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_16(); + uint src = m68ki_read_16(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_16(res); + FLAG_C = FLAG_X = CFLAG_16(res); + FLAG_V = (src & res)>>8; + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_neg_16_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_16(); + uint src = m68ki_read_16(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_16(res); + FLAG_C = FLAG_X = CFLAG_16(res); + FLAG_V = (src & res)>>8; + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_neg_16_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_16(); + uint src = m68ki_read_16(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_16(res); + FLAG_C = FLAG_X = CFLAG_16(res); + FLAG_V = (src & res)>>8; + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_neg_16_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_16(); + uint src = m68ki_read_16(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_16(res); + FLAG_C = FLAG_X = CFLAG_16(res); + FLAG_V = (src & res)>>8; + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_neg_32_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint res = 0 - *r_dst; + + FLAG_N = NFLAG_32(res); + FLAG_C = FLAG_X = CFLAG_SUB_32(*r_dst, 0, res); + FLAG_V = (*r_dst & res)>>24; + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +void m68k_op_neg_32_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_32(); + uint src = m68ki_read_32(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_32(res); + FLAG_C = FLAG_X = CFLAG_SUB_32(src, 0, res); + FLAG_V = (src & res)>>24; + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_neg_32_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_32(); + uint src = m68ki_read_32(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_32(res); + FLAG_C = FLAG_X = CFLAG_SUB_32(src, 0, res); + FLAG_V = (src & res)>>24; + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_neg_32_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_32(); + uint src = m68ki_read_32(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_32(res); + FLAG_C = FLAG_X = CFLAG_SUB_32(src, 0, res); + FLAG_V = (src & res)>>24; + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_neg_32_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_32(); + uint src = m68ki_read_32(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_32(res); + FLAG_C = FLAG_X = CFLAG_SUB_32(src, 0, res); + FLAG_V = (src & res)>>24; + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_neg_32_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_32(); + uint src = m68ki_read_32(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_32(res); + FLAG_C = FLAG_X = CFLAG_SUB_32(src, 0, res); + FLAG_V = (src & res)>>24; + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_neg_32_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_32(); + uint src = m68ki_read_32(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_32(res); + FLAG_C = FLAG_X = CFLAG_SUB_32(src, 0, res); + FLAG_V = (src & res)>>24; + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_neg_32_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_32(); + uint src = m68ki_read_32(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_32(res); + FLAG_C = FLAG_X = CFLAG_SUB_32(src, 0, res); + FLAG_V = (src & res)>>24; + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_negx_8_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint res = 0 - MASK_OUT_ABOVE_8(*r_dst) - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = *r_dst & res; + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; +} + + +void m68k_op_negx_8_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_8(); + uint src = m68ki_read_8(ea); + uint res = 0 - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = src & res; + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +void m68k_op_negx_8_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_8(); + uint src = m68ki_read_8(ea); + uint res = 0 - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = src & res; + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +void m68k_op_negx_8_pi7(m68ki_cpu_core *cpu) +{ + uint ea = EA_A7_PI_8(); + uint src = m68ki_read_8(ea); + uint res = 0 - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = src & res; + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +void m68k_op_negx_8_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_8(); + uint src = m68ki_read_8(ea); + uint res = 0 - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = src & res; + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +void m68k_op_negx_8_pd7(m68ki_cpu_core *cpu) +{ + uint ea = EA_A7_PD_8(); + uint src = m68ki_read_8(ea); + uint res = 0 - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = src & res; + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +void m68k_op_negx_8_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_8(); + uint src = m68ki_read_8(ea); + uint res = 0 - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = src & res; + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +void m68k_op_negx_8_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_8(); + uint src = m68ki_read_8(ea); + uint res = 0 - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = src & res; + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +void m68k_op_negx_8_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_8(); + uint src = m68ki_read_8(ea); + uint res = 0 - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = src & res; + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +void m68k_op_negx_8_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_8(); + uint src = m68ki_read_8(ea); + uint res = 0 - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = src & res; + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +void m68k_op_negx_16_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint res = 0 - MASK_OUT_ABOVE_16(*r_dst) - XFLAG_AS_1(); + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = (*r_dst & res)>>8; + + res = MASK_OUT_ABOVE_16(res); + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; +} + + +void m68k_op_negx_16_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_16(); + uint src = m68ki_read_16(ea); + uint res = 0 - MASK_OUT_ABOVE_16(src) - XFLAG_AS_1(); + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = (src & res)>>8; + + res = MASK_OUT_ABOVE_16(res); + FLAG_Z |= res; + + m68ki_write_16(ea, res); +} + + +void m68k_op_negx_16_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_16(); + uint src = m68ki_read_16(ea); + uint res = 0 - MASK_OUT_ABOVE_16(src) - XFLAG_AS_1(); + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = (src & res)>>8; + + res = MASK_OUT_ABOVE_16(res); + FLAG_Z |= res; + + m68ki_write_16(ea, res); +} + + +void m68k_op_negx_16_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_16(); + uint src = m68ki_read_16(ea); + uint res = 0 - MASK_OUT_ABOVE_16(src) - XFLAG_AS_1(); + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = (src & res)>>8; + + res = MASK_OUT_ABOVE_16(res); + FLAG_Z |= res; + + m68ki_write_16(ea, res); +} + + +void m68k_op_negx_16_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_16(); + uint src = m68ki_read_16(ea); + uint res = 0 - MASK_OUT_ABOVE_16(src) - XFLAG_AS_1(); + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = (src & res)>>8; + + res = MASK_OUT_ABOVE_16(res); + FLAG_Z |= res; + + m68ki_write_16(ea, res); +} + + +void m68k_op_negx_16_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_16(); + uint src = m68ki_read_16(ea); + uint res = 0 - MASK_OUT_ABOVE_16(src) - XFLAG_AS_1(); + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = (src & res)>>8; + + res = MASK_OUT_ABOVE_16(res); + FLAG_Z |= res; + + m68ki_write_16(ea, res); +} + + +void m68k_op_negx_16_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_16(); + uint src = m68ki_read_16(ea); + uint res = 0 - MASK_OUT_ABOVE_16(src) - XFLAG_AS_1(); + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = (src & res)>>8; + + res = MASK_OUT_ABOVE_16(res); + FLAG_Z |= res; + + m68ki_write_16(ea, res); +} + + +void m68k_op_negx_16_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_16(); + uint src = m68ki_read_16(ea); + uint res = 0 - MASK_OUT_ABOVE_16(src) - XFLAG_AS_1(); + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = (src & res)>>8; + + res = MASK_OUT_ABOVE_16(res); + FLAG_Z |= res; + + m68ki_write_16(ea, res); +} + + +void m68k_op_negx_32_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint res = 0 - MASK_OUT_ABOVE_32(*r_dst) - XFLAG_AS_1(); + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(*r_dst, 0, res); + FLAG_V = (*r_dst & res)>>24; + + res = MASK_OUT_ABOVE_32(res); + FLAG_Z |= res; + + *r_dst = res; +} + + +void m68k_op_negx_32_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_32(); + uint src = m68ki_read_32(ea); + uint res = 0 - MASK_OUT_ABOVE_32(src) - XFLAG_AS_1(); + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, 0, res); + FLAG_V = (src & res)>>24; + + res = MASK_OUT_ABOVE_32(res); + FLAG_Z |= res; + + m68ki_write_32(ea, res); +} + + +void m68k_op_negx_32_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_32(); + uint src = m68ki_read_32(ea); + uint res = 0 - MASK_OUT_ABOVE_32(src) - XFLAG_AS_1(); + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, 0, res); + FLAG_V = (src & res)>>24; + + res = MASK_OUT_ABOVE_32(res); + FLAG_Z |= res; + + m68ki_write_32(ea, res); +} + + +void m68k_op_negx_32_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_32(); + uint src = m68ki_read_32(ea); + uint res = 0 - MASK_OUT_ABOVE_32(src) - XFLAG_AS_1(); + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, 0, res); + FLAG_V = (src & res)>>24; + + res = MASK_OUT_ABOVE_32(res); + FLAG_Z |= res; + + m68ki_write_32(ea, res); +} + + +void m68k_op_negx_32_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_32(); + uint src = m68ki_read_32(ea); + uint res = 0 - MASK_OUT_ABOVE_32(src) - XFLAG_AS_1(); + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, 0, res); + FLAG_V = (src & res)>>24; + + res = MASK_OUT_ABOVE_32(res); + FLAG_Z |= res; + + m68ki_write_32(ea, res); +} + + +void m68k_op_negx_32_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_32(); + uint src = m68ki_read_32(ea); + uint res = 0 - MASK_OUT_ABOVE_32(src) - XFLAG_AS_1(); + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, 0, res); + FLAG_V = (src & res)>>24; + + res = MASK_OUT_ABOVE_32(res); + FLAG_Z |= res; + + m68ki_write_32(ea, res); +} + + +void m68k_op_negx_32_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_32(); + uint src = m68ki_read_32(ea); + uint res = 0 - MASK_OUT_ABOVE_32(src) - XFLAG_AS_1(); + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, 0, res); + FLAG_V = (src & res)>>24; + + res = MASK_OUT_ABOVE_32(res); + FLAG_Z |= res; + + m68ki_write_32(ea, res); +} + + +void m68k_op_negx_32_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_32(); + uint src = m68ki_read_32(ea); + uint res = 0 - MASK_OUT_ABOVE_32(src) - XFLAG_AS_1(); + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, 0, res); + FLAG_V = (src & res)>>24; + + res = MASK_OUT_ABOVE_32(res); + FLAG_Z |= res; + + m68ki_write_32(ea, res); +} + + +void m68k_op_nop(m68ki_cpu_core *cpu) +{ + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ +} + + +void m68k_op_not_8_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint res = MASK_OUT_ABOVE_8(~*r_dst); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_not_8_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_8(); + uint res = MASK_OUT_ABOVE_8(~m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_not_8_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_8(); + uint res = MASK_OUT_ABOVE_8(~m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_not_8_pi7(m68ki_cpu_core *cpu) +{ + uint ea = EA_A7_PI_8(); + uint res = MASK_OUT_ABOVE_8(~m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_not_8_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_8(); + uint res = MASK_OUT_ABOVE_8(~m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_not_8_pd7(m68ki_cpu_core *cpu) +{ + uint ea = EA_A7_PD_8(); + uint res = MASK_OUT_ABOVE_8(~m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_not_8_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_8(); + uint res = MASK_OUT_ABOVE_8(~m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_not_8_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_8(); + uint res = MASK_OUT_ABOVE_8(~m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_not_8_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_8(); + uint res = MASK_OUT_ABOVE_8(~m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_not_8_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_8(); + uint res = MASK_OUT_ABOVE_8(~m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_not_16_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint res = MASK_OUT_ABOVE_16(~*r_dst); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_not_16_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_16(); + uint res = MASK_OUT_ABOVE_16(~m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_not_16_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_16(); + uint res = MASK_OUT_ABOVE_16(~m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_not_16_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_16(); + uint res = MASK_OUT_ABOVE_16(~m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_not_16_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_16(); + uint res = MASK_OUT_ABOVE_16(~m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_not_16_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_16(); + uint res = MASK_OUT_ABOVE_16(~m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_not_16_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_16(); + uint res = MASK_OUT_ABOVE_16(~m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_not_16_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_16(); + uint res = MASK_OUT_ABOVE_16(~m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_not_32_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint res = *r_dst = MASK_OUT_ABOVE_32(~*r_dst); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_not_32_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_32(); + uint res = MASK_OUT_ABOVE_32(~m68ki_read_32(ea)); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_not_32_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_32(); + uint res = MASK_OUT_ABOVE_32(~m68ki_read_32(ea)); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_not_32_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_32(); + uint res = MASK_OUT_ABOVE_32(~m68ki_read_32(ea)); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_not_32_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_32(); + uint res = MASK_OUT_ABOVE_32(~m68ki_read_32(ea)); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_not_32_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_32(); + uint res = MASK_OUT_ABOVE_32(~m68ki_read_32(ea)); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_not_32_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_32(); + uint res = MASK_OUT_ABOVE_32(~m68ki_read_32(ea)); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_not_32_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_32(); + uint res = MASK_OUT_ABOVE_32(~m68ki_read_32(ea)); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_8_er_d(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_8((DX |= MASK_OUT_ABOVE_8(DY))); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_8_er_ai(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_8((DX |= OPER_AY_AI_8(cpu))); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_8_er_pi(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_8((DX |= OPER_AY_PI_8(cpu))); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_8_er_pi7(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_8((DX |= OPER_A7_PI_8(cpu))); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_8_er_pd(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_8((DX |= OPER_AY_PD_8(cpu))); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_8_er_pd7(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_8((DX |= OPER_A7_PD_8(cpu))); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_8_er_di(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_8((DX |= OPER_AY_DI_8(cpu))); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_8_er_ix(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_8((DX |= OPER_AY_IX_8(cpu))); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_8_er_aw(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_8((DX |= OPER_AW_8(cpu))); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_8_er_al(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_8((DX |= OPER_AL_8(cpu))); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_8_er_pcdi(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_8((DX |= OPER_PCDI_8(cpu))); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_8_er_pcix(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_8((DX |= OPER_PCIX_8(cpu))); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_8_er_i(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_8((DX |= OPER_I_8())); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_16_er_d(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16((DX |= MASK_OUT_ABOVE_16(DY))); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_16_er_ai(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16((DX |= OPER_AY_AI_16(cpu))); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_16_er_pi(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16((DX |= OPER_AY_PI_16(cpu))); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_16_er_pd(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16((DX |= OPER_AY_PD_16(cpu))); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_16_er_di(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16((DX |= OPER_AY_DI_16(cpu))); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_16_er_ix(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16((DX |= OPER_AY_IX_16(cpu))); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_16_er_aw(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16((DX |= OPER_AW_16(cpu))); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_16_er_al(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16((DX |= OPER_AL_16(cpu))); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_16_er_pcdi(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16((DX |= OPER_PCDI_16(cpu))); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_16_er_pcix(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16((DX |= OPER_PCIX_16(cpu))); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_16_er_i(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16((DX |= OPER_I_16())); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_32_er_d(m68ki_cpu_core *cpu) +{ + uint res = DX |= DY; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_32_er_ai(m68ki_cpu_core *cpu) +{ + uint res = DX |= OPER_AY_AI_32(cpu); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_32_er_pi(m68ki_cpu_core *cpu) +{ + uint res = DX |= OPER_AY_PI_32(cpu); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_32_er_pd(m68ki_cpu_core *cpu) +{ + uint res = DX |= OPER_AY_PD_32(cpu); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_32_er_di(m68ki_cpu_core *cpu) +{ + uint res = DX |= OPER_AY_DI_32(cpu); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_32_er_ix(m68ki_cpu_core *cpu) +{ + uint res = DX |= OPER_AY_IX_32(cpu); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_32_er_aw(m68ki_cpu_core *cpu) +{ + uint res = DX |= OPER_AW_32(cpu); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_32_er_al(m68ki_cpu_core *cpu) +{ + uint res = DX |= OPER_AL_32(cpu); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_32_er_pcdi(m68ki_cpu_core *cpu) +{ + uint res = DX |= OPER_PCDI_32(cpu); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_32_er_pcix(m68ki_cpu_core *cpu) +{ + uint res = DX |= OPER_PCIX_32(cpu); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_32_er_i(m68ki_cpu_core *cpu) +{ + uint res = DX |= OPER_I_32(); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_8_re_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_8(); + uint res = MASK_OUT_ABOVE_8(DX | m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_8_re_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_8(); + uint res = MASK_OUT_ABOVE_8(DX | m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_8_re_pi7(m68ki_cpu_core *cpu) +{ + uint ea = EA_A7_PI_8(); + uint res = MASK_OUT_ABOVE_8(DX | m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_8_re_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_8(); + uint res = MASK_OUT_ABOVE_8(DX | m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_8_re_pd7(m68ki_cpu_core *cpu) +{ + uint ea = EA_A7_PD_8(); + uint res = MASK_OUT_ABOVE_8(DX | m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_8_re_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_8(); + uint res = MASK_OUT_ABOVE_8(DX | m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_8_re_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_8(); + uint res = MASK_OUT_ABOVE_8(DX | m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_8_re_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_8(); + uint res = MASK_OUT_ABOVE_8(DX | m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_8_re_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_8(); + uint res = MASK_OUT_ABOVE_8(DX | m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_16_re_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_16(); + uint res = MASK_OUT_ABOVE_16(DX | m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_16_re_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_16(); + uint res = MASK_OUT_ABOVE_16(DX | m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_16_re_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_16(); + uint res = MASK_OUT_ABOVE_16(DX | m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_16_re_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_16(); + uint res = MASK_OUT_ABOVE_16(DX | m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_16_re_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_16(); + uint res = MASK_OUT_ABOVE_16(DX | m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_16_re_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_16(); + uint res = MASK_OUT_ABOVE_16(DX | m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_16_re_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_16(); + uint res = MASK_OUT_ABOVE_16(DX | m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_32_re_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_32(); + uint res = DX | m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_32_re_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_32(); + uint res = DX | m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_32_re_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_32(); + uint res = DX | m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_32_re_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_32(); + uint res = DX | m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_32_re_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_32(); + uint res = DX | m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_32_re_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_32(); + uint res = DX | m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_or_32_re_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_32(); + uint res = DX | m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ori_8_d(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_8((DY |= OPER_I_8())); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ori_8_ai(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AY_AI_8(); + uint res = MASK_OUT_ABOVE_8(src | m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ori_8_pi(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AY_PI_8(); + uint res = MASK_OUT_ABOVE_8(src | m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ori_8_pi7(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_A7_PI_8(); + uint res = MASK_OUT_ABOVE_8(src | m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ori_8_pd(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AY_PD_8(); + uint res = MASK_OUT_ABOVE_8(src | m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ori_8_pd7(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_A7_PD_8(); + uint res = MASK_OUT_ABOVE_8(src | m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ori_8_di(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AY_DI_8(); + uint res = MASK_OUT_ABOVE_8(src | m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ori_8_ix(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AY_IX_8(); + uint res = MASK_OUT_ABOVE_8(src | m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ori_8_aw(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AW_8(); + uint res = MASK_OUT_ABOVE_8(src | m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ori_8_al(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AL_8(); + uint res = MASK_OUT_ABOVE_8(src | m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ori_16_d(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16(DY |= OPER_I_16()); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ori_16_ai(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AY_AI_16(); + uint res = MASK_OUT_ABOVE_16(src | m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ori_16_pi(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AY_PI_16(); + uint res = MASK_OUT_ABOVE_16(src | m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ori_16_pd(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AY_PD_16(); + uint res = MASK_OUT_ABOVE_16(src | m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ori_16_di(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AY_DI_16(); + uint res = MASK_OUT_ABOVE_16(src | m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ori_16_ix(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AY_IX_16(); + uint res = MASK_OUT_ABOVE_16(src | m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ori_16_aw(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AW_16(); + uint res = MASK_OUT_ABOVE_16(src | m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ori_16_al(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AL_16(); + uint res = MASK_OUT_ABOVE_16(src | m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ori_32_d(m68ki_cpu_core *cpu) +{ + uint res = DY |= OPER_I_32(); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ori_32_ai(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AY_AI_32(); + uint res = src | m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ori_32_pi(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AY_PI_32(); + uint res = src | m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ori_32_pd(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AY_PD_32(); + uint res = src | m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ori_32_di(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AY_DI_32(); + uint res = src | m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ori_32_ix(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AY_IX_32(); + uint res = src | m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ori_32_aw(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AW_32(); + uint res = src | m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ori_32_al(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AL_32(); + uint res = src | m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ori_16_toc(m68ki_cpu_core *cpu) +{ + m68ki_set_ccr(cpu, m68ki_get_ccr() | OPER_I_16()); +} + + +void m68k_op_ori_16_tos(m68ki_cpu_core *cpu) +{ + if(FLAG_S) + { + uint src = OPER_I_16(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_set_sr(cpu, m68ki_get_sr() | src); + return; + } + m68ki_exception_privilege_violation(cpu); +} + + +void m68k_op_pack_16_rr(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: DX and DY are reversed in Motorola's docs */ + uint src = DY + OPER_I_16(); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | ((src >> 4) & 0x00f0) | (src & 0x000f); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_pack_16_mm_ax7(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: AX and AY are reversed in Motorola's docs */ + uint ea_src = EA_AY_PD_8(); + uint src = m68ki_read_8(ea_src); + ea_src = EA_AY_PD_8(); + src = ((src << 8) | m68ki_read_8(ea_src)) + OPER_I_16(); + + m68ki_write_8(EA_A7_PD_8(), ((src >> 4) & 0x00f0) | (src & 0x000f)); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_pack_16_mm_ay7(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: AX and AY are reversed in Motorola's docs */ + uint ea_src = EA_A7_PD_8(); + uint src = m68ki_read_8(ea_src); + ea_src = EA_A7_PD_8(); + src = ((src << 8) | m68ki_read_8(ea_src)) + OPER_I_16(); + + m68ki_write_8(EA_AX_PD_8(), ((src >> 4) & 0x00f0) | (src & 0x000f)); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_pack_16_mm_axy7(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint ea_src = EA_A7_PD_8(); + uint src = m68ki_read_8(ea_src); + ea_src = EA_A7_PD_8(); + src = ((src << 8) | m68ki_read_8(ea_src)) + OPER_I_16(); + + m68ki_write_8(EA_A7_PD_8(), ((src >> 4) & 0x00f0) | (src & 0x000f)); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_pack_16_mm(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: AX and AY are reversed in Motorola's docs */ + uint ea_src = EA_AY_PD_8(); + uint src = m68ki_read_8(ea_src); + ea_src = EA_AY_PD_8(); + src = ((src << 8) | m68ki_read_8(ea_src)) + OPER_I_16(); + + m68ki_write_8(EA_AX_PD_8(), ((src >> 4) & 0x00f0) | (src & 0x000f)); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_pea_32_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_32(); + + m68ki_push_32(cpu, ea); +} + + +void m68k_op_pea_32_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_32(); + + m68ki_push_32(cpu, ea); +} + + +void m68k_op_pea_32_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_32(); + + m68ki_push_32(cpu, ea); +} + + +void m68k_op_pea_32_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_32(); + + m68ki_push_32(cpu, ea); +} + + +void m68k_op_pea_32_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_32(); + + m68ki_push_32(cpu, ea); +} + + +void m68k_op_pea_32_pcdi(m68ki_cpu_core *cpu) +{ + uint ea = EA_PCDI_32(); + + m68ki_push_32(cpu, ea); +} + + +void m68k_op_pea_32_pcix(m68ki_cpu_core *cpu) +{ + uint ea = EA_PCIX_32(); + + m68ki_push_32(cpu, ea); +} + + +void m68k_op_reset(m68ki_cpu_core *cpu) +{ + if(FLAG_S) + { + m68ki_output_reset(); /* auto-disable (see m68kcpu.h) */ + USE_CYCLES(CYC_RESET); + return; + } + m68ki_exception_privilege_violation(cpu); +} + + +void m68k_op_ror_8_s(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint orig_shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint shift = orig_shift & 7; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = ROR_8(src, shift); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = src << (9-orig_shift); + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ror_16_s(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = ROR_16(src, shift); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = src << (9-shift); + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ror_32_s(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint64 src = *r_dst; + uint res = ROR_32(src, shift); + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = src << (9-shift); + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ror_8_r(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + uint shift = orig_shift & 7; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = ROR_8(src, shift); + + if(orig_shift != 0) + { + USE_CYCLES(orig_shift<<CYC_SHIFT); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + FLAG_C = src << (8-((shift-1)&7)); + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_8(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ror_16_r(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + uint shift = orig_shift & 15; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = ROR_16(src, shift); + + if(orig_shift != 0) + { + USE_CYCLES(orig_shift<<CYC_SHIFT); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + FLAG_C = (src >> ((shift - 1) & 15)) << 8; + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_16(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ror_32_r(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + uint shift = orig_shift & 31; + uint64 src = *r_dst; + uint res = ROR_32(src, shift); + + if(orig_shift != 0) + { + USE_CYCLES(orig_shift<<CYC_SHIFT); + + *r_dst = res; + FLAG_C = (src >> ((shift - 1) & 31)) << 8; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_32(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ror_16_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_16(); + uint src = m68ki_read_16(ea); + uint res = ROR_16(src, 1); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = src << 8; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ror_16_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_16(); + uint src = m68ki_read_16(ea); + uint res = ROR_16(src, 1); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = src << 8; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ror_16_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_16(); + uint src = m68ki_read_16(ea); + uint res = ROR_16(src, 1); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = src << 8; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ror_16_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_16(); + uint src = m68ki_read_16(ea); + uint res = ROR_16(src, 1); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = src << 8; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ror_16_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_16(); + uint src = m68ki_read_16(ea); + uint res = ROR_16(src, 1); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = src << 8; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ror_16_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_16(); + uint src = m68ki_read_16(ea); + uint res = ROR_16(src, 1); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = src << 8; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_ror_16_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_16(); + uint src = m68ki_read_16(ea); + uint res = ROR_16(src, 1); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = src << 8; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_rol_8_s(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint orig_shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint shift = orig_shift & 7; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = ROL_8(src, shift); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = src << orig_shift; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_rol_16_s(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = ROL_16(src, shift); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = src >> (8-shift); + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_rol_32_s(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint64 src = *r_dst; + uint res = ROL_32(src, shift); + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = src >> (24-shift); + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_rol_8_r(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + uint shift = orig_shift & 7; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = ROL_8(src, shift); + + if(orig_shift != 0) + { + USE_CYCLES(orig_shift<<CYC_SHIFT); + + if(shift != 0) + { + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + FLAG_C = src << shift; + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + FLAG_C = (src & 1)<<8; + FLAG_N = NFLAG_8(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_8(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_rol_16_r(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + uint shift = orig_shift & 15; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = MASK_OUT_ABOVE_16(ROL_16(src, shift)); + + if(orig_shift != 0) + { + USE_CYCLES(orig_shift<<CYC_SHIFT); + + if(shift != 0) + { + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + FLAG_C = (src << shift) >> 8; + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + FLAG_C = (src & 1)<<8; + FLAG_N = NFLAG_16(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_16(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_rol_32_r(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + uint shift = orig_shift & 31; + uint64 src = *r_dst; + uint res = ROL_32(src, shift); + + if(orig_shift != 0) + { + USE_CYCLES(orig_shift<<CYC_SHIFT); + + *r_dst = res; + + FLAG_C = (src >> (32 - shift)) << 8; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_32(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_rol_16_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_16(); + uint src = m68ki_read_16(ea); + uint res = MASK_OUT_ABOVE_16(ROL_16(src, 1)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = src >> 7; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_rol_16_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_16(); + uint src = m68ki_read_16(ea); + uint res = MASK_OUT_ABOVE_16(ROL_16(src, 1)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = src >> 7; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_rol_16_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_16(); + uint src = m68ki_read_16(ea); + uint res = MASK_OUT_ABOVE_16(ROL_16(src, 1)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = src >> 7; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_rol_16_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_16(); + uint src = m68ki_read_16(ea); + uint res = MASK_OUT_ABOVE_16(ROL_16(src, 1)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = src >> 7; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_rol_16_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_16(); + uint src = m68ki_read_16(ea); + uint res = MASK_OUT_ABOVE_16(ROL_16(src, 1)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = src >> 7; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_rol_16_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_16(); + uint src = m68ki_read_16(ea); + uint res = MASK_OUT_ABOVE_16(ROL_16(src, 1)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = src >> 7; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_rol_16_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_16(); + uint src = m68ki_read_16(ea); + uint res = MASK_OUT_ABOVE_16(ROL_16(src, 1)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = src >> 7; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_roxr_8_s(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = ROR_9(src | (XFLAG_AS_1() << 8), shift); + + FLAG_C = FLAG_X = res; + res = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_roxr_16_s(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = ROR_17(src | (XFLAG_AS_1() << 16), shift); + + FLAG_C = FLAG_X = res >> 8; + res = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_roxr_32_s(m68ki_cpu_core *cpu) +{ +#if M68K_USE_64_BIT + + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint64 src = *r_dst; + uint64 res = src | (((uint64)XFLAG_AS_1()) << 32); + + res = ROR_33_64(res, shift); + + FLAG_C = FLAG_X = res >> 24; + res = MASK_OUT_ABOVE_32(res); + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + +#else + + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32((ROR_33(src, shift) & ~(1 << (32 - shift))) | (XFLAG_AS_1() << (32 - shift))); + uint new_x_flag = src & (1 << (shift - 1)); + + *r_dst = res; + + FLAG_C = FLAG_X = (new_x_flag != 0)<<8; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + +#endif +} + + +void m68k_op_roxr_8_r(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + + if(orig_shift != 0) + { + uint shift = orig_shift % 9; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = ROR_9(src | (XFLAG_AS_1() << 8), shift); + + USE_CYCLES(orig_shift<<CYC_SHIFT); + + FLAG_C = FLAG_X = res; + res = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = FLAG_X; + FLAG_N = NFLAG_8(*r_dst); + FLAG_Z = MASK_OUT_ABOVE_8(*r_dst); + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_roxr_16_r(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + + if(orig_shift != 0) + { + uint shift = orig_shift % 17; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = ROR_17(src | (XFLAG_AS_1() << 16), shift); + + USE_CYCLES(orig_shift<<CYC_SHIFT); + + FLAG_C = FLAG_X = res >> 8; + res = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = FLAG_X; + FLAG_N = NFLAG_16(*r_dst); + FLAG_Z = MASK_OUT_ABOVE_16(*r_dst); + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_roxr_32_r(m68ki_cpu_core *cpu) +{ +#if M68K_USE_64_BIT + + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + + if(orig_shift != 0) + { + uint shift = orig_shift % 33; + uint64 src = *r_dst; + uint64 res = src | (((uint64)XFLAG_AS_1()) << 32); + + res = ROR_33_64(res, shift); + + USE_CYCLES(orig_shift<<CYC_SHIFT); + + FLAG_C = FLAG_X = res >> 24; + res = MASK_OUT_ABOVE_32(res); + + *r_dst = res; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = FLAG_X; + FLAG_N = NFLAG_32(*r_dst); + FLAG_Z = *r_dst; + FLAG_V = VFLAG_CLEAR; + +#else + + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + uint shift = orig_shift % 33; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32((ROR_33(src, shift) & ~(1 << (32 - shift))) | (XFLAG_AS_1() << (32 - shift))); + uint new_x_flag = src & (1 << (shift - 1)); + + if(orig_shift != 0) + USE_CYCLES(orig_shift<<CYC_SHIFT); + + if(shift != 0) + { + *r_dst = res; + FLAG_X = (new_x_flag != 0)<<8; + } + else + res = src; + FLAG_C = FLAG_X; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + +#endif +} + + +void m68k_op_roxr_16_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_16(); + uint src = m68ki_read_16(ea); + uint res = ROR_17(src | (XFLAG_AS_1() << 16), 1); + + FLAG_C = FLAG_X = res >> 8; + res = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_roxr_16_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_16(); + uint src = m68ki_read_16(ea); + uint res = ROR_17(src | (XFLAG_AS_1() << 16), 1); + + FLAG_C = FLAG_X = res >> 8; + res = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_roxr_16_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_16(); + uint src = m68ki_read_16(ea); + uint res = ROR_17(src | (XFLAG_AS_1() << 16), 1); + + FLAG_C = FLAG_X = res >> 8; + res = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_roxr_16_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_16(); + uint src = m68ki_read_16(ea); + uint res = ROR_17(src | (XFLAG_AS_1() << 16), 1); + + FLAG_C = FLAG_X = res >> 8; + res = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_roxr_16_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_16(); + uint src = m68ki_read_16(ea); + uint res = ROR_17(src | (XFLAG_AS_1() << 16), 1); + + FLAG_C = FLAG_X = res >> 8; + res = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_roxr_16_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_16(); + uint src = m68ki_read_16(ea); + uint res = ROR_17(src | (XFLAG_AS_1() << 16), 1); + + FLAG_C = FLAG_X = res >> 8; + res = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_roxr_16_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_16(); + uint src = m68ki_read_16(ea); + uint res = ROR_17(src | (XFLAG_AS_1() << 16), 1); + + FLAG_C = FLAG_X = res >> 8; + res = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_roxl_8_s(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = ROL_9(src | (XFLAG_AS_1() << 8), shift); + + FLAG_C = FLAG_X = res; + res = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_roxl_16_s(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = ROL_17(src | (XFLAG_AS_1() << 16), shift); + + FLAG_C = FLAG_X = res >> 8; + res = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_roxl_32_s(m68ki_cpu_core *cpu) +{ +#if M68K_USE_64_BIT + + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint64 src = *r_dst; + uint64 res = src | (((uint64)XFLAG_AS_1()) << 32); + + res = ROL_33_64(res, shift); + + FLAG_C = FLAG_X = res >> 24; + res = MASK_OUT_ABOVE_32(res); + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + +#else + + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32((ROL_33(src, shift) & ~(1 << (shift - 1))) | (XFLAG_AS_1() << (shift - 1))); + uint new_x_flag = src & (1 << (32 - shift)); + + *r_dst = res; + + FLAG_C = FLAG_X = (new_x_flag != 0)<<8; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + +#endif +} + + +void m68k_op_roxl_8_r(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + + + if(orig_shift != 0) + { + uint shift = orig_shift % 9; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = ROL_9(src | (XFLAG_AS_1() << 8), shift); + + USE_CYCLES(orig_shift<<CYC_SHIFT); + + FLAG_C = FLAG_X = res; + res = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = FLAG_X; + FLAG_N = NFLAG_8(*r_dst); + FLAG_Z = MASK_OUT_ABOVE_8(*r_dst); + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_roxl_16_r(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + + if(orig_shift != 0) + { + uint shift = orig_shift % 17; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = ROL_17(src | (XFLAG_AS_1() << 16), shift); + + USE_CYCLES(orig_shift<<CYC_SHIFT); + + FLAG_C = FLAG_X = res >> 8; + res = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = FLAG_X; + FLAG_N = NFLAG_16(*r_dst); + FLAG_Z = MASK_OUT_ABOVE_16(*r_dst); + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_roxl_32_r(m68ki_cpu_core *cpu) +{ +#if M68K_USE_64_BIT + + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + + if(orig_shift != 0) + { + uint shift = orig_shift % 33; + uint64 src = *r_dst; + uint64 res = src | (((uint64)XFLAG_AS_1()) << 32); + + res = ROL_33_64(res, shift); + + USE_CYCLES(orig_shift<<CYC_SHIFT); + + FLAG_C = FLAG_X = res >> 24; + res = MASK_OUT_ABOVE_32(res); + + *r_dst = res; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = FLAG_X; + FLAG_N = NFLAG_32(*r_dst); + FLAG_Z = *r_dst; + FLAG_V = VFLAG_CLEAR; + +#else + + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + uint shift = orig_shift % 33; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32((ROL_33(src, shift) & ~(1 << (shift - 1))) | (XFLAG_AS_1() << (shift - 1))); + uint new_x_flag = src & (1 << (32 - shift)); + + if(orig_shift != 0) + USE_CYCLES(orig_shift<<CYC_SHIFT); + + if(shift != 0) + { + *r_dst = res; + FLAG_X = (new_x_flag != 0)<<8; + } + else + res = src; + FLAG_C = FLAG_X; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + +#endif +} + + +void m68k_op_roxl_16_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_16(); + uint src = m68ki_read_16(ea); + uint res = ROL_17(src | (XFLAG_AS_1() << 16), 1); + + FLAG_C = FLAG_X = res >> 8; + res = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_roxl_16_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_16(); + uint src = m68ki_read_16(ea); + uint res = ROL_17(src | (XFLAG_AS_1() << 16), 1); + + FLAG_C = FLAG_X = res >> 8; + res = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_roxl_16_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_16(); + uint src = m68ki_read_16(ea); + uint res = ROL_17(src | (XFLAG_AS_1() << 16), 1); + + FLAG_C = FLAG_X = res >> 8; + res = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_roxl_16_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_16(); + uint src = m68ki_read_16(ea); + uint res = ROL_17(src | (XFLAG_AS_1() << 16), 1); + + FLAG_C = FLAG_X = res >> 8; + res = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_roxl_16_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_16(); + uint src = m68ki_read_16(ea); + uint res = ROL_17(src | (XFLAG_AS_1() << 16), 1); + + FLAG_C = FLAG_X = res >> 8; + res = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_roxl_16_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_16(); + uint src = m68ki_read_16(ea); + uint res = ROL_17(src | (XFLAG_AS_1() << 16), 1); + + FLAG_C = FLAG_X = res >> 8; + res = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_roxl_16_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_16(); + uint src = m68ki_read_16(ea); + uint res = ROL_17(src | (XFLAG_AS_1() << 16), 1); + + FLAG_C = FLAG_X = res >> 8; + res = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_rtd_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + uint new_pc = m68ki_pull_32(cpu); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + MAKE_INT_16(OPER_I_16())); + m68ki_jump(cpu, new_pc); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_rte_32(m68ki_cpu_core *cpu) +{ + if(FLAG_S) + { + uint new_sr; + uint new_pc; + uint format_word; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + + if(CPU_TYPE_IS_000(CPU_TYPE)) + { + new_sr = m68ki_pull_16(cpu); + new_pc = m68ki_pull_32(cpu); + m68ki_jump(cpu, new_pc); + m68ki_set_sr(cpu, new_sr); + + CPU_INSTR_MODE = INSTRUCTION_YES; + CPU_RUN_MODE = RUN_MODE_NORMAL; + + return; + } + + if(CPU_TYPE_IS_010(CPU_TYPE)) + { + format_word = m68ki_read_16(REG_A[7]+6) >> 12; + if(format_word == 0) + { + new_sr = m68ki_pull_16(cpu); + new_pc = m68ki_pull_32(cpu); + m68ki_fake_pull_16(cpu); /* format word */ + m68ki_jump(cpu, new_pc); + m68ki_set_sr(cpu, new_sr); + CPU_INSTR_MODE = INSTRUCTION_YES; + CPU_RUN_MODE = RUN_MODE_NORMAL; + return; + } + CPU_INSTR_MODE = INSTRUCTION_YES; + CPU_RUN_MODE = RUN_MODE_NORMAL; + /* Not handling bus fault (9) */ + m68ki_exception_format_error(cpu); + return; + } + + /* Otherwise it's 020 */ +rte_loop: + format_word = m68ki_read_16(REG_A[7]+6) >> 12; + switch(format_word) + { + case 0: /* Normal */ + new_sr = m68ki_pull_16(cpu); + new_pc = m68ki_pull_32(cpu); + m68ki_fake_pull_16(cpu); /* format word */ + m68ki_jump(cpu, new_pc); + m68ki_set_sr(cpu, new_sr); + CPU_INSTR_MODE = INSTRUCTION_YES; + CPU_RUN_MODE = RUN_MODE_NORMAL; + return; + case 1: /* Throwaway */ + new_sr = m68ki_pull_16(cpu); + m68ki_fake_pull_32(cpu); /* program counter */ + m68ki_fake_pull_16(cpu); /* format word */ + m68ki_set_sr_noint(cpu, new_sr); + goto rte_loop; + case 2: /* Trap */ + new_sr = m68ki_pull_16(cpu); + new_pc = m68ki_pull_32(cpu); + m68ki_fake_pull_16(cpu); /* format word */ + m68ki_fake_pull_32(cpu); /* address */ + m68ki_jump(cpu, new_pc); + m68ki_set_sr(cpu, new_sr); + CPU_INSTR_MODE = INSTRUCTION_YES; + CPU_RUN_MODE = RUN_MODE_NORMAL; + return; + } + /* Not handling long or short bus fault */ + CPU_INSTR_MODE = INSTRUCTION_YES; + CPU_RUN_MODE = RUN_MODE_NORMAL; + m68ki_exception_format_error(cpu); + return; + } + m68ki_exception_privilege_violation(cpu); +} + + +void m68k_op_rtm_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_rtr_32(m68ki_cpu_core *cpu) +{ + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_set_ccr(cpu, m68ki_pull_16(cpu)); + m68ki_jump(cpu, m68ki_pull_32(cpu)); +} + + +void m68k_op_rts_32(m68ki_cpu_core *cpu) +{ + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_jump(cpu, m68ki_pull_32(cpu)); +} + + +void m68k_op_sbcd_8_rr(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = DY; + uint dst = *r_dst; + uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res -= 6; + res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res += 0xa0; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; +} + + +void m68k_op_sbcd_8_mm_ax7(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_PD_8(cpu); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res -= 6; + res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res += 0xa0; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +void m68k_op_sbcd_8_mm_ay7(m68ki_cpu_core *cpu) +{ + uint src = OPER_A7_PD_8(cpu); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res -= 6; + res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res += 0xa0; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +void m68k_op_sbcd_8_mm_axy7(m68ki_cpu_core *cpu) +{ + uint src = OPER_A7_PD_8(cpu); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res -= 6; + res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res += 0xa0; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +void m68k_op_sbcd_8_mm(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_PD_8(cpu); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res -= 6; + res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res += 0xa0; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +void m68k_op_st_8_d(m68ki_cpu_core *cpu) +{ + DY |= 0xff; +} + + +void m68k_op_st_8_ai(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_AI_8(), 0xff); +} + + +void m68k_op_st_8_pi(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PI_8(), 0xff); +} + + +void m68k_op_st_8_pi7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PI_8(), 0xff); +} + + +void m68k_op_st_8_pd(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PD_8(), 0xff); +} + + +void m68k_op_st_8_pd7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PD_8(), 0xff); +} + + +void m68k_op_st_8_di(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_DI_8(), 0xff); +} + + +void m68k_op_st_8_ix(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_IX_8(), 0xff); +} + + +void m68k_op_st_8_aw(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AW_8(), 0xff); +} + + +void m68k_op_st_8_al(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AL_8(), 0xff); +} + + +void m68k_op_sf_8_d(m68ki_cpu_core *cpu) +{ + DY &= 0xffffff00; +} + + +void m68k_op_sf_8_ai(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_AI_8(), 0); +} + + +void m68k_op_sf_8_pi(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PI_8(), 0); +} + + +void m68k_op_sf_8_pi7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PI_8(), 0); +} + + +void m68k_op_sf_8_pd(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PD_8(), 0); +} + + +void m68k_op_sf_8_pd7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PD_8(), 0); +} + + +void m68k_op_sf_8_di(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_DI_8(), 0); +} + + +void m68k_op_sf_8_ix(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_IX_8(), 0); +} + + +void m68k_op_sf_8_aw(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AW_8(), 0); +} + + +void m68k_op_sf_8_al(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AL_8(), 0); +} + + +void m68k_op_shi_8_d(m68ki_cpu_core *cpu) +{ + if(COND_HI()) + { + DY |= 0xff; + return; + } + DY &= 0xffffff00; +} + + +void m68k_op_sls_8_d(m68ki_cpu_core *cpu) +{ + if(COND_LS()) + { + DY |= 0xff; + return; + } + DY &= 0xffffff00; +} + + +void m68k_op_scc_8_d(m68ki_cpu_core *cpu) +{ + if(COND_CC()) + { + DY |= 0xff; + return; + } + DY &= 0xffffff00; +} + + +void m68k_op_scs_8_d(m68ki_cpu_core *cpu) +{ + if(COND_CS()) + { + DY |= 0xff; + return; + } + DY &= 0xffffff00; +} + + +void m68k_op_sne_8_d(m68ki_cpu_core *cpu) +{ + if(COND_NE()) + { + DY |= 0xff; + return; + } + DY &= 0xffffff00; +} + + +void m68k_op_seq_8_d(m68ki_cpu_core *cpu) +{ + if(COND_EQ()) + { + DY |= 0xff; + return; + } + DY &= 0xffffff00; +} + + +void m68k_op_svc_8_d(m68ki_cpu_core *cpu) +{ + if(COND_VC()) + { + DY |= 0xff; + return; + } + DY &= 0xffffff00; +} + + +void m68k_op_svs_8_d(m68ki_cpu_core *cpu) +{ + if(COND_VS()) + { + DY |= 0xff; + return; + } + DY &= 0xffffff00; +} + + +void m68k_op_spl_8_d(m68ki_cpu_core *cpu) +{ + if(COND_PL()) + { + DY |= 0xff; + return; + } + DY &= 0xffffff00; +} + + +void m68k_op_smi_8_d(m68ki_cpu_core *cpu) +{ + if(COND_MI()) + { + DY |= 0xff; + return; + } + DY &= 0xffffff00; +} + + +void m68k_op_sge_8_d(m68ki_cpu_core *cpu) +{ + if(COND_GE()) + { + DY |= 0xff; + return; + } + DY &= 0xffffff00; +} + + +void m68k_op_slt_8_d(m68ki_cpu_core *cpu) +{ + if(COND_LT()) + { + DY |= 0xff; + return; + } + DY &= 0xffffff00; +} + + +void m68k_op_sgt_8_d(m68ki_cpu_core *cpu) +{ + if(COND_GT()) + { + DY |= 0xff; + return; + } + DY &= 0xffffff00; +} + + +void m68k_op_sle_8_d(m68ki_cpu_core *cpu) +{ + if(COND_LE()) + { + DY |= 0xff; + return; + } + DY &= 0xffffff00; +} + + +void m68k_op_shi_8_ai(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_AI_8(), COND_HI() ? 0xff : 0); +} + + +void m68k_op_shi_8_pi(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PI_8(), COND_HI() ? 0xff : 0); +} + + +void m68k_op_shi_8_pi7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PI_8(), COND_HI() ? 0xff : 0); +} + + +void m68k_op_shi_8_pd(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PD_8(), COND_HI() ? 0xff : 0); +} + + +void m68k_op_shi_8_pd7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PD_8(), COND_HI() ? 0xff : 0); +} + + +void m68k_op_shi_8_di(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_DI_8(), COND_HI() ? 0xff : 0); +} + + +void m68k_op_shi_8_ix(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_IX_8(), COND_HI() ? 0xff : 0); +} + + +void m68k_op_shi_8_aw(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AW_8(), COND_HI() ? 0xff : 0); +} + + +void m68k_op_shi_8_al(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AL_8(), COND_HI() ? 0xff : 0); +} + + +void m68k_op_sls_8_ai(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_AI_8(), COND_LS() ? 0xff : 0); +} + + +void m68k_op_sls_8_pi(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PI_8(), COND_LS() ? 0xff : 0); +} + + +void m68k_op_sls_8_pi7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PI_8(), COND_LS() ? 0xff : 0); +} + + +void m68k_op_sls_8_pd(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PD_8(), COND_LS() ? 0xff : 0); +} + + +void m68k_op_sls_8_pd7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PD_8(), COND_LS() ? 0xff : 0); +} + + +void m68k_op_sls_8_di(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_DI_8(), COND_LS() ? 0xff : 0); +} + + +void m68k_op_sls_8_ix(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_IX_8(), COND_LS() ? 0xff : 0); +} + + +void m68k_op_sls_8_aw(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AW_8(), COND_LS() ? 0xff : 0); +} + + +void m68k_op_sls_8_al(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AL_8(), COND_LS() ? 0xff : 0); +} + + +void m68k_op_scc_8_ai(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_AI_8(), COND_CC() ? 0xff : 0); +} + + +void m68k_op_scc_8_pi(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PI_8(), COND_CC() ? 0xff : 0); +} + + +void m68k_op_scc_8_pi7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PI_8(), COND_CC() ? 0xff : 0); +} + + +void m68k_op_scc_8_pd(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PD_8(), COND_CC() ? 0xff : 0); +} + + +void m68k_op_scc_8_pd7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PD_8(), COND_CC() ? 0xff : 0); +} + + +void m68k_op_scc_8_di(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_DI_8(), COND_CC() ? 0xff : 0); +} + + +void m68k_op_scc_8_ix(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_IX_8(), COND_CC() ? 0xff : 0); +} + + +void m68k_op_scc_8_aw(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AW_8(), COND_CC() ? 0xff : 0); +} + + +void m68k_op_scc_8_al(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AL_8(), COND_CC() ? 0xff : 0); +} + + +void m68k_op_scs_8_ai(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_AI_8(), COND_CS() ? 0xff : 0); +} + + +void m68k_op_scs_8_pi(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PI_8(), COND_CS() ? 0xff : 0); +} + + +void m68k_op_scs_8_pi7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PI_8(), COND_CS() ? 0xff : 0); +} + + +void m68k_op_scs_8_pd(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PD_8(), COND_CS() ? 0xff : 0); +} + + +void m68k_op_scs_8_pd7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PD_8(), COND_CS() ? 0xff : 0); +} + + +void m68k_op_scs_8_di(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_DI_8(), COND_CS() ? 0xff : 0); +} + + +void m68k_op_scs_8_ix(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_IX_8(), COND_CS() ? 0xff : 0); +} + + +void m68k_op_scs_8_aw(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AW_8(), COND_CS() ? 0xff : 0); +} + + +void m68k_op_scs_8_al(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AL_8(), COND_CS() ? 0xff : 0); +} + + +void m68k_op_sne_8_ai(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_AI_8(), COND_NE() ? 0xff : 0); +} + + +void m68k_op_sne_8_pi(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PI_8(), COND_NE() ? 0xff : 0); +} + + +void m68k_op_sne_8_pi7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PI_8(), COND_NE() ? 0xff : 0); +} + + +void m68k_op_sne_8_pd(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PD_8(), COND_NE() ? 0xff : 0); +} + + +void m68k_op_sne_8_pd7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PD_8(), COND_NE() ? 0xff : 0); +} + + +void m68k_op_sne_8_di(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_DI_8(), COND_NE() ? 0xff : 0); +} + + +void m68k_op_sne_8_ix(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_IX_8(), COND_NE() ? 0xff : 0); +} + + +void m68k_op_sne_8_aw(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AW_8(), COND_NE() ? 0xff : 0); +} + + +void m68k_op_sne_8_al(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AL_8(), COND_NE() ? 0xff : 0); +} + + +void m68k_op_seq_8_ai(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_AI_8(), COND_EQ() ? 0xff : 0); +} + + +void m68k_op_seq_8_pi(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PI_8(), COND_EQ() ? 0xff : 0); +} + + +void m68k_op_seq_8_pi7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PI_8(), COND_EQ() ? 0xff : 0); +} + + +void m68k_op_seq_8_pd(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PD_8(), COND_EQ() ? 0xff : 0); +} + + +void m68k_op_seq_8_pd7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PD_8(), COND_EQ() ? 0xff : 0); +} + + +void m68k_op_seq_8_di(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_DI_8(), COND_EQ() ? 0xff : 0); +} + + +void m68k_op_seq_8_ix(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_IX_8(), COND_EQ() ? 0xff : 0); +} + + +void m68k_op_seq_8_aw(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AW_8(), COND_EQ() ? 0xff : 0); +} + + +void m68k_op_seq_8_al(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AL_8(), COND_EQ() ? 0xff : 0); +} + + +void m68k_op_svc_8_ai(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_AI_8(), COND_VC() ? 0xff : 0); +} + + +void m68k_op_svc_8_pi(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PI_8(), COND_VC() ? 0xff : 0); +} + + +void m68k_op_svc_8_pi7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PI_8(), COND_VC() ? 0xff : 0); +} + + +void m68k_op_svc_8_pd(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PD_8(), COND_VC() ? 0xff : 0); +} + + +void m68k_op_svc_8_pd7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PD_8(), COND_VC() ? 0xff : 0); +} + + +void m68k_op_svc_8_di(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_DI_8(), COND_VC() ? 0xff : 0); +} + + +void m68k_op_svc_8_ix(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_IX_8(), COND_VC() ? 0xff : 0); +} + + +void m68k_op_svc_8_aw(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AW_8(), COND_VC() ? 0xff : 0); +} + + +void m68k_op_svc_8_al(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AL_8(), COND_VC() ? 0xff : 0); +} + + +void m68k_op_svs_8_ai(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_AI_8(), COND_VS() ? 0xff : 0); +} + + +void m68k_op_svs_8_pi(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PI_8(), COND_VS() ? 0xff : 0); +} + + +void m68k_op_svs_8_pi7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PI_8(), COND_VS() ? 0xff : 0); +} + + +void m68k_op_svs_8_pd(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PD_8(), COND_VS() ? 0xff : 0); +} + + +void m68k_op_svs_8_pd7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PD_8(), COND_VS() ? 0xff : 0); +} + + +void m68k_op_svs_8_di(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_DI_8(), COND_VS() ? 0xff : 0); +} + + +void m68k_op_svs_8_ix(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_IX_8(), COND_VS() ? 0xff : 0); +} + + +void m68k_op_svs_8_aw(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AW_8(), COND_VS() ? 0xff : 0); +} + + +void m68k_op_svs_8_al(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AL_8(), COND_VS() ? 0xff : 0); +} + + +void m68k_op_spl_8_ai(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_AI_8(), COND_PL() ? 0xff : 0); +} + + +void m68k_op_spl_8_pi(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PI_8(), COND_PL() ? 0xff : 0); +} + + +void m68k_op_spl_8_pi7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PI_8(), COND_PL() ? 0xff : 0); +} + + +void m68k_op_spl_8_pd(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PD_8(), COND_PL() ? 0xff : 0); +} + + +void m68k_op_spl_8_pd7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PD_8(), COND_PL() ? 0xff : 0); +} + + +void m68k_op_spl_8_di(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_DI_8(), COND_PL() ? 0xff : 0); +} + + +void m68k_op_spl_8_ix(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_IX_8(), COND_PL() ? 0xff : 0); +} + + +void m68k_op_spl_8_aw(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AW_8(), COND_PL() ? 0xff : 0); +} + + +void m68k_op_spl_8_al(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AL_8(), COND_PL() ? 0xff : 0); +} + + +void m68k_op_smi_8_ai(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_AI_8(), COND_MI() ? 0xff : 0); +} + + +void m68k_op_smi_8_pi(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PI_8(), COND_MI() ? 0xff : 0); +} + + +void m68k_op_smi_8_pi7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PI_8(), COND_MI() ? 0xff : 0); +} + + +void m68k_op_smi_8_pd(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PD_8(), COND_MI() ? 0xff : 0); +} + + +void m68k_op_smi_8_pd7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PD_8(), COND_MI() ? 0xff : 0); +} + + +void m68k_op_smi_8_di(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_DI_8(), COND_MI() ? 0xff : 0); +} + + +void m68k_op_smi_8_ix(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_IX_8(), COND_MI() ? 0xff : 0); +} + + +void m68k_op_smi_8_aw(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AW_8(), COND_MI() ? 0xff : 0); +} + + +void m68k_op_smi_8_al(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AL_8(), COND_MI() ? 0xff : 0); +} + + +void m68k_op_sge_8_ai(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_AI_8(), COND_GE() ? 0xff : 0); +} + + +void m68k_op_sge_8_pi(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PI_8(), COND_GE() ? 0xff : 0); +} + + +void m68k_op_sge_8_pi7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PI_8(), COND_GE() ? 0xff : 0); +} + + +void m68k_op_sge_8_pd(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PD_8(), COND_GE() ? 0xff : 0); +} + + +void m68k_op_sge_8_pd7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PD_8(), COND_GE() ? 0xff : 0); +} + + +void m68k_op_sge_8_di(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_DI_8(), COND_GE() ? 0xff : 0); +} + + +void m68k_op_sge_8_ix(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_IX_8(), COND_GE() ? 0xff : 0); +} + + +void m68k_op_sge_8_aw(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AW_8(), COND_GE() ? 0xff : 0); +} + + +void m68k_op_sge_8_al(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AL_8(), COND_GE() ? 0xff : 0); +} + + +void m68k_op_slt_8_ai(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_AI_8(), COND_LT() ? 0xff : 0); +} + + +void m68k_op_slt_8_pi(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PI_8(), COND_LT() ? 0xff : 0); +} + + +void m68k_op_slt_8_pi7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PI_8(), COND_LT() ? 0xff : 0); +} + + +void m68k_op_slt_8_pd(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PD_8(), COND_LT() ? 0xff : 0); +} + + +void m68k_op_slt_8_pd7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PD_8(), COND_LT() ? 0xff : 0); +} + + +void m68k_op_slt_8_di(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_DI_8(), COND_LT() ? 0xff : 0); +} + + +void m68k_op_slt_8_ix(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_IX_8(), COND_LT() ? 0xff : 0); +} + + +void m68k_op_slt_8_aw(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AW_8(), COND_LT() ? 0xff : 0); +} + + +void m68k_op_slt_8_al(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AL_8(), COND_LT() ? 0xff : 0); +} + + +void m68k_op_sgt_8_ai(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_AI_8(), COND_GT() ? 0xff : 0); +} + + +void m68k_op_sgt_8_pi(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PI_8(), COND_GT() ? 0xff : 0); +} + + +void m68k_op_sgt_8_pi7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PI_8(), COND_GT() ? 0xff : 0); +} + + +void m68k_op_sgt_8_pd(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PD_8(), COND_GT() ? 0xff : 0); +} + + +void m68k_op_sgt_8_pd7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PD_8(), COND_GT() ? 0xff : 0); +} + + +void m68k_op_sgt_8_di(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_DI_8(), COND_GT() ? 0xff : 0); +} + + +void m68k_op_sgt_8_ix(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_IX_8(), COND_GT() ? 0xff : 0); +} + + +void m68k_op_sgt_8_aw(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AW_8(), COND_GT() ? 0xff : 0); +} + + +void m68k_op_sgt_8_al(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AL_8(), COND_GT() ? 0xff : 0); +} + + +void m68k_op_sle_8_ai(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_AI_8(), COND_LE() ? 0xff : 0); +} + + +void m68k_op_sle_8_pi(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PI_8(), COND_LE() ? 0xff : 0); +} + + +void m68k_op_sle_8_pi7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PI_8(), COND_LE() ? 0xff : 0); +} + + +void m68k_op_sle_8_pd(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_PD_8(), COND_LE() ? 0xff : 0); +} + + +void m68k_op_sle_8_pd7(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_A7_PD_8(), COND_LE() ? 0xff : 0); +} + + +void m68k_op_sle_8_di(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_DI_8(), COND_LE() ? 0xff : 0); +} + + +void m68k_op_sle_8_ix(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AY_IX_8(), COND_LE() ? 0xff : 0); +} + + +void m68k_op_sle_8_aw(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AW_8(), COND_LE() ? 0xff : 0); +} + + +void m68k_op_sle_8_al(m68ki_cpu_core *cpu) +{ + m68ki_write_8(EA_AL_8(), COND_LE() ? 0xff : 0); +} + + +void m68k_op_stop(m68ki_cpu_core *cpu) +{ + if(FLAG_S) + { + uint new_sr = OPER_I_16(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + CPU_STOPPED |= STOP_LEVEL_STOP; + m68ki_set_sr(cpu, new_sr); + cpu->m68ki_remaining_cycles = 0; + return; + } + m68ki_exception_privilege_violation(cpu); +} + + +void m68k_op_sub_8_er_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_8(DY); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_sub_8_er_ai(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_AI_8(cpu); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_sub_8_er_pi(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_PI_8(cpu); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_sub_8_er_pi7(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_A7_PI_8(cpu); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_sub_8_er_pd(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_PD_8(cpu); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_sub_8_er_pd7(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_A7_PD_8(cpu); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_sub_8_er_di(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_DI_8(cpu); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_sub_8_er_ix(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_IX_8(cpu); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_sub_8_er_aw(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AW_8(cpu); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_sub_8_er_al(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AL_8(cpu); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_sub_8_er_pcdi(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_PCDI_8(cpu); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_sub_8_er_pcix(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_PCIX_8(cpu); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_sub_8_er_i(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_I_8(); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_sub_16_er_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_16(DY); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +void m68k_op_sub_16_er_a(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_16(AY); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +void m68k_op_sub_16_er_ai(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_AI_16(cpu); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +void m68k_op_sub_16_er_pi(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_PI_16(cpu); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +void m68k_op_sub_16_er_pd(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_PD_16(cpu); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +void m68k_op_sub_16_er_di(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_DI_16(cpu); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +void m68k_op_sub_16_er_ix(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_IX_16(cpu); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +void m68k_op_sub_16_er_aw(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AW_16(cpu); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +void m68k_op_sub_16_er_al(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AL_16(cpu); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +void m68k_op_sub_16_er_pcdi(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_PCDI_16(cpu); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +void m68k_op_sub_16_er_pcix(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_PCIX_16(cpu); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +void m68k_op_sub_16_er_i(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_I_16(); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +void m68k_op_sub_32_er_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = DY; + uint dst = *r_dst; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +void m68k_op_sub_32_er_a(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = AY; + uint dst = *r_dst; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +void m68k_op_sub_32_er_ai(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_AI_32(cpu); + uint dst = *r_dst; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +void m68k_op_sub_32_er_pi(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_PI_32(cpu); + uint dst = *r_dst; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +void m68k_op_sub_32_er_pd(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_PD_32(cpu); + uint dst = *r_dst; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +void m68k_op_sub_32_er_di(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_DI_32(cpu); + uint dst = *r_dst; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +void m68k_op_sub_32_er_ix(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AY_IX_32(cpu); + uint dst = *r_dst; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +void m68k_op_sub_32_er_aw(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AW_32(cpu); + uint dst = *r_dst; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +void m68k_op_sub_32_er_al(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_AL_32(cpu); + uint dst = *r_dst; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +void m68k_op_sub_32_er_pcdi(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_PCDI_32(cpu); + uint dst = *r_dst; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +void m68k_op_sub_32_er_pcix(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_PCIX_32(cpu); + uint dst = *r_dst; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +void m68k_op_sub_32_er_i(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = OPER_I_32(); + uint dst = *r_dst; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +void m68k_op_sub_8_re_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_8(); + uint src = MASK_OUT_ABOVE_8(DX); + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_sub_8_re_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_8(); + uint src = MASK_OUT_ABOVE_8(DX); + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_sub_8_re_pi7(m68ki_cpu_core *cpu) +{ + uint ea = EA_A7_PI_8(); + uint src = MASK_OUT_ABOVE_8(DX); + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_sub_8_re_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_8(); + uint src = MASK_OUT_ABOVE_8(DX); + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_sub_8_re_pd7(m68ki_cpu_core *cpu) +{ + uint ea = EA_A7_PD_8(); + uint src = MASK_OUT_ABOVE_8(DX); + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_sub_8_re_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_8(); + uint src = MASK_OUT_ABOVE_8(DX); + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_sub_8_re_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_8(); + uint src = MASK_OUT_ABOVE_8(DX); + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_sub_8_re_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_8(); + uint src = MASK_OUT_ABOVE_8(DX); + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_sub_8_re_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_8(); + uint src = MASK_OUT_ABOVE_8(DX); + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_sub_16_re_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_16(); + uint src = MASK_OUT_ABOVE_16(DX); + uint dst = m68ki_read_16(ea); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_sub_16_re_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_16(); + uint src = MASK_OUT_ABOVE_16(DX); + uint dst = m68ki_read_16(ea); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_sub_16_re_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_16(); + uint src = MASK_OUT_ABOVE_16(DX); + uint dst = m68ki_read_16(ea); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_sub_16_re_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_16(); + uint src = MASK_OUT_ABOVE_16(DX); + uint dst = m68ki_read_16(ea); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_sub_16_re_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_16(); + uint src = MASK_OUT_ABOVE_16(DX); + uint dst = m68ki_read_16(ea); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_sub_16_re_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_16(); + uint src = MASK_OUT_ABOVE_16(DX); + uint dst = m68ki_read_16(ea); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_sub_16_re_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_16(); + uint src = MASK_OUT_ABOVE_16(DX); + uint dst = m68ki_read_16(ea); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_sub_32_re_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_32(); + uint src = DX; + uint dst = m68ki_read_32(ea); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_sub_32_re_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_32(); + uint src = DX; + uint dst = m68ki_read_32(ea); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_sub_32_re_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_32(); + uint src = DX; + uint dst = m68ki_read_32(ea); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_sub_32_re_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_32(); + uint src = DX; + uint dst = m68ki_read_32(ea); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_sub_32_re_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_32(); + uint src = DX; + uint dst = m68ki_read_32(ea); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_sub_32_re_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_32(); + uint src = DX; + uint dst = m68ki_read_32(ea); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_sub_32_re_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_32(); + uint src = DX; + uint dst = m68ki_read_32(ea); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_suba_16_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - MAKE_INT_16(DY)); +} + + +void m68k_op_suba_16_a(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - MAKE_INT_16(AY)); +} + + +void m68k_op_suba_16_ai(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - MAKE_INT_16(OPER_AY_AI_16(cpu))); +} + + +void m68k_op_suba_16_pi(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - MAKE_INT_16(OPER_AY_PI_16(cpu))); +} + + +void m68k_op_suba_16_pd(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - MAKE_INT_16(OPER_AY_PD_16(cpu))); +} + + +void m68k_op_suba_16_di(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - MAKE_INT_16(OPER_AY_DI_16(cpu))); +} + + +void m68k_op_suba_16_ix(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - MAKE_INT_16(OPER_AY_IX_16(cpu))); +} + + +void m68k_op_suba_16_aw(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - MAKE_INT_16(OPER_AW_16(cpu))); +} + + +void m68k_op_suba_16_al(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - MAKE_INT_16(OPER_AL_16(cpu))); +} + + +void m68k_op_suba_16_pcdi(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - MAKE_INT_16(OPER_PCDI_16(cpu))); +} + + +void m68k_op_suba_16_pcix(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - MAKE_INT_16(OPER_PCIX_16(cpu))); +} + + +void m68k_op_suba_16_i(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - MAKE_INT_16(OPER_I_16())); +} + + +void m68k_op_suba_32_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - DY); +} + + +void m68k_op_suba_32_a(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - AY); +} + + +void m68k_op_suba_32_ai(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - OPER_AY_AI_32(cpu)); +} + + +void m68k_op_suba_32_pi(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - OPER_AY_PI_32(cpu)); +} + + +void m68k_op_suba_32_pd(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - OPER_AY_PD_32(cpu)); +} + + +void m68k_op_suba_32_di(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - OPER_AY_DI_32(cpu)); +} + + +void m68k_op_suba_32_ix(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - OPER_AY_IX_32(cpu)); +} + + +void m68k_op_suba_32_aw(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - OPER_AW_32(cpu)); +} + + +void m68k_op_suba_32_al(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - OPER_AL_32(cpu)); +} + + +void m68k_op_suba_32_pcdi(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - OPER_PCDI_32(cpu)); +} + + +void m68k_op_suba_32_pcix(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - OPER_PCIX_32(cpu)); +} + + +void m68k_op_suba_32_i(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - OPER_I_32()); +} + + +void m68k_op_subi_8_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint src = OPER_I_8(); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_subi_8_ai(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AY_AI_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_subi_8_pi(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AY_PI_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_subi_8_pi7(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_A7_PI_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_subi_8_pd(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AY_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_subi_8_pd7(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_subi_8_di(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AY_DI_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_subi_8_ix(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AY_IX_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_subi_8_aw(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AW_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_subi_8_al(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_8(); + uint ea = EA_AL_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_subi_16_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint src = OPER_I_16(); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +void m68k_op_subi_16_ai(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AY_AI_16(); + uint dst = m68ki_read_16(ea); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_subi_16_pi(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AY_PI_16(); + uint dst = m68ki_read_16(ea); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_subi_16_pd(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AY_PD_16(); + uint dst = m68ki_read_16(ea); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_subi_16_di(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AY_DI_16(); + uint dst = m68ki_read_16(ea); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_subi_16_ix(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AY_IX_16(); + uint dst = m68ki_read_16(ea); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_subi_16_aw(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AW_16(); + uint dst = m68ki_read_16(ea); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_subi_16_al(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_16(); + uint ea = EA_AL_16(); + uint dst = m68ki_read_16(ea); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_subi_32_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint src = OPER_I_32(); + uint dst = *r_dst; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + *r_dst = FLAG_Z; +} + + +void m68k_op_subi_32_ai(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AY_AI_32(); + uint dst = m68ki_read_32(ea); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_subi_32_pi(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AY_PI_32(); + uint dst = m68ki_read_32(ea); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_subi_32_pd(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AY_PD_32(); + uint dst = m68ki_read_32(ea); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_subi_32_di(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AY_DI_32(); + uint dst = m68ki_read_32(ea); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_subi_32_ix(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AY_IX_32(); + uint dst = m68ki_read_32(ea); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_subi_32_aw(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AW_32(); + uint dst = m68ki_read_32(ea); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_subi_32_al(m68ki_cpu_core *cpu) +{ + uint src = OPER_I_32(); + uint ea = EA_AL_32(); + uint dst = m68ki_read_32(ea); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_subq_8_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +void m68k_op_subq_8_ai(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AY_AI_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_subq_8_pi(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AY_PI_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_subq_8_pi7(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_A7_PI_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_subq_8_pd(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AY_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_subq_8_pd7(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_subq_8_di(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AY_DI_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_subq_8_ix(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AY_IX_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_subq_8_aw(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AW_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_subq_8_al(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AL_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +void m68k_op_subq_16_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +void m68k_op_subq_16_a(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AY; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - ((((REG_IR >> 9) - 1) & 7) + 1)); +} + + +void m68k_op_subq_16_ai(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AY_AI_16(); + uint dst = m68ki_read_16(ea); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_subq_16_pi(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AY_PI_16(); + uint dst = m68ki_read_16(ea); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_subq_16_pd(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AY_PD_16(); + uint dst = m68ki_read_16(ea); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_subq_16_di(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AY_DI_16(); + uint dst = m68ki_read_16(ea); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_subq_16_ix(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AY_IX_16(); + uint dst = m68ki_read_16(ea); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_subq_16_aw(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AW_16(); + uint dst = m68ki_read_16(ea); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_subq_16_al(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AL_16(); + uint dst = m68ki_read_16(ea); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + m68ki_write_16(ea, FLAG_Z); +} + + +void m68k_op_subq_32_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint dst = *r_dst; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + *r_dst = FLAG_Z; +} + + +void m68k_op_subq_32_a(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AY; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - ((((REG_IR >> 9) - 1) & 7) + 1)); +} + + +void m68k_op_subq_32_ai(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AY_AI_32(); + uint dst = m68ki_read_32(ea); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_subq_32_pi(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AY_PI_32(); + uint dst = m68ki_read_32(ea); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_subq_32_pd(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AY_PD_32(); + uint dst = m68ki_read_32(ea); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_subq_32_di(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AY_DI_32(); + uint dst = m68ki_read_32(ea); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_subq_32_ix(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AY_IX_32(); + uint dst = m68ki_read_32(ea); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_subq_32_aw(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AW_32(); + uint dst = m68ki_read_32(ea); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_subq_32_al(m68ki_cpu_core *cpu) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = EA_AL_32(); + uint dst = m68ki_read_32(ea); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + m68ki_write_32(ea, FLAG_Z); +} + + +void m68k_op_subx_8_rr(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_8(DY); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; +} + + +void m68k_op_subx_16_rr(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_16(DY); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + res = MASK_OUT_ABOVE_16(res); + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; +} + + +void m68k_op_subx_32_rr(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DX; + uint src = DY; + uint dst = *r_dst; + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + res = MASK_OUT_ABOVE_32(res); + FLAG_Z |= res; + + *r_dst = res; +} + + +void m68k_op_subx_8_mm_ax7(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_PD_8(cpu); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +void m68k_op_subx_8_mm_ay7(m68ki_cpu_core *cpu) +{ + uint src = OPER_A7_PD_8(cpu); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +void m68k_op_subx_8_mm_axy7(m68ki_cpu_core *cpu) +{ + uint src = OPER_A7_PD_8(cpu); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +void m68k_op_subx_8_mm(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_PD_8(cpu); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +void m68k_op_subx_16_mm(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_PD_16(cpu); + uint ea = EA_AX_PD_16(); + uint dst = m68ki_read_16(ea); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + res = MASK_OUT_ABOVE_16(res); + FLAG_Z |= res; + + m68ki_write_16(ea, res); +} + + +void m68k_op_subx_32_mm(m68ki_cpu_core *cpu) +{ + uint src = OPER_AY_PD_32(cpu); + uint ea = EA_AX_PD_32(); + uint dst = m68ki_read_32(ea); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + res = MASK_OUT_ABOVE_32(res); + FLAG_Z |= res; + + m68ki_write_32(ea, res); +} + + +void m68k_op_swap_32(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + + FLAG_Z = MASK_OUT_ABOVE_32(*r_dst<<16); + *r_dst = (*r_dst>>16) | FLAG_Z; + + FLAG_Z = *r_dst; + FLAG_N = NFLAG_32(*r_dst); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +void m68k_op_tas_8_d(m68ki_cpu_core *cpu) +{ + uint* r_dst = &DY; + + FLAG_Z = MASK_OUT_ABOVE_8(*r_dst); + FLAG_N = NFLAG_8(*r_dst); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst |= 0x80; +} + + +void m68k_op_tas_8_ai(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_AI_8(); + uint dst = m68ki_read_8(ea); + + FLAG_Z = dst; + FLAG_N = NFLAG_8(dst); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + m68ki_write_8(ea, dst | 0x80); +} + + +void m68k_op_tas_8_pi(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PI_8(); + uint dst = m68ki_read_8(ea); + + FLAG_Z = dst; + FLAG_N = NFLAG_8(dst); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + m68ki_write_8(ea, dst | 0x80); +} + + +void m68k_op_tas_8_pi7(m68ki_cpu_core *cpu) +{ + uint ea = EA_A7_PI_8(); + uint dst = m68ki_read_8(ea); + + FLAG_Z = dst; + FLAG_N = NFLAG_8(dst); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + m68ki_write_8(ea, dst | 0x80); +} + + +void m68k_op_tas_8_pd(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_PD_8(); + uint dst = m68ki_read_8(ea); + + FLAG_Z = dst; + FLAG_N = NFLAG_8(dst); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + m68ki_write_8(ea, dst | 0x80); +} + + +void m68k_op_tas_8_pd7(m68ki_cpu_core *cpu) +{ + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + + FLAG_Z = dst; + FLAG_N = NFLAG_8(dst); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + m68ki_write_8(ea, dst | 0x80); +} + + +void m68k_op_tas_8_di(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_DI_8(); + uint dst = m68ki_read_8(ea); + + FLAG_Z = dst; + FLAG_N = NFLAG_8(dst); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + m68ki_write_8(ea, dst | 0x80); +} + + +void m68k_op_tas_8_ix(m68ki_cpu_core *cpu) +{ + uint ea = EA_AY_IX_8(); + uint dst = m68ki_read_8(ea); + + FLAG_Z = dst; + FLAG_N = NFLAG_8(dst); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + m68ki_write_8(ea, dst | 0x80); +} + + +void m68k_op_tas_8_aw(m68ki_cpu_core *cpu) +{ + uint ea = EA_AW_8(); + uint dst = m68ki_read_8(ea); + + FLAG_Z = dst; + FLAG_N = NFLAG_8(dst); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + m68ki_write_8(ea, dst | 0x80); +} + + +void m68k_op_tas_8_al(m68ki_cpu_core *cpu) +{ + uint ea = EA_AL_8(); + uint dst = m68ki_read_8(ea); + + FLAG_Z = dst; + FLAG_N = NFLAG_8(dst); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + m68ki_write_8(ea, dst | 0x80); +} + + +void m68k_op_trap(m68ki_cpu_core *cpu) +{ + /* Trap#n stacks exception frame type 0 */ + m68ki_exception_trapN(cpu, EXCEPTION_TRAP_BASE + (REG_IR & 0xf)); /* HJB 990403 */ +} + + +void m68k_op_trapt(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapt_16(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapt_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapf(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapf_16(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_PC += 2; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapf_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_PC += 4; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_traphi(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_HI()) + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapls(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_LS()) + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapcc(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_CC()) + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapcs(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_CS()) + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapne(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_NE()) + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapeq(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_EQ()) + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapvc(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_VC()) + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapvs(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_VS()) + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trappl(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_PL()) + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapmi(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_MI()) + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapge(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_GE()) + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_traplt(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_LT()) + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapgt(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_GT()) + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_traple(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_LE()) + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_traphi_16(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_HI()) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 2; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapls_16(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_LS()) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 2; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapcc_16(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_CC()) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 2; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapcs_16(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_CS()) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 2; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapne_16(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_NE()) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 2; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapeq_16(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_EQ()) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 2; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapvc_16(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_VC()) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 2; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapvs_16(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_VS()) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 2; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trappl_16(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_PL()) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 2; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapmi_16(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_MI()) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 2; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapge_16(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_GE()) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 2; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_traplt_16(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_LT()) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 2; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapgt_16(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_GT()) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 2; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_traple_16(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_LE()) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 2; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_traphi_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_HI()) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapls_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_LS()) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapcc_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_CC()) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapcs_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_CS()) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapne_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_NE()) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapeq_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_EQ()) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapvc_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_VC()) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapvs_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_VS()) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trappl_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_PL()) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapmi_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_MI()) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapge_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_GE()) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_traplt_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_LT()) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapgt_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_GT()) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_traple_32(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(COND_LE()) + { + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_trapv(m68ki_cpu_core *cpu) +{ + if(COND_VC()) + { + return; + } + m68ki_exception_trap(cpu, EXCEPTION_TRAPV); /* HJB 990403 */ +} + + +void m68k_op_tst_8_d(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_8(DY); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_tst_8_ai(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_AI_8(cpu); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_tst_8_pi(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PI_8(cpu); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_tst_8_pi7(m68ki_cpu_core *cpu) +{ + uint res = OPER_A7_PI_8(cpu); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_tst_8_pd(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PD_8(cpu); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_tst_8_pd7(m68ki_cpu_core *cpu) +{ + uint res = OPER_A7_PD_8(cpu); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_tst_8_di(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_DI_8(cpu); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_tst_8_ix(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_IX_8(cpu); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_tst_8_aw(m68ki_cpu_core *cpu) +{ + uint res = OPER_AW_8(cpu); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_tst_8_al(m68ki_cpu_core *cpu) +{ + uint res = OPER_AL_8(cpu); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_tst_8_pcdi(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_PCDI_8(cpu); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_tst_8_pcix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_PCIX_8(cpu); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_tst_8_i(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_I_8(); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_tst_16_d(m68ki_cpu_core *cpu) +{ + uint res = MASK_OUT_ABOVE_16(DY); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_tst_16_a(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = MAKE_INT_16(AY); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_tst_16_ai(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_AI_16(cpu); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_tst_16_pi(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PI_16(cpu); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_tst_16_pd(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PD_16(cpu); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_tst_16_di(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_DI_16(cpu); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_tst_16_ix(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_IX_16(cpu); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_tst_16_aw(m68ki_cpu_core *cpu) +{ + uint res = OPER_AW_16(cpu); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_tst_16_al(m68ki_cpu_core *cpu) +{ + uint res = OPER_AL_16(cpu); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_tst_16_pcdi(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_PCDI_16(cpu); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_tst_16_pcix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_PCIX_16(cpu); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_tst_16_i(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_I_16(); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_tst_32_d(m68ki_cpu_core *cpu) +{ + uint res = DY; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_tst_32_a(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = AY; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_tst_32_ai(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_AI_32(cpu); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_tst_32_pi(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PI_32(cpu); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_tst_32_pd(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_PD_32(cpu); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_tst_32_di(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_DI_32(cpu); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_tst_32_ix(m68ki_cpu_core *cpu) +{ + uint res = OPER_AY_IX_32(cpu); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_tst_32_aw(m68ki_cpu_core *cpu) +{ + uint res = OPER_AW_32(cpu); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_tst_32_al(m68ki_cpu_core *cpu) +{ + uint res = OPER_AL_32(cpu); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +void m68k_op_tst_32_pcdi(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_PCDI_32(cpu); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_tst_32_pcix(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_PCIX_32(cpu); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_tst_32_i(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_I_32(); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_unlk_32_a7(m68ki_cpu_core *cpu) +{ + REG_A[7] = m68ki_read_32(REG_A[7]); +} + + +void m68k_op_unlk_32(m68ki_cpu_core *cpu) +{ + uint* r_dst = &AY; + + REG_A[7] = *r_dst; + *r_dst = m68ki_pull_32(cpu); +} + + +void m68k_op_unpk_16_rr(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: DX and DY are reversed in Motorola's docs */ + uint src = DY; + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | (((((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16()) & 0xffff); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_unpk_16_mm_ax7(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: AX and AY are reversed in Motorola's docs */ + uint src = OPER_AY_PD_8(cpu); + uint ea_dst; + + src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(); + ea_dst = EA_A7_PD_8(); + m68ki_write_8(ea_dst, (src >> 8) & 0xff); + ea_dst = EA_A7_PD_8(); + m68ki_write_8(ea_dst, src & 0xff); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_unpk_16_mm_ay7(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: AX and AY are reversed in Motorola's docs */ + uint src = OPER_A7_PD_8(cpu); + uint ea_dst; + + src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(); + ea_dst = EA_AX_PD_8(); + m68ki_write_8(ea_dst, (src >> 8) & 0xff); + ea_dst = EA_AX_PD_8(); + m68ki_write_8(ea_dst, src & 0xff); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_unpk_16_mm_axy7(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint src = OPER_A7_PD_8(cpu); + uint ea_dst; + + src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(); + ea_dst = EA_A7_PD_8(); + m68ki_write_8(ea_dst, (src >> 8) & 0xff); + ea_dst = EA_A7_PD_8(); + m68ki_write_8(ea_dst, src & 0xff); + return; + } + m68ki_exception_illegal(cpu); +} + + +void m68k_op_unpk_16_mm(m68ki_cpu_core *cpu) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: AX and AY are reversed in Motorola's docs */ + uint src = OPER_AY_PD_8(cpu); + uint ea_dst; + + src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(); + ea_dst = EA_AX_PD_8(); + m68ki_write_8(ea_dst, (src >> 8) & 0xff); + ea_dst = EA_AX_PD_8(); + m68ki_write_8(ea_dst, src & 0xff); + return; + } + m68ki_exception_illegal(cpu); +} + + +/* ======================================================================== */ +/* ============================== END OF FILE ============================= */ +/* ======================================================================== */ + + diff --git a/plugins/ao/eng_ssf/m68kops.c b/plugins/ao/eng_ssf/m68kops.c new file mode 100644 index 00000000..77c93816 --- /dev/null +++ b/plugins/ao/eng_ssf/m68kops.c @@ -0,0 +1,2093 @@ +/* ======================================================================== */ +/* ========================= OPCODE TABLE BUILDER ========================= */ +/* ======================================================================== */ + +#include "m68kops.h" + +#define NUM_CPU_TYPES 3 + +void (*m68ki_instruction_jump_table[0x10000])(m68ki_cpu_core *cpu); /* opcode handler jump table */ +unsigned char m68ki_cycles[NUM_CPU_TYPES][0x10000]; /* Cycles used by CPU type */ + +/* This is used to generate the opcode handler jump table */ +typedef struct +{ + void (*opcode_handler)(m68ki_cpu_core *cpu); /* handler function */ + unsigned int mask; /* mask on opcode */ + unsigned int match; /* what to match after masking */ + unsigned char cycles[NUM_CPU_TYPES]; /* cycles each cpu type takes */ +} opcode_handler_struct; + + +/* Opcode handler table */ +static opcode_handler_struct m68k_opcode_handler_table[] = +{ +/* function mask match 000 010 020 */ + {m68k_op_1010 , 0xf000, 0xa000, { 4, 4, 4}}, + {m68k_op_1111 , 0xf000, 0xf000, { 4, 4, 4}}, + {m68k_op_moveq_32 , 0xf100, 0x7000, { 4, 4, 2}}, + {m68k_op_cpbcc_32 , 0xf180, 0xf080, { 0, 0, 4}}, + {m68k_op_cpgen_32 , 0xf1c0, 0xf000, { 0, 0, 4}}, + {m68k_op_cpscc_32 , 0xf1c0, 0xf040, { 0, 0, 4}}, + {m68k_op_bra_8 , 0xff00, 0x6000, { 10, 10, 10}}, + {m68k_op_bsr_8 , 0xff00, 0x6100, { 18, 18, 7}}, + {m68k_op_bhi_8 , 0xff00, 0x6200, { 8, 8, 6}}, + {m68k_op_bls_8 , 0xff00, 0x6300, { 8, 8, 6}}, + {m68k_op_bcc_8 , 0xff00, 0x6400, { 8, 8, 6}}, + {m68k_op_bcs_8 , 0xff00, 0x6500, { 8, 8, 6}}, + {m68k_op_bne_8 , 0xff00, 0x6600, { 8, 8, 6}}, + {m68k_op_beq_8 , 0xff00, 0x6700, { 8, 8, 6}}, + {m68k_op_bvc_8 , 0xff00, 0x6800, { 8, 8, 6}}, + {m68k_op_bvs_8 , 0xff00, 0x6900, { 8, 8, 6}}, + {m68k_op_bpl_8 , 0xff00, 0x6a00, { 8, 8, 6}}, + {m68k_op_bmi_8 , 0xff00, 0x6b00, { 8, 8, 6}}, + {m68k_op_bge_8 , 0xff00, 0x6c00, { 8, 8, 6}}, + {m68k_op_blt_8 , 0xff00, 0x6d00, { 8, 8, 6}}, + {m68k_op_bgt_8 , 0xff00, 0x6e00, { 8, 8, 6}}, + {m68k_op_ble_8 , 0xff00, 0x6f00, { 8, 8, 6}}, + {m68k_op_btst_32_r_d , 0xf1f8, 0x0100, { 6, 6, 4}}, + {m68k_op_movep_16_er , 0xf1f8, 0x0108, { 16, 16, 12}}, + {m68k_op_btst_8_r_ai , 0xf1f8, 0x0110, { 8, 8, 8}}, + {m68k_op_btst_8_r_pi , 0xf1f8, 0x0118, { 8, 8, 8}}, + {m68k_op_btst_8_r_pd , 0xf1f8, 0x0120, { 10, 10, 9}}, + {m68k_op_btst_8_r_di , 0xf1f8, 0x0128, { 12, 12, 9}}, + {m68k_op_btst_8_r_ix , 0xf1f8, 0x0130, { 14, 14, 11}}, + {m68k_op_bchg_32_r_d , 0xf1f8, 0x0140, { 8, 8, 4}}, + {m68k_op_movep_32_er , 0xf1f8, 0x0148, { 24, 24, 18}}, + {m68k_op_bchg_8_r_ai , 0xf1f8, 0x0150, { 12, 12, 8}}, + {m68k_op_bchg_8_r_pi , 0xf1f8, 0x0158, { 12, 12, 8}}, + {m68k_op_bchg_8_r_pd , 0xf1f8, 0x0160, { 14, 14, 9}}, + {m68k_op_bchg_8_r_di , 0xf1f8, 0x0168, { 16, 16, 9}}, + {m68k_op_bchg_8_r_ix , 0xf1f8, 0x0170, { 18, 18, 11}}, + {m68k_op_bclr_32_r_d , 0xf1f8, 0x0180, { 10, 10, 4}}, + {m68k_op_movep_16_re , 0xf1f8, 0x0188, { 16, 16, 11}}, + {m68k_op_bclr_8_r_ai , 0xf1f8, 0x0190, { 12, 14, 8}}, + {m68k_op_bclr_8_r_pi , 0xf1f8, 0x0198, { 12, 14, 8}}, + {m68k_op_bclr_8_r_pd , 0xf1f8, 0x01a0, { 14, 16, 9}}, + {m68k_op_bclr_8_r_di , 0xf1f8, 0x01a8, { 16, 18, 9}}, + {m68k_op_bclr_8_r_ix , 0xf1f8, 0x01b0, { 18, 20, 11}}, + {m68k_op_bset_32_r_d , 0xf1f8, 0x01c0, { 8, 8, 4}}, + {m68k_op_movep_32_re , 0xf1f8, 0x01c8, { 24, 24, 17}}, + {m68k_op_bset_8_r_ai , 0xf1f8, 0x01d0, { 12, 12, 8}}, + {m68k_op_bset_8_r_pi , 0xf1f8, 0x01d8, { 12, 12, 8}}, + {m68k_op_bset_8_r_pd , 0xf1f8, 0x01e0, { 14, 14, 9}}, + {m68k_op_bset_8_r_di , 0xf1f8, 0x01e8, { 16, 16, 9}}, + {m68k_op_bset_8_r_ix , 0xf1f8, 0x01f0, { 18, 18, 11}}, + {m68k_op_move_8_d_d , 0xf1f8, 0x1000, { 4, 4, 2}}, + {m68k_op_move_8_d_ai , 0xf1f8, 0x1010, { 8, 8, 6}}, + {m68k_op_move_8_d_pi , 0xf1f8, 0x1018, { 8, 8, 6}}, + {m68k_op_move_8_d_pd , 0xf1f8, 0x1020, { 10, 10, 7}}, + {m68k_op_move_8_d_di , 0xf1f8, 0x1028, { 12, 12, 7}}, + {m68k_op_move_8_d_ix , 0xf1f8, 0x1030, { 14, 14, 9}}, + {m68k_op_move_8_ai_d , 0xf1f8, 0x1080, { 8, 8, 4}}, + {m68k_op_move_8_ai_ai , 0xf1f8, 0x1090, { 12, 12, 8}}, + {m68k_op_move_8_ai_pi , 0xf1f8, 0x1098, { 12, 12, 8}}, + {m68k_op_move_8_ai_pd , 0xf1f8, 0x10a0, { 14, 14, 9}}, + {m68k_op_move_8_ai_di , 0xf1f8, 0x10a8, { 16, 16, 9}}, + {m68k_op_move_8_ai_ix , 0xf1f8, 0x10b0, { 18, 18, 11}}, + {m68k_op_move_8_pi_d , 0xf1f8, 0x10c0, { 8, 8, 4}}, + {m68k_op_move_8_pi_ai , 0xf1f8, 0x10d0, { 12, 12, 8}}, + {m68k_op_move_8_pi_pi , 0xf1f8, 0x10d8, { 12, 12, 8}}, + {m68k_op_move_8_pi_pd , 0xf1f8, 0x10e0, { 14, 14, 9}}, + {m68k_op_move_8_pi_di , 0xf1f8, 0x10e8, { 16, 16, 9}}, + {m68k_op_move_8_pi_ix , 0xf1f8, 0x10f0, { 18, 18, 11}}, + {m68k_op_move_8_pd_d , 0xf1f8, 0x1100, { 8, 8, 5}}, + {m68k_op_move_8_pd_ai , 0xf1f8, 0x1110, { 12, 12, 9}}, + {m68k_op_move_8_pd_pi , 0xf1f8, 0x1118, { 12, 12, 9}}, + {m68k_op_move_8_pd_pd , 0xf1f8, 0x1120, { 14, 14, 10}}, + {m68k_op_move_8_pd_di , 0xf1f8, 0x1128, { 16, 16, 10}}, + {m68k_op_move_8_pd_ix , 0xf1f8, 0x1130, { 18, 18, 12}}, + {m68k_op_move_8_di_d , 0xf1f8, 0x1140, { 12, 12, 5}}, + {m68k_op_move_8_di_ai , 0xf1f8, 0x1150, { 16, 16, 9}}, + {m68k_op_move_8_di_pi , 0xf1f8, 0x1158, { 16, 16, 9}}, + {m68k_op_move_8_di_pd , 0xf1f8, 0x1160, { 18, 18, 10}}, + {m68k_op_move_8_di_di , 0xf1f8, 0x1168, { 20, 20, 10}}, + {m68k_op_move_8_di_ix , 0xf1f8, 0x1170, { 22, 22, 12}}, + {m68k_op_move_8_ix_d , 0xf1f8, 0x1180, { 14, 14, 7}}, + {m68k_op_move_8_ix_ai , 0xf1f8, 0x1190, { 18, 18, 11}}, + {m68k_op_move_8_ix_pi , 0xf1f8, 0x1198, { 18, 18, 11}}, + {m68k_op_move_8_ix_pd , 0xf1f8, 0x11a0, { 20, 20, 12}}, + {m68k_op_move_8_ix_di , 0xf1f8, 0x11a8, { 22, 22, 12}}, + {m68k_op_move_8_ix_ix , 0xf1f8, 0x11b0, { 24, 24, 14}}, + {m68k_op_move_32_d_d , 0xf1f8, 0x2000, { 4, 4, 2}}, + {m68k_op_move_32_d_a , 0xf1f8, 0x2008, { 4, 4, 2}}, + {m68k_op_move_32_d_ai , 0xf1f8, 0x2010, { 12, 12, 6}}, + {m68k_op_move_32_d_pi , 0xf1f8, 0x2018, { 12, 12, 6}}, + {m68k_op_move_32_d_pd , 0xf1f8, 0x2020, { 14, 14, 7}}, + {m68k_op_move_32_d_di , 0xf1f8, 0x2028, { 16, 16, 7}}, + {m68k_op_move_32_d_ix , 0xf1f8, 0x2030, { 18, 18, 9}}, + {m68k_op_movea_32_d , 0xf1f8, 0x2040, { 4, 4, 2}}, + {m68k_op_movea_32_a , 0xf1f8, 0x2048, { 4, 4, 2}}, + {m68k_op_movea_32_ai , 0xf1f8, 0x2050, { 12, 12, 6}}, + {m68k_op_movea_32_pi , 0xf1f8, 0x2058, { 12, 12, 6}}, + {m68k_op_movea_32_pd , 0xf1f8, 0x2060, { 14, 14, 7}}, + {m68k_op_movea_32_di , 0xf1f8, 0x2068, { 16, 16, 7}}, + {m68k_op_movea_32_ix , 0xf1f8, 0x2070, { 18, 18, 9}}, + {m68k_op_move_32_ai_d , 0xf1f8, 0x2080, { 12, 12, 4}}, + {m68k_op_move_32_ai_a , 0xf1f8, 0x2088, { 12, 12, 4}}, + {m68k_op_move_32_ai_ai , 0xf1f8, 0x2090, { 20, 20, 8}}, + {m68k_op_move_32_ai_pi , 0xf1f8, 0x2098, { 20, 20, 8}}, + {m68k_op_move_32_ai_pd , 0xf1f8, 0x20a0, { 22, 22, 9}}, + {m68k_op_move_32_ai_di , 0xf1f8, 0x20a8, { 24, 24, 9}}, + {m68k_op_move_32_ai_ix , 0xf1f8, 0x20b0, { 26, 26, 11}}, + {m68k_op_move_32_pi_d , 0xf1f8, 0x20c0, { 12, 12, 4}}, + {m68k_op_move_32_pi_a , 0xf1f8, 0x20c8, { 12, 12, 4}}, + {m68k_op_move_32_pi_ai , 0xf1f8, 0x20d0, { 20, 20, 8}}, + {m68k_op_move_32_pi_pi , 0xf1f8, 0x20d8, { 20, 20, 8}}, + {m68k_op_move_32_pi_pd , 0xf1f8, 0x20e0, { 22, 22, 9}}, + {m68k_op_move_32_pi_di , 0xf1f8, 0x20e8, { 24, 24, 9}}, + {m68k_op_move_32_pi_ix , 0xf1f8, 0x20f0, { 26, 26, 11}}, + {m68k_op_move_32_pd_d , 0xf1f8, 0x2100, { 12, 14, 5}}, + {m68k_op_move_32_pd_a , 0xf1f8, 0x2108, { 12, 14, 5}}, + {m68k_op_move_32_pd_ai , 0xf1f8, 0x2110, { 20, 22, 9}}, + {m68k_op_move_32_pd_pi , 0xf1f8, 0x2118, { 20, 22, 9}}, + {m68k_op_move_32_pd_pd , 0xf1f8, 0x2120, { 22, 24, 10}}, + {m68k_op_move_32_pd_di , 0xf1f8, 0x2128, { 24, 26, 10}}, + {m68k_op_move_32_pd_ix , 0xf1f8, 0x2130, { 26, 28, 12}}, + {m68k_op_move_32_di_d , 0xf1f8, 0x2140, { 16, 16, 5}}, + {m68k_op_move_32_di_a , 0xf1f8, 0x2148, { 16, 16, 5}}, + {m68k_op_move_32_di_ai , 0xf1f8, 0x2150, { 24, 24, 9}}, + {m68k_op_move_32_di_pi , 0xf1f8, 0x2158, { 24, 24, 9}}, + {m68k_op_move_32_di_pd , 0xf1f8, 0x2160, { 26, 26, 10}}, + {m68k_op_move_32_di_di , 0xf1f8, 0x2168, { 28, 28, 10}}, + {m68k_op_move_32_di_ix , 0xf1f8, 0x2170, { 30, 30, 12}}, + {m68k_op_move_32_ix_d , 0xf1f8, 0x2180, { 18, 18, 7}}, + {m68k_op_move_32_ix_a , 0xf1f8, 0x2188, { 18, 18, 7}}, + {m68k_op_move_32_ix_ai , 0xf1f8, 0x2190, { 26, 26, 11}}, + {m68k_op_move_32_ix_pi , 0xf1f8, 0x2198, { 26, 26, 11}}, + {m68k_op_move_32_ix_pd , 0xf1f8, 0x21a0, { 28, 28, 12}}, + {m68k_op_move_32_ix_di , 0xf1f8, 0x21a8, { 30, 30, 12}}, + {m68k_op_move_32_ix_ix , 0xf1f8, 0x21b0, { 32, 32, 14}}, + {m68k_op_move_16_d_d , 0xf1f8, 0x3000, { 4, 4, 2}}, + {m68k_op_move_16_d_a , 0xf1f8, 0x3008, { 4, 4, 2}}, + {m68k_op_move_16_d_ai , 0xf1f8, 0x3010, { 8, 8, 6}}, + {m68k_op_move_16_d_pi , 0xf1f8, 0x3018, { 8, 8, 6}}, + {m68k_op_move_16_d_pd , 0xf1f8, 0x3020, { 10, 10, 7}}, + {m68k_op_move_16_d_di , 0xf1f8, 0x3028, { 12, 12, 7}}, + {m68k_op_move_16_d_ix , 0xf1f8, 0x3030, { 14, 14, 9}}, + {m68k_op_movea_16_d , 0xf1f8, 0x3040, { 4, 4, 2}}, + {m68k_op_movea_16_a , 0xf1f8, 0x3048, { 4, 4, 2}}, + {m68k_op_movea_16_ai , 0xf1f8, 0x3050, { 8, 8, 6}}, + {m68k_op_movea_16_pi , 0xf1f8, 0x3058, { 8, 8, 6}}, + {m68k_op_movea_16_pd , 0xf1f8, 0x3060, { 10, 10, 7}}, + {m68k_op_movea_16_di , 0xf1f8, 0x3068, { 12, 12, 7}}, + {m68k_op_movea_16_ix , 0xf1f8, 0x3070, { 14, 14, 9}}, + {m68k_op_move_16_ai_d , 0xf1f8, 0x3080, { 8, 8, 4}}, + {m68k_op_move_16_ai_a , 0xf1f8, 0x3088, { 8, 8, 4}}, + {m68k_op_move_16_ai_ai , 0xf1f8, 0x3090, { 12, 12, 8}}, + {m68k_op_move_16_ai_pi , 0xf1f8, 0x3098, { 12, 12, 8}}, + {m68k_op_move_16_ai_pd , 0xf1f8, 0x30a0, { 14, 14, 9}}, + {m68k_op_move_16_ai_di , 0xf1f8, 0x30a8, { 16, 16, 9}}, + {m68k_op_move_16_ai_ix , 0xf1f8, 0x30b0, { 18, 18, 11}}, + {m68k_op_move_16_pi_d , 0xf1f8, 0x30c0, { 8, 8, 4}}, + {m68k_op_move_16_pi_a , 0xf1f8, 0x30c8, { 8, 8, 4}}, + {m68k_op_move_16_pi_ai , 0xf1f8, 0x30d0, { 12, 12, 8}}, + {m68k_op_move_16_pi_pi , 0xf1f8, 0x30d8, { 12, 12, 8}}, + {m68k_op_move_16_pi_pd , 0xf1f8, 0x30e0, { 14, 14, 9}}, + {m68k_op_move_16_pi_di , 0xf1f8, 0x30e8, { 16, 16, 9}}, + {m68k_op_move_16_pi_ix , 0xf1f8, 0x30f0, { 18, 18, 11}}, + {m68k_op_move_16_pd_d , 0xf1f8, 0x3100, { 8, 8, 5}}, + {m68k_op_move_16_pd_a , 0xf1f8, 0x3108, { 8, 8, 5}}, + {m68k_op_move_16_pd_ai , 0xf1f8, 0x3110, { 12, 12, 9}}, + {m68k_op_move_16_pd_pi , 0xf1f8, 0x3118, { 12, 12, 9}}, + {m68k_op_move_16_pd_pd , 0xf1f8, 0x3120, { 14, 14, 10}}, + {m68k_op_move_16_pd_di , 0xf1f8, 0x3128, { 16, 16, 10}}, + {m68k_op_move_16_pd_ix , 0xf1f8, 0x3130, { 18, 18, 12}}, + {m68k_op_move_16_di_d , 0xf1f8, 0x3140, { 12, 12, 5}}, + {m68k_op_move_16_di_a , 0xf1f8, 0x3148, { 12, 12, 5}}, + {m68k_op_move_16_di_ai , 0xf1f8, 0x3150, { 16, 16, 9}}, + {m68k_op_move_16_di_pi , 0xf1f8, 0x3158, { 16, 16, 9}}, + {m68k_op_move_16_di_pd , 0xf1f8, 0x3160, { 18, 18, 10}}, + {m68k_op_move_16_di_di , 0xf1f8, 0x3168, { 20, 20, 10}}, + {m68k_op_move_16_di_ix , 0xf1f8, 0x3170, { 22, 22, 12}}, + {m68k_op_move_16_ix_d , 0xf1f8, 0x3180, { 14, 14, 7}}, + {m68k_op_move_16_ix_a , 0xf1f8, 0x3188, { 14, 14, 7}}, + {m68k_op_move_16_ix_ai , 0xf1f8, 0x3190, { 18, 18, 11}}, + {m68k_op_move_16_ix_pi , 0xf1f8, 0x3198, { 18, 18, 11}}, + {m68k_op_move_16_ix_pd , 0xf1f8, 0x31a0, { 20, 20, 12}}, + {m68k_op_move_16_ix_di , 0xf1f8, 0x31a8, { 22, 22, 12}}, + {m68k_op_move_16_ix_ix , 0xf1f8, 0x31b0, { 24, 24, 14}}, + {m68k_op_chk_32_d , 0xf1f8, 0x4100, { 0, 0, 8}}, + {m68k_op_chk_32_ai , 0xf1f8, 0x4110, { 0, 0, 12}}, + {m68k_op_chk_32_pi , 0xf1f8, 0x4118, { 0, 0, 12}}, + {m68k_op_chk_32_pd , 0xf1f8, 0x4120, { 0, 0, 13}}, + {m68k_op_chk_32_di , 0xf1f8, 0x4128, { 0, 0, 13}}, + {m68k_op_chk_32_ix , 0xf1f8, 0x4130, { 0, 0, 15}}, + {m68k_op_chk_16_d , 0xf1f8, 0x4180, { 10, 8, 8}}, + {m68k_op_chk_16_ai , 0xf1f8, 0x4190, { 14, 12, 12}}, + {m68k_op_chk_16_pi , 0xf1f8, 0x4198, { 14, 12, 12}}, + {m68k_op_chk_16_pd , 0xf1f8, 0x41a0, { 16, 14, 13}}, + {m68k_op_chk_16_di , 0xf1f8, 0x41a8, { 18, 16, 13}}, + {m68k_op_chk_16_ix , 0xf1f8, 0x41b0, { 20, 18, 15}}, + {m68k_op_lea_32_ai , 0xf1f8, 0x41d0, { 4, 4, 6}}, + {m68k_op_lea_32_di , 0xf1f8, 0x41e8, { 8, 8, 7}}, + {m68k_op_lea_32_ix , 0xf1f8, 0x41f0, { 12, 12, 9}}, + {m68k_op_addq_8_d , 0xf1f8, 0x5000, { 4, 4, 2}}, + {m68k_op_addq_8_ai , 0xf1f8, 0x5010, { 12, 12, 8}}, + {m68k_op_addq_8_pi , 0xf1f8, 0x5018, { 12, 12, 8}}, + {m68k_op_addq_8_pd , 0xf1f8, 0x5020, { 14, 14, 9}}, + {m68k_op_addq_8_di , 0xf1f8, 0x5028, { 16, 16, 9}}, + {m68k_op_addq_8_ix , 0xf1f8, 0x5030, { 18, 18, 11}}, + {m68k_op_addq_16_d , 0xf1f8, 0x5040, { 4, 4, 2}}, + {m68k_op_addq_16_a , 0xf1f8, 0x5048, { 4, 4, 2}}, + {m68k_op_addq_16_ai , 0xf1f8, 0x5050, { 12, 12, 8}}, + {m68k_op_addq_16_pi , 0xf1f8, 0x5058, { 12, 12, 8}}, + {m68k_op_addq_16_pd , 0xf1f8, 0x5060, { 14, 14, 9}}, + {m68k_op_addq_16_di , 0xf1f8, 0x5068, { 16, 16, 9}}, + {m68k_op_addq_16_ix , 0xf1f8, 0x5070, { 18, 18, 11}}, + {m68k_op_addq_32_d , 0xf1f8, 0x5080, { 8, 8, 2}}, + {m68k_op_addq_32_a , 0xf1f8, 0x5088, { 8, 8, 2}}, + {m68k_op_addq_32_ai , 0xf1f8, 0x5090, { 20, 20, 8}}, + {m68k_op_addq_32_pi , 0xf1f8, 0x5098, { 20, 20, 8}}, + {m68k_op_addq_32_pd , 0xf1f8, 0x50a0, { 22, 22, 9}}, + {m68k_op_addq_32_di , 0xf1f8, 0x50a8, { 24, 24, 9}}, + {m68k_op_addq_32_ix , 0xf1f8, 0x50b0, { 26, 26, 11}}, + {m68k_op_subq_8_d , 0xf1f8, 0x5100, { 4, 4, 2}}, + {m68k_op_subq_8_ai , 0xf1f8, 0x5110, { 12, 12, 8}}, + {m68k_op_subq_8_pi , 0xf1f8, 0x5118, { 12, 12, 8}}, + {m68k_op_subq_8_pd , 0xf1f8, 0x5120, { 14, 14, 9}}, + {m68k_op_subq_8_di , 0xf1f8, 0x5128, { 16, 16, 9}}, + {m68k_op_subq_8_ix , 0xf1f8, 0x5130, { 18, 18, 11}}, + {m68k_op_subq_16_d , 0xf1f8, 0x5140, { 4, 4, 2}}, + {m68k_op_subq_16_a , 0xf1f8, 0x5148, { 8, 4, 2}}, + {m68k_op_subq_16_ai , 0xf1f8, 0x5150, { 12, 12, 8}}, + {m68k_op_subq_16_pi , 0xf1f8, 0x5158, { 12, 12, 8}}, + {m68k_op_subq_16_pd , 0xf1f8, 0x5160, { 14, 14, 9}}, + {m68k_op_subq_16_di , 0xf1f8, 0x5168, { 16, 16, 9}}, + {m68k_op_subq_16_ix , 0xf1f8, 0x5170, { 18, 18, 11}}, + {m68k_op_subq_32_d , 0xf1f8, 0x5180, { 8, 8, 2}}, + {m68k_op_subq_32_a , 0xf1f8, 0x5188, { 8, 8, 2}}, + {m68k_op_subq_32_ai , 0xf1f8, 0x5190, { 20, 20, 8}}, + {m68k_op_subq_32_pi , 0xf1f8, 0x5198, { 20, 20, 8}}, + {m68k_op_subq_32_pd , 0xf1f8, 0x51a0, { 22, 22, 9}}, + {m68k_op_subq_32_di , 0xf1f8, 0x51a8, { 24, 24, 9}}, + {m68k_op_subq_32_ix , 0xf1f8, 0x51b0, { 26, 26, 11}}, + {m68k_op_or_8_er_d , 0xf1f8, 0x8000, { 4, 4, 2}}, + {m68k_op_or_8_er_ai , 0xf1f8, 0x8010, { 8, 8, 6}}, + {m68k_op_or_8_er_pi , 0xf1f8, 0x8018, { 8, 8, 6}}, + {m68k_op_or_8_er_pd , 0xf1f8, 0x8020, { 10, 10, 7}}, + {m68k_op_or_8_er_di , 0xf1f8, 0x8028, { 12, 12, 7}}, + {m68k_op_or_8_er_ix , 0xf1f8, 0x8030, { 14, 14, 9}}, + {m68k_op_or_16_er_d , 0xf1f8, 0x8040, { 4, 4, 2}}, + {m68k_op_or_16_er_ai , 0xf1f8, 0x8050, { 8, 8, 6}}, + {m68k_op_or_16_er_pi , 0xf1f8, 0x8058, { 8, 8, 6}}, + {m68k_op_or_16_er_pd , 0xf1f8, 0x8060, { 10, 10, 7}}, + {m68k_op_or_16_er_di , 0xf1f8, 0x8068, { 12, 12, 7}}, + {m68k_op_or_16_er_ix , 0xf1f8, 0x8070, { 14, 14, 9}}, + {m68k_op_or_32_er_d , 0xf1f8, 0x8080, { 6, 6, 2}}, + {m68k_op_or_32_er_ai , 0xf1f8, 0x8090, { 14, 14, 6}}, + {m68k_op_or_32_er_pi , 0xf1f8, 0x8098, { 14, 14, 6}}, + {m68k_op_or_32_er_pd , 0xf1f8, 0x80a0, { 16, 16, 7}}, + {m68k_op_or_32_er_di , 0xf1f8, 0x80a8, { 18, 18, 7}}, + {m68k_op_or_32_er_ix , 0xf1f8, 0x80b0, { 20, 20, 9}}, + {m68k_op_divu_16_d , 0xf1f8, 0x80c0, {140, 108, 44}}, + {m68k_op_divu_16_ai , 0xf1f8, 0x80d0, {144, 112, 48}}, + {m68k_op_divu_16_pi , 0xf1f8, 0x80d8, {144, 112, 48}}, + {m68k_op_divu_16_pd , 0xf1f8, 0x80e0, {146, 114, 49}}, + {m68k_op_divu_16_di , 0xf1f8, 0x80e8, {148, 116, 49}}, + {m68k_op_divu_16_ix , 0xf1f8, 0x80f0, {150, 118, 51}}, + {m68k_op_sbcd_8_rr , 0xf1f8, 0x8100, { 6, 6, 4}}, + {m68k_op_sbcd_8_mm , 0xf1f8, 0x8108, { 18, 18, 16}}, + {m68k_op_or_8_re_ai , 0xf1f8, 0x8110, { 12, 12, 8}}, + {m68k_op_or_8_re_pi , 0xf1f8, 0x8118, { 12, 12, 8}}, + {m68k_op_or_8_re_pd , 0xf1f8, 0x8120, { 14, 14, 9}}, + {m68k_op_or_8_re_di , 0xf1f8, 0x8128, { 16, 16, 9}}, + {m68k_op_or_8_re_ix , 0xf1f8, 0x8130, { 18, 18, 11}}, + {m68k_op_pack_16_rr , 0xf1f8, 0x8140, { 0, 0, 6}}, + {m68k_op_pack_16_mm , 0xf1f8, 0x8148, { 0, 0, 13}}, + {m68k_op_or_16_re_ai , 0xf1f8, 0x8150, { 12, 12, 8}}, + {m68k_op_or_16_re_pi , 0xf1f8, 0x8158, { 12, 12, 8}}, + {m68k_op_or_16_re_pd , 0xf1f8, 0x8160, { 14, 14, 9}}, + {m68k_op_or_16_re_di , 0xf1f8, 0x8168, { 16, 16, 9}}, + {m68k_op_or_16_re_ix , 0xf1f8, 0x8170, { 18, 18, 11}}, + {m68k_op_unpk_16_rr , 0xf1f8, 0x8180, { 0, 0, 8}}, + {m68k_op_unpk_16_mm , 0xf1f8, 0x8188, { 0, 0, 13}}, + {m68k_op_or_32_re_ai , 0xf1f8, 0x8190, { 20, 20, 8}}, + {m68k_op_or_32_re_pi , 0xf1f8, 0x8198, { 20, 20, 8}}, + {m68k_op_or_32_re_pd , 0xf1f8, 0x81a0, { 22, 22, 9}}, + {m68k_op_or_32_re_di , 0xf1f8, 0x81a8, { 24, 24, 9}}, + {m68k_op_or_32_re_ix , 0xf1f8, 0x81b0, { 26, 26, 11}}, + {m68k_op_divs_16_d , 0xf1f8, 0x81c0, {158, 122, 56}}, + {m68k_op_divs_16_ai , 0xf1f8, 0x81d0, {162, 126, 60}}, + {m68k_op_divs_16_pi , 0xf1f8, 0x81d8, {162, 126, 60}}, + {m68k_op_divs_16_pd , 0xf1f8, 0x81e0, {164, 128, 61}}, + {m68k_op_divs_16_di , 0xf1f8, 0x81e8, {166, 130, 61}}, + {m68k_op_divs_16_ix , 0xf1f8, 0x81f0, {168, 132, 63}}, + {m68k_op_sub_8_er_d , 0xf1f8, 0x9000, { 4, 4, 2}}, + {m68k_op_sub_8_er_ai , 0xf1f8, 0x9010, { 8, 8, 6}}, + {m68k_op_sub_8_er_pi , 0xf1f8, 0x9018, { 8, 8, 6}}, + {m68k_op_sub_8_er_pd , 0xf1f8, 0x9020, { 10, 10, 7}}, + {m68k_op_sub_8_er_di , 0xf1f8, 0x9028, { 12, 12, 7}}, + {m68k_op_sub_8_er_ix , 0xf1f8, 0x9030, { 14, 14, 9}}, + {m68k_op_sub_16_er_d , 0xf1f8, 0x9040, { 4, 4, 2}}, + {m68k_op_sub_16_er_a , 0xf1f8, 0x9048, { 4, 4, 2}}, + {m68k_op_sub_16_er_ai , 0xf1f8, 0x9050, { 8, 8, 6}}, + {m68k_op_sub_16_er_pi , 0xf1f8, 0x9058, { 8, 8, 6}}, + {m68k_op_sub_16_er_pd , 0xf1f8, 0x9060, { 10, 10, 7}}, + {m68k_op_sub_16_er_di , 0xf1f8, 0x9068, { 12, 12, 7}}, + {m68k_op_sub_16_er_ix , 0xf1f8, 0x9070, { 14, 14, 9}}, + {m68k_op_sub_32_er_d , 0xf1f8, 0x9080, { 6, 6, 2}}, + {m68k_op_sub_32_er_a , 0xf1f8, 0x9088, { 6, 6, 2}}, + {m68k_op_sub_32_er_ai , 0xf1f8, 0x9090, { 14, 14, 6}}, + {m68k_op_sub_32_er_pi , 0xf1f8, 0x9098, { 14, 14, 6}}, + {m68k_op_sub_32_er_pd , 0xf1f8, 0x90a0, { 16, 16, 7}}, + {m68k_op_sub_32_er_di , 0xf1f8, 0x90a8, { 18, 18, 7}}, + {m68k_op_sub_32_er_ix , 0xf1f8, 0x90b0, { 20, 20, 9}}, + {m68k_op_suba_16_d , 0xf1f8, 0x90c0, { 8, 8, 2}}, + {m68k_op_suba_16_a , 0xf1f8, 0x90c8, { 8, 8, 2}}, + {m68k_op_suba_16_ai , 0xf1f8, 0x90d0, { 12, 12, 6}}, + {m68k_op_suba_16_pi , 0xf1f8, 0x90d8, { 12, 12, 6}}, + {m68k_op_suba_16_pd , 0xf1f8, 0x90e0, { 14, 14, 7}}, + {m68k_op_suba_16_di , 0xf1f8, 0x90e8, { 16, 16, 7}}, + {m68k_op_suba_16_ix , 0xf1f8, 0x90f0, { 18, 18, 9}}, + {m68k_op_subx_8_rr , 0xf1f8, 0x9100, { 4, 4, 2}}, + {m68k_op_subx_8_mm , 0xf1f8, 0x9108, { 18, 18, 12}}, + {m68k_op_sub_8_re_ai , 0xf1f8, 0x9110, { 12, 12, 8}}, + {m68k_op_sub_8_re_pi , 0xf1f8, 0x9118, { 12, 12, 8}}, + {m68k_op_sub_8_re_pd , 0xf1f8, 0x9120, { 14, 14, 9}}, + {m68k_op_sub_8_re_di , 0xf1f8, 0x9128, { 16, 16, 9}}, + {m68k_op_sub_8_re_ix , 0xf1f8, 0x9130, { 18, 18, 11}}, + {m68k_op_subx_16_rr , 0xf1f8, 0x9140, { 4, 4, 2}}, + {m68k_op_subx_16_mm , 0xf1f8, 0x9148, { 18, 18, 12}}, + {m68k_op_sub_16_re_ai , 0xf1f8, 0x9150, { 12, 12, 8}}, + {m68k_op_sub_16_re_pi , 0xf1f8, 0x9158, { 12, 12, 8}}, + {m68k_op_sub_16_re_pd , 0xf1f8, 0x9160, { 14, 14, 9}}, + {m68k_op_sub_16_re_di , 0xf1f8, 0x9168, { 16, 16, 9}}, + {m68k_op_sub_16_re_ix , 0xf1f8, 0x9170, { 18, 18, 11}}, + {m68k_op_subx_32_rr , 0xf1f8, 0x9180, { 8, 6, 2}}, + {m68k_op_subx_32_mm , 0xf1f8, 0x9188, { 30, 30, 12}}, + {m68k_op_sub_32_re_ai , 0xf1f8, 0x9190, { 20, 20, 8}}, + {m68k_op_sub_32_re_pi , 0xf1f8, 0x9198, { 20, 20, 8}}, + {m68k_op_sub_32_re_pd , 0xf1f8, 0x91a0, { 22, 22, 9}}, + {m68k_op_sub_32_re_di , 0xf1f8, 0x91a8, { 24, 24, 9}}, + {m68k_op_sub_32_re_ix , 0xf1f8, 0x91b0, { 26, 26, 11}}, + {m68k_op_suba_32_d , 0xf1f8, 0x91c0, { 6, 6, 2}}, + {m68k_op_suba_32_a , 0xf1f8, 0x91c8, { 6, 6, 2}}, + {m68k_op_suba_32_ai , 0xf1f8, 0x91d0, { 14, 14, 6}}, + {m68k_op_suba_32_pi , 0xf1f8, 0x91d8, { 14, 14, 6}}, + {m68k_op_suba_32_pd , 0xf1f8, 0x91e0, { 16, 16, 7}}, + {m68k_op_suba_32_di , 0xf1f8, 0x91e8, { 18, 18, 7}}, + {m68k_op_suba_32_ix , 0xf1f8, 0x91f0, { 20, 20, 9}}, + {m68k_op_cmp_8_d , 0xf1f8, 0xb000, { 4, 4, 2}}, + {m68k_op_cmp_8_ai , 0xf1f8, 0xb010, { 8, 8, 6}}, + {m68k_op_cmp_8_pi , 0xf1f8, 0xb018, { 8, 8, 6}}, + {m68k_op_cmp_8_pd , 0xf1f8, 0xb020, { 10, 10, 7}}, + {m68k_op_cmp_8_di , 0xf1f8, 0xb028, { 12, 12, 7}}, + {m68k_op_cmp_8_ix , 0xf1f8, 0xb030, { 14, 14, 9}}, + {m68k_op_cmp_16_d , 0xf1f8, 0xb040, { 4, 4, 2}}, + {m68k_op_cmp_16_a , 0xf1f8, 0xb048, { 4, 4, 2}}, + {m68k_op_cmp_16_ai , 0xf1f8, 0xb050, { 8, 8, 6}}, + {m68k_op_cmp_16_pi , 0xf1f8, 0xb058, { 8, 8, 6}}, + {m68k_op_cmp_16_pd , 0xf1f8, 0xb060, { 10, 10, 7}}, + {m68k_op_cmp_16_di , 0xf1f8, 0xb068, { 12, 12, 7}}, + {m68k_op_cmp_16_ix , 0xf1f8, 0xb070, { 14, 14, 9}}, + {m68k_op_cmp_32_d , 0xf1f8, 0xb080, { 6, 6, 2}}, + {m68k_op_cmp_32_a , 0xf1f8, 0xb088, { 6, 6, 2}}, + {m68k_op_cmp_32_ai , 0xf1f8, 0xb090, { 14, 14, 6}}, + {m68k_op_cmp_32_pi , 0xf1f8, 0xb098, { 14, 14, 6}}, + {m68k_op_cmp_32_pd , 0xf1f8, 0xb0a0, { 16, 16, 7}}, + {m68k_op_cmp_32_di , 0xf1f8, 0xb0a8, { 18, 18, 7}}, + {m68k_op_cmp_32_ix , 0xf1f8, 0xb0b0, { 20, 20, 9}}, + {m68k_op_cmpa_16_d , 0xf1f8, 0xb0c0, { 6, 6, 4}}, + {m68k_op_cmpa_16_a , 0xf1f8, 0xb0c8, { 6, 6, 4}}, + {m68k_op_cmpa_16_ai , 0xf1f8, 0xb0d0, { 10, 10, 8}}, + {m68k_op_cmpa_16_pi , 0xf1f8, 0xb0d8, { 10, 10, 8}}, + {m68k_op_cmpa_16_pd , 0xf1f8, 0xb0e0, { 12, 12, 9}}, + {m68k_op_cmpa_16_di , 0xf1f8, 0xb0e8, { 14, 14, 9}}, + {m68k_op_cmpa_16_ix , 0xf1f8, 0xb0f0, { 16, 16, 11}}, + {m68k_op_eor_8_d , 0xf1f8, 0xb100, { 4, 4, 2}}, + {m68k_op_cmpm_8 , 0xf1f8, 0xb108, { 12, 12, 9}}, + {m68k_op_eor_8_ai , 0xf1f8, 0xb110, { 12, 12, 8}}, + {m68k_op_eor_8_pi , 0xf1f8, 0xb118, { 12, 12, 8}}, + {m68k_op_eor_8_pd , 0xf1f8, 0xb120, { 14, 14, 9}}, + {m68k_op_eor_8_di , 0xf1f8, 0xb128, { 16, 16, 9}}, + {m68k_op_eor_8_ix , 0xf1f8, 0xb130, { 18, 18, 11}}, + {m68k_op_eor_16_d , 0xf1f8, 0xb140, { 4, 4, 2}}, + {m68k_op_cmpm_16 , 0xf1f8, 0xb148, { 12, 12, 9}}, + {m68k_op_eor_16_ai , 0xf1f8, 0xb150, { 12, 12, 8}}, + {m68k_op_eor_16_pi , 0xf1f8, 0xb158, { 12, 12, 8}}, + {m68k_op_eor_16_pd , 0xf1f8, 0xb160, { 14, 14, 9}}, + {m68k_op_eor_16_di , 0xf1f8, 0xb168, { 16, 16, 9}}, + {m68k_op_eor_16_ix , 0xf1f8, 0xb170, { 18, 18, 11}}, + {m68k_op_eor_32_d , 0xf1f8, 0xb180, { 8, 6, 2}}, + {m68k_op_cmpm_32 , 0xf1f8, 0xb188, { 20, 20, 9}}, + {m68k_op_eor_32_ai , 0xf1f8, 0xb190, { 20, 20, 8}}, + {m68k_op_eor_32_pi , 0xf1f8, 0xb198, { 20, 20, 8}}, + {m68k_op_eor_32_pd , 0xf1f8, 0xb1a0, { 22, 22, 9}}, + {m68k_op_eor_32_di , 0xf1f8, 0xb1a8, { 24, 24, 9}}, + {m68k_op_eor_32_ix , 0xf1f8, 0xb1b0, { 26, 26, 11}}, + {m68k_op_cmpa_32_d , 0xf1f8, 0xb1c0, { 6, 6, 4}}, + {m68k_op_cmpa_32_a , 0xf1f8, 0xb1c8, { 6, 6, 4}}, + {m68k_op_cmpa_32_ai , 0xf1f8, 0xb1d0, { 14, 14, 8}}, + {m68k_op_cmpa_32_pi , 0xf1f8, 0xb1d8, { 14, 14, 8}}, + {m68k_op_cmpa_32_pd , 0xf1f8, 0xb1e0, { 16, 16, 9}}, + {m68k_op_cmpa_32_di , 0xf1f8, 0xb1e8, { 18, 18, 9}}, + {m68k_op_cmpa_32_ix , 0xf1f8, 0xb1f0, { 20, 20, 11}}, + {m68k_op_and_8_er_d , 0xf1f8, 0xc000, { 4, 4, 2}}, + {m68k_op_and_8_er_ai , 0xf1f8, 0xc010, { 8, 8, 6}}, + {m68k_op_and_8_er_pi , 0xf1f8, 0xc018, { 8, 8, 6}}, + {m68k_op_and_8_er_pd , 0xf1f8, 0xc020, { 10, 10, 7}}, + {m68k_op_and_8_er_di , 0xf1f8, 0xc028, { 12, 12, 7}}, + {m68k_op_and_8_er_ix , 0xf1f8, 0xc030, { 14, 14, 9}}, + {m68k_op_and_16_er_d , 0xf1f8, 0xc040, { 4, 4, 2}}, + {m68k_op_and_16_er_ai , 0xf1f8, 0xc050, { 8, 8, 6}}, + {m68k_op_and_16_er_pi , 0xf1f8, 0xc058, { 8, 8, 6}}, + {m68k_op_and_16_er_pd , 0xf1f8, 0xc060, { 10, 10, 7}}, + {m68k_op_and_16_er_di , 0xf1f8, 0xc068, { 12, 12, 7}}, + {m68k_op_and_16_er_ix , 0xf1f8, 0xc070, { 14, 14, 9}}, + {m68k_op_and_32_er_d , 0xf1f8, 0xc080, { 6, 6, 2}}, + {m68k_op_and_32_er_ai , 0xf1f8, 0xc090, { 14, 14, 6}}, + {m68k_op_and_32_er_pi , 0xf1f8, 0xc098, { 14, 14, 6}}, + {m68k_op_and_32_er_pd , 0xf1f8, 0xc0a0, { 16, 16, 7}}, + {m68k_op_and_32_er_di , 0xf1f8, 0xc0a8, { 18, 18, 7}}, + {m68k_op_and_32_er_ix , 0xf1f8, 0xc0b0, { 20, 20, 9}}, + {m68k_op_mulu_16_d , 0xf1f8, 0xc0c0, { 54, 30, 27}}, + {m68k_op_mulu_16_ai , 0xf1f8, 0xc0d0, { 58, 34, 31}}, + {m68k_op_mulu_16_pi , 0xf1f8, 0xc0d8, { 58, 34, 31}}, + {m68k_op_mulu_16_pd , 0xf1f8, 0xc0e0, { 60, 36, 32}}, + {m68k_op_mulu_16_di , 0xf1f8, 0xc0e8, { 62, 38, 32}}, + {m68k_op_mulu_16_ix , 0xf1f8, 0xc0f0, { 64, 40, 34}}, + {m68k_op_abcd_8_rr , 0xf1f8, 0xc100, { 6, 6, 4}}, + {m68k_op_abcd_8_mm , 0xf1f8, 0xc108, { 18, 18, 16}}, + {m68k_op_and_8_re_ai , 0xf1f8, 0xc110, { 12, 12, 8}}, + {m68k_op_and_8_re_pi , 0xf1f8, 0xc118, { 12, 12, 8}}, + {m68k_op_and_8_re_pd , 0xf1f8, 0xc120, { 14, 14, 9}}, + {m68k_op_and_8_re_di , 0xf1f8, 0xc128, { 16, 16, 9}}, + {m68k_op_and_8_re_ix , 0xf1f8, 0xc130, { 18, 18, 11}}, + {m68k_op_exg_32_dd , 0xf1f8, 0xc140, { 6, 6, 2}}, + {m68k_op_exg_32_aa , 0xf1f8, 0xc148, { 6, 6, 2}}, + {m68k_op_and_16_re_ai , 0xf1f8, 0xc150, { 12, 12, 8}}, + {m68k_op_and_16_re_pi , 0xf1f8, 0xc158, { 12, 12, 8}}, + {m68k_op_and_16_re_pd , 0xf1f8, 0xc160, { 14, 14, 9}}, + {m68k_op_and_16_re_di , 0xf1f8, 0xc168, { 16, 16, 9}}, + {m68k_op_and_16_re_ix , 0xf1f8, 0xc170, { 18, 18, 11}}, + {m68k_op_exg_32_da , 0xf1f8, 0xc188, { 6, 6, 2}}, + {m68k_op_and_32_re_ai , 0xf1f8, 0xc190, { 20, 20, 8}}, + {m68k_op_and_32_re_pi , 0xf1f8, 0xc198, { 20, 20, 8}}, + {m68k_op_and_32_re_pd , 0xf1f8, 0xc1a0, { 22, 22, 9}}, + {m68k_op_and_32_re_di , 0xf1f8, 0xc1a8, { 24, 24, 9}}, + {m68k_op_and_32_re_ix , 0xf1f8, 0xc1b0, { 26, 26, 11}}, + {m68k_op_muls_16_d , 0xf1f8, 0xc1c0, { 54, 32, 27}}, + {m68k_op_muls_16_ai , 0xf1f8, 0xc1d0, { 58, 36, 31}}, + {m68k_op_muls_16_pi , 0xf1f8, 0xc1d8, { 58, 36, 31}}, + {m68k_op_muls_16_pd , 0xf1f8, 0xc1e0, { 60, 38, 32}}, + {m68k_op_muls_16_di , 0xf1f8, 0xc1e8, { 62, 40, 32}}, + {m68k_op_muls_16_ix , 0xf1f8, 0xc1f0, { 64, 42, 34}}, + {m68k_op_add_8_er_d , 0xf1f8, 0xd000, { 4, 4, 2}}, + {m68k_op_add_8_er_ai , 0xf1f8, 0xd010, { 8, 8, 6}}, + {m68k_op_add_8_er_pi , 0xf1f8, 0xd018, { 8, 8, 6}}, + {m68k_op_add_8_er_pd , 0xf1f8, 0xd020, { 10, 10, 7}}, + {m68k_op_add_8_er_di , 0xf1f8, 0xd028, { 12, 12, 7}}, + {m68k_op_add_8_er_ix , 0xf1f8, 0xd030, { 14, 14, 9}}, + {m68k_op_add_16_er_d , 0xf1f8, 0xd040, { 4, 4, 2}}, + {m68k_op_add_16_er_a , 0xf1f8, 0xd048, { 4, 4, 2}}, + {m68k_op_add_16_er_ai , 0xf1f8, 0xd050, { 8, 8, 6}}, + {m68k_op_add_16_er_pi , 0xf1f8, 0xd058, { 8, 8, 6}}, + {m68k_op_add_16_er_pd , 0xf1f8, 0xd060, { 10, 10, 7}}, + {m68k_op_add_16_er_di , 0xf1f8, 0xd068, { 12, 12, 7}}, + {m68k_op_add_16_er_ix , 0xf1f8, 0xd070, { 14, 14, 9}}, + {m68k_op_add_32_er_d , 0xf1f8, 0xd080, { 6, 6, 2}}, + {m68k_op_add_32_er_a , 0xf1f8, 0xd088, { 6, 6, 2}}, + {m68k_op_add_32_er_ai , 0xf1f8, 0xd090, { 14, 14, 6}}, + {m68k_op_add_32_er_pi , 0xf1f8, 0xd098, { 14, 14, 6}}, + {m68k_op_add_32_er_pd , 0xf1f8, 0xd0a0, { 16, 16, 7}}, + {m68k_op_add_32_er_di , 0xf1f8, 0xd0a8, { 18, 18, 7}}, + {m68k_op_add_32_er_ix , 0xf1f8, 0xd0b0, { 20, 20, 9}}, + {m68k_op_adda_16_d , 0xf1f8, 0xd0c0, { 8, 8, 2}}, + {m68k_op_adda_16_a , 0xf1f8, 0xd0c8, { 8, 8, 2}}, + {m68k_op_adda_16_ai , 0xf1f8, 0xd0d0, { 12, 12, 6}}, + {m68k_op_adda_16_pi , 0xf1f8, 0xd0d8, { 12, 12, 6}}, + {m68k_op_adda_16_pd , 0xf1f8, 0xd0e0, { 14, 14, 7}}, + {m68k_op_adda_16_di , 0xf1f8, 0xd0e8, { 16, 16, 7}}, + {m68k_op_adda_16_ix , 0xf1f8, 0xd0f0, { 18, 18, 9}}, + {m68k_op_addx_8_rr , 0xf1f8, 0xd100, { 4, 4, 2}}, + {m68k_op_addx_8_mm , 0xf1f8, 0xd108, { 18, 18, 12}}, + {m68k_op_add_8_re_ai , 0xf1f8, 0xd110, { 12, 12, 8}}, + {m68k_op_add_8_re_pi , 0xf1f8, 0xd118, { 12, 12, 8}}, + {m68k_op_add_8_re_pd , 0xf1f8, 0xd120, { 14, 14, 9}}, + {m68k_op_add_8_re_di , 0xf1f8, 0xd128, { 16, 16, 9}}, + {m68k_op_add_8_re_ix , 0xf1f8, 0xd130, { 18, 18, 11}}, + {m68k_op_addx_16_rr , 0xf1f8, 0xd140, { 4, 4, 2}}, + {m68k_op_addx_16_mm , 0xf1f8, 0xd148, { 18, 18, 12}}, + {m68k_op_add_16_re_ai , 0xf1f8, 0xd150, { 12, 12, 8}}, + {m68k_op_add_16_re_pi , 0xf1f8, 0xd158, { 12, 12, 8}}, + {m68k_op_add_16_re_pd , 0xf1f8, 0xd160, { 14, 14, 9}}, + {m68k_op_add_16_re_di , 0xf1f8, 0xd168, { 16, 16, 9}}, + {m68k_op_add_16_re_ix , 0xf1f8, 0xd170, { 18, 18, 11}}, + {m68k_op_addx_32_rr , 0xf1f8, 0xd180, { 8, 6, 2}}, + {m68k_op_addx_32_mm , 0xf1f8, 0xd188, { 30, 30, 12}}, + {m68k_op_add_32_re_ai , 0xf1f8, 0xd190, { 20, 20, 8}}, + {m68k_op_add_32_re_pi , 0xf1f8, 0xd198, { 20, 20, 8}}, + {m68k_op_add_32_re_pd , 0xf1f8, 0xd1a0, { 22, 22, 9}}, + {m68k_op_add_32_re_di , 0xf1f8, 0xd1a8, { 24, 24, 9}}, + {m68k_op_add_32_re_ix , 0xf1f8, 0xd1b0, { 26, 26, 11}}, + {m68k_op_adda_32_d , 0xf1f8, 0xd1c0, { 6, 6, 2}}, + {m68k_op_adda_32_a , 0xf1f8, 0xd1c8, { 6, 6, 2}}, + {m68k_op_adda_32_ai , 0xf1f8, 0xd1d0, { 14, 14, 6}}, + {m68k_op_adda_32_pi , 0xf1f8, 0xd1d8, { 14, 14, 6}}, + {m68k_op_adda_32_pd , 0xf1f8, 0xd1e0, { 16, 16, 7}}, + {m68k_op_adda_32_di , 0xf1f8, 0xd1e8, { 18, 18, 7}}, + {m68k_op_adda_32_ix , 0xf1f8, 0xd1f0, { 20, 20, 9}}, + {m68k_op_asr_8_s , 0xf1f8, 0xe000, { 6, 6, 6}}, + {m68k_op_lsr_8_s , 0xf1f8, 0xe008, { 6, 6, 4}}, + {m68k_op_roxr_8_s , 0xf1f8, 0xe010, { 6, 6, 12}}, + {m68k_op_ror_8_s , 0xf1f8, 0xe018, { 6, 6, 8}}, + {m68k_op_asr_8_r , 0xf1f8, 0xe020, { 6, 6, 6}}, + {m68k_op_lsr_8_r , 0xf1f8, 0xe028, { 6, 6, 6}}, + {m68k_op_roxr_8_r , 0xf1f8, 0xe030, { 6, 6, 12}}, + {m68k_op_ror_8_r , 0xf1f8, 0xe038, { 6, 6, 8}}, + {m68k_op_asr_16_s , 0xf1f8, 0xe040, { 6, 6, 6}}, + {m68k_op_lsr_16_s , 0xf1f8, 0xe048, { 6, 6, 4}}, + {m68k_op_roxr_16_s , 0xf1f8, 0xe050, { 6, 6, 12}}, + {m68k_op_ror_16_s , 0xf1f8, 0xe058, { 6, 6, 8}}, + {m68k_op_asr_16_r , 0xf1f8, 0xe060, { 6, 6, 6}}, + {m68k_op_lsr_16_r , 0xf1f8, 0xe068, { 6, 6, 6}}, + {m68k_op_roxr_16_r , 0xf1f8, 0xe070, { 6, 6, 12}}, + {m68k_op_ror_16_r , 0xf1f8, 0xe078, { 6, 6, 8}}, + {m68k_op_asr_32_s , 0xf1f8, 0xe080, { 8, 8, 6}}, + {m68k_op_lsr_32_s , 0xf1f8, 0xe088, { 8, 8, 4}}, + {m68k_op_roxr_32_s , 0xf1f8, 0xe090, { 8, 8, 12}}, + {m68k_op_ror_32_s , 0xf1f8, 0xe098, { 8, 8, 8}}, + {m68k_op_asr_32_r , 0xf1f8, 0xe0a0, { 8, 8, 6}}, + {m68k_op_lsr_32_r , 0xf1f8, 0xe0a8, { 8, 8, 6}}, + {m68k_op_roxr_32_r , 0xf1f8, 0xe0b0, { 8, 8, 12}}, + {m68k_op_ror_32_r , 0xf1f8, 0xe0b8, { 8, 8, 8}}, + {m68k_op_asl_8_s , 0xf1f8, 0xe100, { 6, 6, 8}}, + {m68k_op_lsl_8_s , 0xf1f8, 0xe108, { 6, 6, 4}}, + {m68k_op_roxl_8_s , 0xf1f8, 0xe110, { 6, 6, 12}}, + {m68k_op_rol_8_s , 0xf1f8, 0xe118, { 6, 6, 8}}, + {m68k_op_asl_8_r , 0xf1f8, 0xe120, { 6, 6, 8}}, + {m68k_op_lsl_8_r , 0xf1f8, 0xe128, { 6, 6, 6}}, + {m68k_op_roxl_8_r , 0xf1f8, 0xe130, { 6, 6, 12}}, + {m68k_op_rol_8_r , 0xf1f8, 0xe138, { 6, 6, 8}}, + {m68k_op_asl_16_s , 0xf1f8, 0xe140, { 6, 6, 8}}, + {m68k_op_lsl_16_s , 0xf1f8, 0xe148, { 6, 6, 4}}, + {m68k_op_roxl_16_s , 0xf1f8, 0xe150, { 6, 6, 12}}, + {m68k_op_rol_16_s , 0xf1f8, 0xe158, { 6, 6, 8}}, + {m68k_op_asl_16_r , 0xf1f8, 0xe160, { 6, 6, 8}}, + {m68k_op_lsl_16_r , 0xf1f8, 0xe168, { 6, 6, 6}}, + {m68k_op_roxl_16_r , 0xf1f8, 0xe170, { 6, 6, 12}}, + {m68k_op_rol_16_r , 0xf1f8, 0xe178, { 6, 6, 8}}, + {m68k_op_asl_32_s , 0xf1f8, 0xe180, { 8, 8, 8}}, + {m68k_op_lsl_32_s , 0xf1f8, 0xe188, { 8, 8, 4}}, + {m68k_op_roxl_32_s , 0xf1f8, 0xe190, { 8, 8, 12}}, + {m68k_op_rol_32_s , 0xf1f8, 0xe198, { 8, 8, 8}}, + {m68k_op_asl_32_r , 0xf1f8, 0xe1a0, { 8, 8, 8}}, + {m68k_op_lsl_32_r , 0xf1f8, 0xe1a8, { 8, 8, 6}}, + {m68k_op_roxl_32_r , 0xf1f8, 0xe1b0, { 8, 8, 12}}, + {m68k_op_rol_32_r , 0xf1f8, 0xe1b8, { 8, 8, 8}}, + {m68k_op_cpdbcc_32 , 0xf1f8, 0xf048, { 0, 0, 4}}, + {m68k_op_cptrapcc_32 , 0xf1f8, 0xf078, { 0, 0, 4}}, + {m68k_op_rtm_32 , 0xfff0, 0x06c0, { 0, 0, 19}}, + {m68k_op_trap , 0xfff0, 0x4e40, { 4, 4, 4}}, + {m68k_op_btst_8_r_pi7 , 0xf1ff, 0x011f, { 8, 8, 8}}, + {m68k_op_btst_8_r_pd7 , 0xf1ff, 0x0127, { 10, 10, 9}}, + {m68k_op_btst_8_r_aw , 0xf1ff, 0x0138, { 12, 12, 8}}, + {m68k_op_btst_8_r_al , 0xf1ff, 0x0139, { 16, 16, 8}}, + {m68k_op_btst_8_r_pcdi , 0xf1ff, 0x013a, { 12, 12, 9}}, + {m68k_op_btst_8_r_pcix , 0xf1ff, 0x013b, { 14, 14, 11}}, + {m68k_op_btst_8_r_i , 0xf1ff, 0x013c, { 8, 8, 6}}, + {m68k_op_bchg_8_r_pi7 , 0xf1ff, 0x015f, { 12, 12, 8}}, + {m68k_op_bchg_8_r_pd7 , 0xf1ff, 0x0167, { 14, 14, 9}}, + {m68k_op_bchg_8_r_aw , 0xf1ff, 0x0178, { 16, 16, 8}}, + {m68k_op_bchg_8_r_al , 0xf1ff, 0x0179, { 20, 20, 8}}, + {m68k_op_bclr_8_r_pi7 , 0xf1ff, 0x019f, { 12, 14, 8}}, + {m68k_op_bclr_8_r_pd7 , 0xf1ff, 0x01a7, { 14, 16, 9}}, + {m68k_op_bclr_8_r_aw , 0xf1ff, 0x01b8, { 16, 18, 8}}, + {m68k_op_bclr_8_r_al , 0xf1ff, 0x01b9, { 20, 22, 8}}, + {m68k_op_bset_8_r_pi7 , 0xf1ff, 0x01df, { 12, 12, 8}}, + {m68k_op_bset_8_r_pd7 , 0xf1ff, 0x01e7, { 14, 14, 9}}, + {m68k_op_bset_8_r_aw , 0xf1ff, 0x01f8, { 16, 16, 8}}, + {m68k_op_bset_8_r_al , 0xf1ff, 0x01f9, { 20, 20, 8}}, + {m68k_op_move_8_d_pi7 , 0xf1ff, 0x101f, { 8, 8, 6}}, + {m68k_op_move_8_d_pd7 , 0xf1ff, 0x1027, { 10, 10, 7}}, + {m68k_op_move_8_d_aw , 0xf1ff, 0x1038, { 12, 12, 6}}, + {m68k_op_move_8_d_al , 0xf1ff, 0x1039, { 16, 16, 6}}, + {m68k_op_move_8_d_pcdi , 0xf1ff, 0x103a, { 12, 12, 7}}, + {m68k_op_move_8_d_pcix , 0xf1ff, 0x103b, { 14, 14, 9}}, + {m68k_op_move_8_d_i , 0xf1ff, 0x103c, { 8, 8, 4}}, + {m68k_op_move_8_ai_pi7 , 0xf1ff, 0x109f, { 12, 12, 8}}, + {m68k_op_move_8_ai_pd7 , 0xf1ff, 0x10a7, { 14, 14, 9}}, + {m68k_op_move_8_ai_aw , 0xf1ff, 0x10b8, { 16, 16, 8}}, + {m68k_op_move_8_ai_al , 0xf1ff, 0x10b9, { 20, 20, 8}}, + {m68k_op_move_8_ai_pcdi , 0xf1ff, 0x10ba, { 16, 16, 9}}, + {m68k_op_move_8_ai_pcix , 0xf1ff, 0x10bb, { 18, 18, 11}}, + {m68k_op_move_8_ai_i , 0xf1ff, 0x10bc, { 12, 12, 6}}, + {m68k_op_move_8_pi_pi7 , 0xf1ff, 0x10df, { 12, 12, 8}}, + {m68k_op_move_8_pi_pd7 , 0xf1ff, 0x10e7, { 14, 14, 9}}, + {m68k_op_move_8_pi_aw , 0xf1ff, 0x10f8, { 16, 16, 8}}, + {m68k_op_move_8_pi_al , 0xf1ff, 0x10f9, { 20, 20, 8}}, + {m68k_op_move_8_pi_pcdi , 0xf1ff, 0x10fa, { 16, 16, 9}}, + {m68k_op_move_8_pi_pcix , 0xf1ff, 0x10fb, { 18, 18, 11}}, + {m68k_op_move_8_pi_i , 0xf1ff, 0x10fc, { 12, 12, 6}}, + {m68k_op_move_8_pd_pi7 , 0xf1ff, 0x111f, { 12, 12, 9}}, + {m68k_op_move_8_pd_pd7 , 0xf1ff, 0x1127, { 14, 14, 10}}, + {m68k_op_move_8_pd_aw , 0xf1ff, 0x1138, { 16, 16, 9}}, + {m68k_op_move_8_pd_al , 0xf1ff, 0x1139, { 20, 20, 9}}, + {m68k_op_move_8_pd_pcdi , 0xf1ff, 0x113a, { 16, 16, 10}}, + {m68k_op_move_8_pd_pcix , 0xf1ff, 0x113b, { 18, 18, 12}}, + {m68k_op_move_8_pd_i , 0xf1ff, 0x113c, { 12, 12, 7}}, + {m68k_op_move_8_di_pi7 , 0xf1ff, 0x115f, { 16, 16, 9}}, + {m68k_op_move_8_di_pd7 , 0xf1ff, 0x1167, { 18, 18, 10}}, + {m68k_op_move_8_di_aw , 0xf1ff, 0x1178, { 20, 20, 9}}, + {m68k_op_move_8_di_al , 0xf1ff, 0x1179, { 24, 24, 9}}, + {m68k_op_move_8_di_pcdi , 0xf1ff, 0x117a, { 20, 20, 10}}, + {m68k_op_move_8_di_pcix , 0xf1ff, 0x117b, { 22, 22, 12}}, + {m68k_op_move_8_di_i , 0xf1ff, 0x117c, { 16, 16, 7}}, + {m68k_op_move_8_ix_pi7 , 0xf1ff, 0x119f, { 18, 18, 11}}, + {m68k_op_move_8_ix_pd7 , 0xf1ff, 0x11a7, { 20, 20, 12}}, + {m68k_op_move_8_ix_aw , 0xf1ff, 0x11b8, { 22, 22, 11}}, + {m68k_op_move_8_ix_al , 0xf1ff, 0x11b9, { 26, 26, 11}}, + {m68k_op_move_8_ix_pcdi , 0xf1ff, 0x11ba, { 22, 22, 12}}, + {m68k_op_move_8_ix_pcix , 0xf1ff, 0x11bb, { 24, 24, 14}}, + {m68k_op_move_8_ix_i , 0xf1ff, 0x11bc, { 18, 18, 9}}, + {m68k_op_move_32_d_aw , 0xf1ff, 0x2038, { 16, 16, 6}}, + {m68k_op_move_32_d_al , 0xf1ff, 0x2039, { 20, 20, 6}}, + {m68k_op_move_32_d_pcdi , 0xf1ff, 0x203a, { 16, 16, 7}}, + {m68k_op_move_32_d_pcix , 0xf1ff, 0x203b, { 18, 18, 9}}, + {m68k_op_move_32_d_i , 0xf1ff, 0x203c, { 12, 12, 6}}, + {m68k_op_movea_32_aw , 0xf1ff, 0x2078, { 16, 16, 6}}, + {m68k_op_movea_32_al , 0xf1ff, 0x2079, { 20, 20, 6}}, + {m68k_op_movea_32_pcdi , 0xf1ff, 0x207a, { 16, 16, 7}}, + {m68k_op_movea_32_pcix , 0xf1ff, 0x207b, { 18, 18, 9}}, + {m68k_op_movea_32_i , 0xf1ff, 0x207c, { 12, 12, 6}}, + {m68k_op_move_32_ai_aw , 0xf1ff, 0x20b8, { 24, 24, 8}}, + {m68k_op_move_32_ai_al , 0xf1ff, 0x20b9, { 28, 28, 8}}, + {m68k_op_move_32_ai_pcdi , 0xf1ff, 0x20ba, { 24, 24, 9}}, + {m68k_op_move_32_ai_pcix , 0xf1ff, 0x20bb, { 26, 26, 11}}, + {m68k_op_move_32_ai_i , 0xf1ff, 0x20bc, { 20, 20, 8}}, + {m68k_op_move_32_pi_aw , 0xf1ff, 0x20f8, { 24, 24, 8}}, + {m68k_op_move_32_pi_al , 0xf1ff, 0x20f9, { 28, 28, 8}}, + {m68k_op_move_32_pi_pcdi , 0xf1ff, 0x20fa, { 24, 24, 9}}, + {m68k_op_move_32_pi_pcix , 0xf1ff, 0x20fb, { 26, 26, 11}}, + {m68k_op_move_32_pi_i , 0xf1ff, 0x20fc, { 20, 20, 8}}, + {m68k_op_move_32_pd_aw , 0xf1ff, 0x2138, { 24, 26, 9}}, + {m68k_op_move_32_pd_al , 0xf1ff, 0x2139, { 28, 30, 9}}, + {m68k_op_move_32_pd_pcdi , 0xf1ff, 0x213a, { 24, 26, 10}}, + {m68k_op_move_32_pd_pcix , 0xf1ff, 0x213b, { 26, 28, 12}}, + {m68k_op_move_32_pd_i , 0xf1ff, 0x213c, { 20, 22, 9}}, + {m68k_op_move_32_di_aw , 0xf1ff, 0x2178, { 28, 28, 9}}, + {m68k_op_move_32_di_al , 0xf1ff, 0x2179, { 32, 32, 9}}, + {m68k_op_move_32_di_pcdi , 0xf1ff, 0x217a, { 28, 28, 10}}, + {m68k_op_move_32_di_pcix , 0xf1ff, 0x217b, { 30, 30, 12}}, + {m68k_op_move_32_di_i , 0xf1ff, 0x217c, { 24, 24, 9}}, + {m68k_op_move_32_ix_aw , 0xf1ff, 0x21b8, { 30, 30, 11}}, + {m68k_op_move_32_ix_al , 0xf1ff, 0x21b9, { 34, 34, 11}}, + {m68k_op_move_32_ix_pcdi , 0xf1ff, 0x21ba, { 30, 30, 12}}, + {m68k_op_move_32_ix_pcix , 0xf1ff, 0x21bb, { 32, 32, 14}}, + {m68k_op_move_32_ix_i , 0xf1ff, 0x21bc, { 26, 26, 11}}, + {m68k_op_move_16_d_aw , 0xf1ff, 0x3038, { 12, 12, 6}}, + {m68k_op_move_16_d_al , 0xf1ff, 0x3039, { 16, 16, 6}}, + {m68k_op_move_16_d_pcdi , 0xf1ff, 0x303a, { 12, 12, 7}}, + {m68k_op_move_16_d_pcix , 0xf1ff, 0x303b, { 14, 14, 9}}, + {m68k_op_move_16_d_i , 0xf1ff, 0x303c, { 8, 8, 4}}, + {m68k_op_movea_16_aw , 0xf1ff, 0x3078, { 12, 12, 6}}, + {m68k_op_movea_16_al , 0xf1ff, 0x3079, { 16, 16, 6}}, + {m68k_op_movea_16_pcdi , 0xf1ff, 0x307a, { 12, 12, 7}}, + {m68k_op_movea_16_pcix , 0xf1ff, 0x307b, { 14, 14, 9}}, + {m68k_op_movea_16_i , 0xf1ff, 0x307c, { 8, 8, 4}}, + {m68k_op_move_16_ai_aw , 0xf1ff, 0x30b8, { 16, 16, 8}}, + {m68k_op_move_16_ai_al , 0xf1ff, 0x30b9, { 20, 20, 8}}, + {m68k_op_move_16_ai_pcdi , 0xf1ff, 0x30ba, { 16, 16, 9}}, + {m68k_op_move_16_ai_pcix , 0xf1ff, 0x30bb, { 18, 18, 11}}, + {m68k_op_move_16_ai_i , 0xf1ff, 0x30bc, { 12, 12, 6}}, + {m68k_op_move_16_pi_aw , 0xf1ff, 0x30f8, { 16, 16, 8}}, + {m68k_op_move_16_pi_al , 0xf1ff, 0x30f9, { 20, 20, 8}}, + {m68k_op_move_16_pi_pcdi , 0xf1ff, 0x30fa, { 16, 16, 9}}, + {m68k_op_move_16_pi_pcix , 0xf1ff, 0x30fb, { 18, 18, 11}}, + {m68k_op_move_16_pi_i , 0xf1ff, 0x30fc, { 12, 12, 6}}, + {m68k_op_move_16_pd_aw , 0xf1ff, 0x3138, { 16, 16, 9}}, + {m68k_op_move_16_pd_al , 0xf1ff, 0x3139, { 20, 20, 9}}, + {m68k_op_move_16_pd_pcdi , 0xf1ff, 0x313a, { 16, 16, 10}}, + {m68k_op_move_16_pd_pcix , 0xf1ff, 0x313b, { 18, 18, 12}}, + {m68k_op_move_16_pd_i , 0xf1ff, 0x313c, { 12, 12, 7}}, + {m68k_op_move_16_di_aw , 0xf1ff, 0x3178, { 20, 20, 9}}, + {m68k_op_move_16_di_al , 0xf1ff, 0x3179, { 24, 24, 9}}, + {m68k_op_move_16_di_pcdi , 0xf1ff, 0x317a, { 20, 20, 10}}, + {m68k_op_move_16_di_pcix , 0xf1ff, 0x317b, { 22, 22, 12}}, + {m68k_op_move_16_di_i , 0xf1ff, 0x317c, { 16, 16, 7}}, + {m68k_op_move_16_ix_aw , 0xf1ff, 0x31b8, { 22, 22, 11}}, + {m68k_op_move_16_ix_al , 0xf1ff, 0x31b9, { 26, 26, 11}}, + {m68k_op_move_16_ix_pcdi , 0xf1ff, 0x31ba, { 22, 22, 12}}, + {m68k_op_move_16_ix_pcix , 0xf1ff, 0x31bb, { 24, 24, 14}}, + {m68k_op_move_16_ix_i , 0xf1ff, 0x31bc, { 18, 18, 9}}, + {m68k_op_chk_32_aw , 0xf1ff, 0x4138, { 0, 0, 12}}, + {m68k_op_chk_32_al , 0xf1ff, 0x4139, { 0, 0, 12}}, + {m68k_op_chk_32_pcdi , 0xf1ff, 0x413a, { 0, 0, 13}}, + {m68k_op_chk_32_pcix , 0xf1ff, 0x413b, { 0, 0, 15}}, + {m68k_op_chk_32_i , 0xf1ff, 0x413c, { 0, 0, 12}}, + {m68k_op_chk_16_aw , 0xf1ff, 0x41b8, { 18, 16, 12}}, + {m68k_op_chk_16_al , 0xf1ff, 0x41b9, { 22, 20, 12}}, + {m68k_op_chk_16_pcdi , 0xf1ff, 0x41ba, { 18, 16, 13}}, + {m68k_op_chk_16_pcix , 0xf1ff, 0x41bb, { 20, 18, 15}}, + {m68k_op_chk_16_i , 0xf1ff, 0x41bc, { 14, 12, 10}}, + {m68k_op_lea_32_aw , 0xf1ff, 0x41f8, { 8, 8, 6}}, + {m68k_op_lea_32_al , 0xf1ff, 0x41f9, { 12, 12, 6}}, + {m68k_op_lea_32_pcdi , 0xf1ff, 0x41fa, { 8, 8, 7}}, + {m68k_op_lea_32_pcix , 0xf1ff, 0x41fb, { 12, 12, 9}}, + {m68k_op_addq_8_pi7 , 0xf1ff, 0x501f, { 12, 12, 8}}, + {m68k_op_addq_8_pd7 , 0xf1ff, 0x5027, { 14, 14, 9}}, + {m68k_op_addq_8_aw , 0xf1ff, 0x5038, { 16, 16, 8}}, + {m68k_op_addq_8_al , 0xf1ff, 0x5039, { 20, 20, 8}}, + {m68k_op_addq_16_aw , 0xf1ff, 0x5078, { 16, 16, 8}}, + {m68k_op_addq_16_al , 0xf1ff, 0x5079, { 20, 20, 8}}, + {m68k_op_addq_32_aw , 0xf1ff, 0x50b8, { 24, 24, 8}}, + {m68k_op_addq_32_al , 0xf1ff, 0x50b9, { 28, 28, 8}}, + {m68k_op_subq_8_pi7 , 0xf1ff, 0x511f, { 12, 12, 8}}, + {m68k_op_subq_8_pd7 , 0xf1ff, 0x5127, { 14, 14, 9}}, + {m68k_op_subq_8_aw , 0xf1ff, 0x5138, { 16, 16, 8}}, + {m68k_op_subq_8_al , 0xf1ff, 0x5139, { 20, 20, 8}}, + {m68k_op_subq_16_aw , 0xf1ff, 0x5178, { 16, 16, 8}}, + {m68k_op_subq_16_al , 0xf1ff, 0x5179, { 20, 20, 8}}, + {m68k_op_subq_32_aw , 0xf1ff, 0x51b8, { 24, 24, 8}}, + {m68k_op_subq_32_al , 0xf1ff, 0x51b9, { 28, 28, 8}}, + {m68k_op_or_8_er_pi7 , 0xf1ff, 0x801f, { 8, 8, 6}}, + {m68k_op_or_8_er_pd7 , 0xf1ff, 0x8027, { 10, 10, 7}}, + {m68k_op_or_8_er_aw , 0xf1ff, 0x8038, { 12, 12, 6}}, + {m68k_op_or_8_er_al , 0xf1ff, 0x8039, { 16, 16, 6}}, + {m68k_op_or_8_er_pcdi , 0xf1ff, 0x803a, { 12, 12, 7}}, + {m68k_op_or_8_er_pcix , 0xf1ff, 0x803b, { 14, 14, 9}}, + {m68k_op_or_8_er_i , 0xf1ff, 0x803c, { 10, 8, 4}}, + {m68k_op_or_16_er_aw , 0xf1ff, 0x8078, { 12, 12, 6}}, + {m68k_op_or_16_er_al , 0xf1ff, 0x8079, { 16, 16, 6}}, + {m68k_op_or_16_er_pcdi , 0xf1ff, 0x807a, { 12, 12, 7}}, + {m68k_op_or_16_er_pcix , 0xf1ff, 0x807b, { 14, 14, 9}}, + {m68k_op_or_16_er_i , 0xf1ff, 0x807c, { 10, 8, 4}}, + {m68k_op_or_32_er_aw , 0xf1ff, 0x80b8, { 18, 18, 6}}, + {m68k_op_or_32_er_al , 0xf1ff, 0x80b9, { 22, 22, 6}}, + {m68k_op_or_32_er_pcdi , 0xf1ff, 0x80ba, { 18, 18, 7}}, + {m68k_op_or_32_er_pcix , 0xf1ff, 0x80bb, { 20, 20, 9}}, + {m68k_op_or_32_er_i , 0xf1ff, 0x80bc, { 16, 14, 6}}, + {m68k_op_divu_16_aw , 0xf1ff, 0x80f8, {148, 116, 48}}, + {m68k_op_divu_16_al , 0xf1ff, 0x80f9, {152, 120, 48}}, + {m68k_op_divu_16_pcdi , 0xf1ff, 0x80fa, {148, 116, 49}}, + {m68k_op_divu_16_pcix , 0xf1ff, 0x80fb, {150, 118, 51}}, + {m68k_op_divu_16_i , 0xf1ff, 0x80fc, {144, 112, 46}}, + {m68k_op_sbcd_8_mm_ay7 , 0xf1ff, 0x810f, { 18, 18, 16}}, + {m68k_op_or_8_re_pi7 , 0xf1ff, 0x811f, { 12, 12, 8}}, + {m68k_op_or_8_re_pd7 , 0xf1ff, 0x8127, { 14, 14, 9}}, + {m68k_op_or_8_re_aw , 0xf1ff, 0x8138, { 16, 16, 8}}, + {m68k_op_or_8_re_al , 0xf1ff, 0x8139, { 20, 20, 8}}, + {m68k_op_pack_16_mm_ay7 , 0xf1ff, 0x814f, { 0, 0, 13}}, + {m68k_op_or_16_re_aw , 0xf1ff, 0x8178, { 16, 16, 8}}, + {m68k_op_or_16_re_al , 0xf1ff, 0x8179, { 20, 20, 8}}, + {m68k_op_unpk_16_mm_ay7 , 0xf1ff, 0x818f, { 0, 0, 13}}, + {m68k_op_or_32_re_aw , 0xf1ff, 0x81b8, { 24, 24, 8}}, + {m68k_op_or_32_re_al , 0xf1ff, 0x81b9, { 28, 28, 8}}, + {m68k_op_divs_16_aw , 0xf1ff, 0x81f8, {166, 130, 60}}, + {m68k_op_divs_16_al , 0xf1ff, 0x81f9, {170, 134, 60}}, + {m68k_op_divs_16_pcdi , 0xf1ff, 0x81fa, {166, 130, 61}}, + {m68k_op_divs_16_pcix , 0xf1ff, 0x81fb, {168, 132, 63}}, + {m68k_op_divs_16_i , 0xf1ff, 0x81fc, {162, 126, 58}}, + {m68k_op_sub_8_er_pi7 , 0xf1ff, 0x901f, { 8, 8, 6}}, + {m68k_op_sub_8_er_pd7 , 0xf1ff, 0x9027, { 10, 10, 7}}, + {m68k_op_sub_8_er_aw , 0xf1ff, 0x9038, { 12, 12, 6}}, + {m68k_op_sub_8_er_al , 0xf1ff, 0x9039, { 16, 16, 6}}, + {m68k_op_sub_8_er_pcdi , 0xf1ff, 0x903a, { 12, 12, 7}}, + {m68k_op_sub_8_er_pcix , 0xf1ff, 0x903b, { 14, 14, 9}}, + {m68k_op_sub_8_er_i , 0xf1ff, 0x903c, { 10, 8, 4}}, + {m68k_op_sub_16_er_aw , 0xf1ff, 0x9078, { 12, 12, 6}}, + {m68k_op_sub_16_er_al , 0xf1ff, 0x9079, { 16, 16, 6}}, + {m68k_op_sub_16_er_pcdi , 0xf1ff, 0x907a, { 12, 12, 7}}, + {m68k_op_sub_16_er_pcix , 0xf1ff, 0x907b, { 14, 14, 9}}, + {m68k_op_sub_16_er_i , 0xf1ff, 0x907c, { 10, 8, 4}}, + {m68k_op_sub_32_er_aw , 0xf1ff, 0x90b8, { 18, 18, 6}}, + {m68k_op_sub_32_er_al , 0xf1ff, 0x90b9, { 22, 22, 6}}, + {m68k_op_sub_32_er_pcdi , 0xf1ff, 0x90ba, { 18, 18, 7}}, + {m68k_op_sub_32_er_pcix , 0xf1ff, 0x90bb, { 20, 20, 9}}, + {m68k_op_sub_32_er_i , 0xf1ff, 0x90bc, { 16, 14, 6}}, + {m68k_op_suba_16_aw , 0xf1ff, 0x90f8, { 16, 16, 6}}, + {m68k_op_suba_16_al , 0xf1ff, 0x90f9, { 20, 20, 6}}, + {m68k_op_suba_16_pcdi , 0xf1ff, 0x90fa, { 16, 16, 7}}, + {m68k_op_suba_16_pcix , 0xf1ff, 0x90fb, { 18, 18, 9}}, + {m68k_op_suba_16_i , 0xf1ff, 0x90fc, { 14, 12, 4}}, + {m68k_op_subx_8_mm_ay7 , 0xf1ff, 0x910f, { 18, 18, 12}}, + {m68k_op_sub_8_re_pi7 , 0xf1ff, 0x911f, { 12, 12, 8}}, + {m68k_op_sub_8_re_pd7 , 0xf1ff, 0x9127, { 14, 14, 9}}, + {m68k_op_sub_8_re_aw , 0xf1ff, 0x9138, { 16, 16, 8}}, + {m68k_op_sub_8_re_al , 0xf1ff, 0x9139, { 20, 20, 8}}, + {m68k_op_sub_16_re_aw , 0xf1ff, 0x9178, { 16, 16, 8}}, + {m68k_op_sub_16_re_al , 0xf1ff, 0x9179, { 20, 20, 8}}, + {m68k_op_sub_32_re_aw , 0xf1ff, 0x91b8, { 24, 24, 8}}, + {m68k_op_sub_32_re_al , 0xf1ff, 0x91b9, { 28, 28, 8}}, + {m68k_op_suba_32_aw , 0xf1ff, 0x91f8, { 18, 18, 6}}, + {m68k_op_suba_32_al , 0xf1ff, 0x91f9, { 22, 22, 6}}, + {m68k_op_suba_32_pcdi , 0xf1ff, 0x91fa, { 18, 18, 7}}, + {m68k_op_suba_32_pcix , 0xf1ff, 0x91fb, { 20, 20, 9}}, + {m68k_op_suba_32_i , 0xf1ff, 0x91fc, { 16, 14, 6}}, + {m68k_op_cmp_8_pi7 , 0xf1ff, 0xb01f, { 8, 8, 6}}, + {m68k_op_cmp_8_pd7 , 0xf1ff, 0xb027, { 10, 10, 7}}, + {m68k_op_cmp_8_aw , 0xf1ff, 0xb038, { 12, 12, 6}}, + {m68k_op_cmp_8_al , 0xf1ff, 0xb039, { 16, 16, 6}}, + {m68k_op_cmp_8_pcdi , 0xf1ff, 0xb03a, { 12, 12, 7}}, + {m68k_op_cmp_8_pcix , 0xf1ff, 0xb03b, { 14, 14, 9}}, + {m68k_op_cmp_8_i , 0xf1ff, 0xb03c, { 8, 8, 4}}, + {m68k_op_cmp_16_aw , 0xf1ff, 0xb078, { 12, 12, 6}}, + {m68k_op_cmp_16_al , 0xf1ff, 0xb079, { 16, 16, 6}}, + {m68k_op_cmp_16_pcdi , 0xf1ff, 0xb07a, { 12, 12, 7}}, + {m68k_op_cmp_16_pcix , 0xf1ff, 0xb07b, { 14, 14, 9}}, + {m68k_op_cmp_16_i , 0xf1ff, 0xb07c, { 8, 8, 4}}, + {m68k_op_cmp_32_aw , 0xf1ff, 0xb0b8, { 18, 18, 6}}, + {m68k_op_cmp_32_al , 0xf1ff, 0xb0b9, { 22, 22, 6}}, + {m68k_op_cmp_32_pcdi , 0xf1ff, 0xb0ba, { 18, 18, 7}}, + {m68k_op_cmp_32_pcix , 0xf1ff, 0xb0bb, { 20, 20, 9}}, + {m68k_op_cmp_32_i , 0xf1ff, 0xb0bc, { 14, 14, 6}}, + {m68k_op_cmpa_16_aw , 0xf1ff, 0xb0f8, { 14, 14, 8}}, + {m68k_op_cmpa_16_al , 0xf1ff, 0xb0f9, { 18, 18, 8}}, + {m68k_op_cmpa_16_pcdi , 0xf1ff, 0xb0fa, { 14, 14, 9}}, + {m68k_op_cmpa_16_pcix , 0xf1ff, 0xb0fb, { 16, 16, 11}}, + {m68k_op_cmpa_16_i , 0xf1ff, 0xb0fc, { 10, 10, 6}}, + {m68k_op_cmpm_8_ay7 , 0xf1ff, 0xb10f, { 12, 12, 9}}, + {m68k_op_eor_8_pi7 , 0xf1ff, 0xb11f, { 12, 12, 8}}, + {m68k_op_eor_8_pd7 , 0xf1ff, 0xb127, { 14, 14, 9}}, + {m68k_op_eor_8_aw , 0xf1ff, 0xb138, { 16, 16, 8}}, + {m68k_op_eor_8_al , 0xf1ff, 0xb139, { 20, 20, 8}}, + {m68k_op_eor_16_aw , 0xf1ff, 0xb178, { 16, 16, 8}}, + {m68k_op_eor_16_al , 0xf1ff, 0xb179, { 20, 20, 8}}, + {m68k_op_eor_32_aw , 0xf1ff, 0xb1b8, { 24, 24, 8}}, + {m68k_op_eor_32_al , 0xf1ff, 0xb1b9, { 28, 28, 8}}, + {m68k_op_cmpa_32_aw , 0xf1ff, 0xb1f8, { 18, 18, 8}}, + {m68k_op_cmpa_32_al , 0xf1ff, 0xb1f9, { 22, 22, 8}}, + {m68k_op_cmpa_32_pcdi , 0xf1ff, 0xb1fa, { 18, 18, 9}}, + {m68k_op_cmpa_32_pcix , 0xf1ff, 0xb1fb, { 20, 20, 11}}, + {m68k_op_cmpa_32_i , 0xf1ff, 0xb1fc, { 14, 14, 8}}, + {m68k_op_and_8_er_pi7 , 0xf1ff, 0xc01f, { 8, 8, 6}}, + {m68k_op_and_8_er_pd7 , 0xf1ff, 0xc027, { 10, 10, 7}}, + {m68k_op_and_8_er_aw , 0xf1ff, 0xc038, { 12, 12, 6}}, + {m68k_op_and_8_er_al , 0xf1ff, 0xc039, { 16, 16, 6}}, + {m68k_op_and_8_er_pcdi , 0xf1ff, 0xc03a, { 12, 12, 7}}, + {m68k_op_and_8_er_pcix , 0xf1ff, 0xc03b, { 14, 14, 9}}, + {m68k_op_and_8_er_i , 0xf1ff, 0xc03c, { 10, 8, 4}}, + {m68k_op_and_16_er_aw , 0xf1ff, 0xc078, { 12, 12, 6}}, + {m68k_op_and_16_er_al , 0xf1ff, 0xc079, { 16, 16, 6}}, + {m68k_op_and_16_er_pcdi , 0xf1ff, 0xc07a, { 12, 12, 7}}, + {m68k_op_and_16_er_pcix , 0xf1ff, 0xc07b, { 14, 14, 9}}, + {m68k_op_and_16_er_i , 0xf1ff, 0xc07c, { 10, 8, 4}}, + {m68k_op_and_32_er_aw , 0xf1ff, 0xc0b8, { 18, 18, 6}}, + {m68k_op_and_32_er_al , 0xf1ff, 0xc0b9, { 22, 22, 6}}, + {m68k_op_and_32_er_pcdi , 0xf1ff, 0xc0ba, { 18, 18, 7}}, + {m68k_op_and_32_er_pcix , 0xf1ff, 0xc0bb, { 20, 20, 9}}, + {m68k_op_and_32_er_i , 0xf1ff, 0xc0bc, { 16, 14, 6}}, + {m68k_op_mulu_16_aw , 0xf1ff, 0xc0f8, { 62, 38, 31}}, + {m68k_op_mulu_16_al , 0xf1ff, 0xc0f9, { 66, 42, 31}}, + {m68k_op_mulu_16_pcdi , 0xf1ff, 0xc0fa, { 62, 38, 32}}, + {m68k_op_mulu_16_pcix , 0xf1ff, 0xc0fb, { 64, 40, 34}}, + {m68k_op_mulu_16_i , 0xf1ff, 0xc0fc, { 58, 34, 29}}, + {m68k_op_abcd_8_mm_ay7 , 0xf1ff, 0xc10f, { 18, 18, 16}}, + {m68k_op_and_8_re_pi7 , 0xf1ff, 0xc11f, { 12, 12, 8}}, + {m68k_op_and_8_re_pd7 , 0xf1ff, 0xc127, { 14, 14, 9}}, + {m68k_op_and_8_re_aw , 0xf1ff, 0xc138, { 16, 16, 8}}, + {m68k_op_and_8_re_al , 0xf1ff, 0xc139, { 20, 20, 8}}, + {m68k_op_and_16_re_aw , 0xf1ff, 0xc178, { 16, 16, 8}}, + {m68k_op_and_16_re_al , 0xf1ff, 0xc179, { 20, 20, 8}}, + {m68k_op_and_32_re_aw , 0xf1ff, 0xc1b8, { 24, 24, 8}}, + {m68k_op_and_32_re_al , 0xf1ff, 0xc1b9, { 28, 28, 8}}, + {m68k_op_muls_16_aw , 0xf1ff, 0xc1f8, { 62, 40, 31}}, + {m68k_op_muls_16_al , 0xf1ff, 0xc1f9, { 66, 44, 31}}, + {m68k_op_muls_16_pcdi , 0xf1ff, 0xc1fa, { 62, 40, 32}}, + {m68k_op_muls_16_pcix , 0xf1ff, 0xc1fb, { 64, 42, 34}}, + {m68k_op_muls_16_i , 0xf1ff, 0xc1fc, { 58, 36, 29}}, + {m68k_op_add_8_er_pi7 , 0xf1ff, 0xd01f, { 8, 8, 6}}, + {m68k_op_add_8_er_pd7 , 0xf1ff, 0xd027, { 10, 10, 7}}, + {m68k_op_add_8_er_aw , 0xf1ff, 0xd038, { 12, 12, 6}}, + {m68k_op_add_8_er_al , 0xf1ff, 0xd039, { 16, 16, 6}}, + {m68k_op_add_8_er_pcdi , 0xf1ff, 0xd03a, { 12, 12, 7}}, + {m68k_op_add_8_er_pcix , 0xf1ff, 0xd03b, { 14, 14, 9}}, + {m68k_op_add_8_er_i , 0xf1ff, 0xd03c, { 10, 8, 4}}, + {m68k_op_add_16_er_aw , 0xf1ff, 0xd078, { 12, 12, 6}}, + {m68k_op_add_16_er_al , 0xf1ff, 0xd079, { 16, 16, 6}}, + {m68k_op_add_16_er_pcdi , 0xf1ff, 0xd07a, { 12, 12, 7}}, + {m68k_op_add_16_er_pcix , 0xf1ff, 0xd07b, { 14, 14, 9}}, + {m68k_op_add_16_er_i , 0xf1ff, 0xd07c, { 10, 8, 4}}, + {m68k_op_add_32_er_aw , 0xf1ff, 0xd0b8, { 18, 18, 6}}, + {m68k_op_add_32_er_al , 0xf1ff, 0xd0b9, { 22, 22, 6}}, + {m68k_op_add_32_er_pcdi , 0xf1ff, 0xd0ba, { 18, 18, 7}}, + {m68k_op_add_32_er_pcix , 0xf1ff, 0xd0bb, { 20, 20, 9}}, + {m68k_op_add_32_er_i , 0xf1ff, 0xd0bc, { 16, 14, 6}}, + {m68k_op_adda_16_aw , 0xf1ff, 0xd0f8, { 16, 16, 6}}, + {m68k_op_adda_16_al , 0xf1ff, 0xd0f9, { 20, 20, 6}}, + {m68k_op_adda_16_pcdi , 0xf1ff, 0xd0fa, { 16, 16, 7}}, + {m68k_op_adda_16_pcix , 0xf1ff, 0xd0fb, { 18, 18, 9}}, + {m68k_op_adda_16_i , 0xf1ff, 0xd0fc, { 14, 12, 4}}, + {m68k_op_addx_8_mm_ay7 , 0xf1ff, 0xd10f, { 18, 18, 12}}, + {m68k_op_add_8_re_pi7 , 0xf1ff, 0xd11f, { 12, 12, 8}}, + {m68k_op_add_8_re_pd7 , 0xf1ff, 0xd127, { 14, 14, 9}}, + {m68k_op_add_8_re_aw , 0xf1ff, 0xd138, { 16, 16, 8}}, + {m68k_op_add_8_re_al , 0xf1ff, 0xd139, { 20, 20, 8}}, + {m68k_op_add_16_re_aw , 0xf1ff, 0xd178, { 16, 16, 8}}, + {m68k_op_add_16_re_al , 0xf1ff, 0xd179, { 20, 20, 8}}, + {m68k_op_add_32_re_aw , 0xf1ff, 0xd1b8, { 24, 24, 8}}, + {m68k_op_add_32_re_al , 0xf1ff, 0xd1b9, { 28, 28, 8}}, + {m68k_op_adda_32_aw , 0xf1ff, 0xd1f8, { 18, 18, 6}}, + {m68k_op_adda_32_al , 0xf1ff, 0xd1f9, { 22, 22, 6}}, + {m68k_op_adda_32_pcdi , 0xf1ff, 0xd1fa, { 18, 18, 7}}, + {m68k_op_adda_32_pcix , 0xf1ff, 0xd1fb, { 20, 20, 9}}, + {m68k_op_adda_32_i , 0xf1ff, 0xd1fc, { 16, 14, 6}}, + {m68k_op_ori_8_d , 0xfff8, 0x0000, { 8, 8, 2}}, + {m68k_op_ori_8_ai , 0xfff8, 0x0010, { 16, 16, 8}}, + {m68k_op_ori_8_pi , 0xfff8, 0x0018, { 16, 16, 8}}, + {m68k_op_ori_8_pd , 0xfff8, 0x0020, { 18, 18, 9}}, + {m68k_op_ori_8_di , 0xfff8, 0x0028, { 20, 20, 9}}, + {m68k_op_ori_8_ix , 0xfff8, 0x0030, { 22, 22, 11}}, + {m68k_op_ori_16_d , 0xfff8, 0x0040, { 8, 8, 2}}, + {m68k_op_ori_16_ai , 0xfff8, 0x0050, { 16, 16, 8}}, + {m68k_op_ori_16_pi , 0xfff8, 0x0058, { 16, 16, 8}}, + {m68k_op_ori_16_pd , 0xfff8, 0x0060, { 18, 18, 9}}, + {m68k_op_ori_16_di , 0xfff8, 0x0068, { 20, 20, 9}}, + {m68k_op_ori_16_ix , 0xfff8, 0x0070, { 22, 22, 11}}, + {m68k_op_ori_32_d , 0xfff8, 0x0080, { 16, 14, 2}}, + {m68k_op_ori_32_ai , 0xfff8, 0x0090, { 28, 28, 8}}, + {m68k_op_ori_32_pi , 0xfff8, 0x0098, { 28, 28, 8}}, + {m68k_op_ori_32_pd , 0xfff8, 0x00a0, { 30, 30, 9}}, + {m68k_op_ori_32_di , 0xfff8, 0x00a8, { 32, 32, 9}}, + {m68k_op_ori_32_ix , 0xfff8, 0x00b0, { 34, 34, 11}}, + {m68k_op_chk2cmp2_8_ai , 0xfff8, 0x00d0, { 0, 0, 22}}, + {m68k_op_chk2cmp2_8_di , 0xfff8, 0x00e8, { 0, 0, 23}}, + {m68k_op_chk2cmp2_8_ix , 0xfff8, 0x00f0, { 0, 0, 25}}, + {m68k_op_andi_8_d , 0xfff8, 0x0200, { 8, 8, 2}}, + {m68k_op_andi_8_ai , 0xfff8, 0x0210, { 16, 16, 8}}, + {m68k_op_andi_8_pi , 0xfff8, 0x0218, { 16, 16, 8}}, + {m68k_op_andi_8_pd , 0xfff8, 0x0220, { 18, 18, 9}}, + {m68k_op_andi_8_di , 0xfff8, 0x0228, { 20, 20, 9}}, + {m68k_op_andi_8_ix , 0xfff8, 0x0230, { 22, 22, 11}}, + {m68k_op_andi_16_d , 0xfff8, 0x0240, { 8, 8, 2}}, + {m68k_op_andi_16_ai , 0xfff8, 0x0250, { 16, 16, 8}}, + {m68k_op_andi_16_pi , 0xfff8, 0x0258, { 16, 16, 8}}, + {m68k_op_andi_16_pd , 0xfff8, 0x0260, { 18, 18, 9}}, + {m68k_op_andi_16_di , 0xfff8, 0x0268, { 20, 20, 9}}, + {m68k_op_andi_16_ix , 0xfff8, 0x0270, { 22, 22, 11}}, + {m68k_op_andi_32_d , 0xfff8, 0x0280, { 14, 14, 2}}, + {m68k_op_andi_32_ai , 0xfff8, 0x0290, { 28, 28, 8}}, + {m68k_op_andi_32_pi , 0xfff8, 0x0298, { 28, 28, 8}}, + {m68k_op_andi_32_pd , 0xfff8, 0x02a0, { 30, 30, 9}}, + {m68k_op_andi_32_di , 0xfff8, 0x02a8, { 32, 32, 9}}, + {m68k_op_andi_32_ix , 0xfff8, 0x02b0, { 34, 34, 11}}, + {m68k_op_chk2cmp2_16_ai , 0xfff8, 0x02d0, { 0, 0, 22}}, + {m68k_op_chk2cmp2_16_di , 0xfff8, 0x02e8, { 0, 0, 23}}, + {m68k_op_chk2cmp2_16_ix , 0xfff8, 0x02f0, { 0, 0, 25}}, + {m68k_op_subi_8_d , 0xfff8, 0x0400, { 8, 8, 2}}, + {m68k_op_subi_8_ai , 0xfff8, 0x0410, { 16, 16, 8}}, + {m68k_op_subi_8_pi , 0xfff8, 0x0418, { 16, 16, 8}}, + {m68k_op_subi_8_pd , 0xfff8, 0x0420, { 18, 18, 9}}, + {m68k_op_subi_8_di , 0xfff8, 0x0428, { 20, 20, 9}}, + {m68k_op_subi_8_ix , 0xfff8, 0x0430, { 22, 22, 11}}, + {m68k_op_subi_16_d , 0xfff8, 0x0440, { 8, 8, 2}}, + {m68k_op_subi_16_ai , 0xfff8, 0x0450, { 16, 16, 8}}, + {m68k_op_subi_16_pi , 0xfff8, 0x0458, { 16, 16, 8}}, + {m68k_op_subi_16_pd , 0xfff8, 0x0460, { 18, 18, 9}}, + {m68k_op_subi_16_di , 0xfff8, 0x0468, { 20, 20, 9}}, + {m68k_op_subi_16_ix , 0xfff8, 0x0470, { 22, 22, 11}}, + {m68k_op_subi_32_d , 0xfff8, 0x0480, { 16, 14, 2}}, + {m68k_op_subi_32_ai , 0xfff8, 0x0490, { 28, 28, 8}}, + {m68k_op_subi_32_pi , 0xfff8, 0x0498, { 28, 28, 8}}, + {m68k_op_subi_32_pd , 0xfff8, 0x04a0, { 30, 30, 9}}, + {m68k_op_subi_32_di , 0xfff8, 0x04a8, { 32, 32, 9}}, + {m68k_op_subi_32_ix , 0xfff8, 0x04b0, { 34, 34, 11}}, + {m68k_op_chk2cmp2_32_ai , 0xfff8, 0x04d0, { 0, 0, 22}}, + {m68k_op_chk2cmp2_32_di , 0xfff8, 0x04e8, { 0, 0, 23}}, + {m68k_op_chk2cmp2_32_ix , 0xfff8, 0x04f0, { 0, 0, 25}}, + {m68k_op_addi_8_d , 0xfff8, 0x0600, { 8, 8, 2}}, + {m68k_op_addi_8_ai , 0xfff8, 0x0610, { 16, 16, 8}}, + {m68k_op_addi_8_pi , 0xfff8, 0x0618, { 16, 16, 8}}, + {m68k_op_addi_8_pd , 0xfff8, 0x0620, { 18, 18, 9}}, + {m68k_op_addi_8_di , 0xfff8, 0x0628, { 20, 20, 9}}, + {m68k_op_addi_8_ix , 0xfff8, 0x0630, { 22, 22, 11}}, + {m68k_op_addi_16_d , 0xfff8, 0x0640, { 8, 8, 2}}, + {m68k_op_addi_16_ai , 0xfff8, 0x0650, { 16, 16, 8}}, + {m68k_op_addi_16_pi , 0xfff8, 0x0658, { 16, 16, 8}}, + {m68k_op_addi_16_pd , 0xfff8, 0x0660, { 18, 18, 9}}, + {m68k_op_addi_16_di , 0xfff8, 0x0668, { 20, 20, 9}}, + {m68k_op_addi_16_ix , 0xfff8, 0x0670, { 22, 22, 11}}, + {m68k_op_addi_32_d , 0xfff8, 0x0680, { 16, 14, 2}}, + {m68k_op_addi_32_ai , 0xfff8, 0x0690, { 28, 28, 8}}, + {m68k_op_addi_32_pi , 0xfff8, 0x0698, { 28, 28, 8}}, + {m68k_op_addi_32_pd , 0xfff8, 0x06a0, { 30, 30, 9}}, + {m68k_op_addi_32_di , 0xfff8, 0x06a8, { 32, 32, 9}}, + {m68k_op_addi_32_ix , 0xfff8, 0x06b0, { 34, 34, 11}}, + {m68k_op_callm_32_ai , 0xfff8, 0x06d0, { 0, 0, 64}}, + {m68k_op_callm_32_di , 0xfff8, 0x06e8, { 0, 0, 65}}, + {m68k_op_callm_32_ix , 0xfff8, 0x06f0, { 0, 0, 67}}, + {m68k_op_btst_32_s_d , 0xfff8, 0x0800, { 10, 10, 4}}, + {m68k_op_btst_8_s_ai , 0xfff8, 0x0810, { 12, 12, 8}}, + {m68k_op_btst_8_s_pi , 0xfff8, 0x0818, { 12, 12, 8}}, + {m68k_op_btst_8_s_pd , 0xfff8, 0x0820, { 14, 14, 9}}, + {m68k_op_btst_8_s_di , 0xfff8, 0x0828, { 16, 16, 9}}, + {m68k_op_btst_8_s_ix , 0xfff8, 0x0830, { 18, 18, 11}}, + {m68k_op_bchg_32_s_d , 0xfff8, 0x0840, { 12, 12, 4}}, + {m68k_op_bchg_8_s_ai , 0xfff8, 0x0850, { 16, 16, 8}}, + {m68k_op_bchg_8_s_pi , 0xfff8, 0x0858, { 16, 16, 8}}, + {m68k_op_bchg_8_s_pd , 0xfff8, 0x0860, { 18, 18, 9}}, + {m68k_op_bchg_8_s_di , 0xfff8, 0x0868, { 20, 20, 9}}, + {m68k_op_bchg_8_s_ix , 0xfff8, 0x0870, { 22, 22, 11}}, + {m68k_op_bclr_32_s_d , 0xfff8, 0x0880, { 14, 14, 4}}, + {m68k_op_bclr_8_s_ai , 0xfff8, 0x0890, { 16, 16, 8}}, + {m68k_op_bclr_8_s_pi , 0xfff8, 0x0898, { 16, 16, 8}}, + {m68k_op_bclr_8_s_pd , 0xfff8, 0x08a0, { 18, 18, 9}}, + {m68k_op_bclr_8_s_di , 0xfff8, 0x08a8, { 20, 20, 9}}, + {m68k_op_bclr_8_s_ix , 0xfff8, 0x08b0, { 22, 22, 11}}, + {m68k_op_bset_32_s_d , 0xfff8, 0x08c0, { 12, 12, 4}}, + {m68k_op_bset_8_s_ai , 0xfff8, 0x08d0, { 16, 16, 8}}, + {m68k_op_bset_8_s_pi , 0xfff8, 0x08d8, { 16, 16, 8}}, + {m68k_op_bset_8_s_pd , 0xfff8, 0x08e0, { 18, 18, 9}}, + {m68k_op_bset_8_s_di , 0xfff8, 0x08e8, { 20, 20, 9}}, + {m68k_op_bset_8_s_ix , 0xfff8, 0x08f0, { 22, 22, 11}}, + {m68k_op_eori_8_d , 0xfff8, 0x0a00, { 8, 8, 2}}, + {m68k_op_eori_8_ai , 0xfff8, 0x0a10, { 16, 16, 8}}, + {m68k_op_eori_8_pi , 0xfff8, 0x0a18, { 16, 16, 8}}, + {m68k_op_eori_8_pd , 0xfff8, 0x0a20, { 18, 18, 9}}, + {m68k_op_eori_8_di , 0xfff8, 0x0a28, { 20, 20, 9}}, + {m68k_op_eori_8_ix , 0xfff8, 0x0a30, { 22, 22, 11}}, + {m68k_op_eori_16_d , 0xfff8, 0x0a40, { 8, 8, 2}}, + {m68k_op_eori_16_ai , 0xfff8, 0x0a50, { 16, 16, 8}}, + {m68k_op_eori_16_pi , 0xfff8, 0x0a58, { 16, 16, 8}}, + {m68k_op_eori_16_pd , 0xfff8, 0x0a60, { 18, 18, 9}}, + {m68k_op_eori_16_di , 0xfff8, 0x0a68, { 20, 20, 9}}, + {m68k_op_eori_16_ix , 0xfff8, 0x0a70, { 22, 22, 11}}, + {m68k_op_eori_32_d , 0xfff8, 0x0a80, { 16, 14, 2}}, + {m68k_op_eori_32_ai , 0xfff8, 0x0a90, { 28, 28, 8}}, + {m68k_op_eori_32_pi , 0xfff8, 0x0a98, { 28, 28, 8}}, + {m68k_op_eori_32_pd , 0xfff8, 0x0aa0, { 30, 30, 9}}, + {m68k_op_eori_32_di , 0xfff8, 0x0aa8, { 32, 32, 9}}, + {m68k_op_eori_32_ix , 0xfff8, 0x0ab0, { 34, 34, 11}}, + {m68k_op_cas_8_ai , 0xfff8, 0x0ad0, { 0, 0, 16}}, + {m68k_op_cas_8_pi , 0xfff8, 0x0ad8, { 0, 0, 16}}, + {m68k_op_cas_8_pd , 0xfff8, 0x0ae0, { 0, 0, 17}}, + {m68k_op_cas_8_di , 0xfff8, 0x0ae8, { 0, 0, 17}}, + {m68k_op_cas_8_ix , 0xfff8, 0x0af0, { 0, 0, 19}}, + {m68k_op_cmpi_8_d , 0xfff8, 0x0c00, { 8, 8, 2}}, + {m68k_op_cmpi_8_ai , 0xfff8, 0x0c10, { 12, 12, 6}}, + {m68k_op_cmpi_8_pi , 0xfff8, 0x0c18, { 12, 12, 6}}, + {m68k_op_cmpi_8_pd , 0xfff8, 0x0c20, { 14, 14, 7}}, + {m68k_op_cmpi_8_di , 0xfff8, 0x0c28, { 16, 16, 7}}, + {m68k_op_cmpi_8_ix , 0xfff8, 0x0c30, { 18, 18, 9}}, + {m68k_op_cmpi_16_d , 0xfff8, 0x0c40, { 8, 8, 2}}, + {m68k_op_cmpi_16_ai , 0xfff8, 0x0c50, { 12, 12, 6}}, + {m68k_op_cmpi_16_pi , 0xfff8, 0x0c58, { 12, 12, 6}}, + {m68k_op_cmpi_16_pd , 0xfff8, 0x0c60, { 14, 14, 7}}, + {m68k_op_cmpi_16_di , 0xfff8, 0x0c68, { 16, 16, 7}}, + {m68k_op_cmpi_16_ix , 0xfff8, 0x0c70, { 18, 18, 9}}, + {m68k_op_cmpi_32_d , 0xfff8, 0x0c80, { 14, 12, 2}}, + {m68k_op_cmpi_32_ai , 0xfff8, 0x0c90, { 20, 20, 6}}, + {m68k_op_cmpi_32_pi , 0xfff8, 0x0c98, { 20, 20, 6}}, + {m68k_op_cmpi_32_pd , 0xfff8, 0x0ca0, { 22, 22, 7}}, + {m68k_op_cmpi_32_di , 0xfff8, 0x0ca8, { 24, 24, 7}}, + {m68k_op_cmpi_32_ix , 0xfff8, 0x0cb0, { 26, 26, 9}}, + {m68k_op_cas_16_ai , 0xfff8, 0x0cd0, { 0, 0, 16}}, + {m68k_op_cas_16_pi , 0xfff8, 0x0cd8, { 0, 0, 16}}, + {m68k_op_cas_16_pd , 0xfff8, 0x0ce0, { 0, 0, 17}}, + {m68k_op_cas_16_di , 0xfff8, 0x0ce8, { 0, 0, 17}}, + {m68k_op_cas_16_ix , 0xfff8, 0x0cf0, { 0, 0, 19}}, + {m68k_op_moves_8_ai , 0xfff8, 0x0e10, { 0, 18, 9}}, + {m68k_op_moves_8_pi , 0xfff8, 0x0e18, { 0, 18, 9}}, + {m68k_op_moves_8_pd , 0xfff8, 0x0e20, { 0, 20, 10}}, + {m68k_op_moves_8_di , 0xfff8, 0x0e28, { 0, 26, 10}}, + {m68k_op_moves_8_ix , 0xfff8, 0x0e30, { 0, 30, 12}}, + {m68k_op_moves_16_ai , 0xfff8, 0x0e50, { 0, 18, 9}}, + {m68k_op_moves_16_pi , 0xfff8, 0x0e58, { 0, 18, 9}}, + {m68k_op_moves_16_pd , 0xfff8, 0x0e60, { 0, 20, 10}}, + {m68k_op_moves_16_di , 0xfff8, 0x0e68, { 0, 26, 10}}, + {m68k_op_moves_16_ix , 0xfff8, 0x0e70, { 0, 30, 12}}, + {m68k_op_moves_32_ai , 0xfff8, 0x0e90, { 0, 22, 9}}, + {m68k_op_moves_32_pi , 0xfff8, 0x0e98, { 0, 22, 9}}, + {m68k_op_moves_32_pd , 0xfff8, 0x0ea0, { 0, 28, 10}}, + {m68k_op_moves_32_di , 0xfff8, 0x0ea8, { 0, 32, 10}}, + {m68k_op_moves_32_ix , 0xfff8, 0x0eb0, { 0, 36, 12}}, + {m68k_op_cas_32_ai , 0xfff8, 0x0ed0, { 0, 0, 16}}, + {m68k_op_cas_32_pi , 0xfff8, 0x0ed8, { 0, 0, 16}}, + {m68k_op_cas_32_pd , 0xfff8, 0x0ee0, { 0, 0, 17}}, + {m68k_op_cas_32_di , 0xfff8, 0x0ee8, { 0, 0, 17}}, + {m68k_op_cas_32_ix , 0xfff8, 0x0ef0, { 0, 0, 19}}, + {m68k_op_move_8_aw_d , 0xfff8, 0x11c0, { 12, 12, 4}}, + {m68k_op_move_8_aw_ai , 0xfff8, 0x11d0, { 16, 16, 8}}, + {m68k_op_move_8_aw_pi , 0xfff8, 0x11d8, { 16, 16, 8}}, + {m68k_op_move_8_aw_pd , 0xfff8, 0x11e0, { 18, 18, 9}}, + {m68k_op_move_8_aw_di , 0xfff8, 0x11e8, { 20, 20, 9}}, + {m68k_op_move_8_aw_ix , 0xfff8, 0x11f0, { 22, 22, 11}}, + {m68k_op_move_8_al_d , 0xfff8, 0x13c0, { 16, 16, 6}}, + {m68k_op_move_8_al_ai , 0xfff8, 0x13d0, { 20, 20, 10}}, + {m68k_op_move_8_al_pi , 0xfff8, 0x13d8, { 20, 20, 10}}, + {m68k_op_move_8_al_pd , 0xfff8, 0x13e0, { 22, 22, 11}}, + {m68k_op_move_8_al_di , 0xfff8, 0x13e8, { 24, 24, 11}}, + {m68k_op_move_8_al_ix , 0xfff8, 0x13f0, { 26, 26, 13}}, + {m68k_op_move_8_pi7_d , 0xfff8, 0x1ec0, { 8, 8, 4}}, + {m68k_op_move_8_pi7_ai , 0xfff8, 0x1ed0, { 12, 12, 8}}, + {m68k_op_move_8_pi7_pi , 0xfff8, 0x1ed8, { 12, 12, 8}}, + {m68k_op_move_8_pi7_pd , 0xfff8, 0x1ee0, { 14, 14, 9}}, + {m68k_op_move_8_pi7_di , 0xfff8, 0x1ee8, { 16, 16, 9}}, + {m68k_op_move_8_pi7_ix , 0xfff8, 0x1ef0, { 18, 18, 11}}, + {m68k_op_move_8_pd7_d , 0xfff8, 0x1f00, { 8, 8, 5}}, + {m68k_op_move_8_pd7_ai , 0xfff8, 0x1f10, { 12, 12, 9}}, + {m68k_op_move_8_pd7_pi , 0xfff8, 0x1f18, { 12, 12, 9}}, + {m68k_op_move_8_pd7_pd , 0xfff8, 0x1f20, { 14, 14, 10}}, + {m68k_op_move_8_pd7_di , 0xfff8, 0x1f28, { 16, 16, 10}}, + {m68k_op_move_8_pd7_ix , 0xfff8, 0x1f30, { 18, 18, 12}}, + {m68k_op_move_32_aw_d , 0xfff8, 0x21c0, { 16, 16, 4}}, + {m68k_op_move_32_aw_a , 0xfff8, 0x21c8, { 16, 16, 4}}, + {m68k_op_move_32_aw_ai , 0xfff8, 0x21d0, { 24, 24, 8}}, + {m68k_op_move_32_aw_pi , 0xfff8, 0x21d8, { 24, 24, 8}}, + {m68k_op_move_32_aw_pd , 0xfff8, 0x21e0, { 26, 26, 9}}, + {m68k_op_move_32_aw_di , 0xfff8, 0x21e8, { 28, 28, 9}}, + {m68k_op_move_32_aw_ix , 0xfff8, 0x21f0, { 30, 30, 11}}, + {m68k_op_move_32_al_d , 0xfff8, 0x23c0, { 20, 20, 6}}, + {m68k_op_move_32_al_a , 0xfff8, 0x23c8, { 20, 20, 6}}, + {m68k_op_move_32_al_ai , 0xfff8, 0x23d0, { 28, 28, 10}}, + {m68k_op_move_32_al_pi , 0xfff8, 0x23d8, { 28, 28, 10}}, + {m68k_op_move_32_al_pd , 0xfff8, 0x23e0, { 30, 30, 11}}, + {m68k_op_move_32_al_di , 0xfff8, 0x23e8, { 32, 32, 11}}, + {m68k_op_move_32_al_ix , 0xfff8, 0x23f0, { 34, 34, 13}}, + {m68k_op_move_16_aw_d , 0xfff8, 0x31c0, { 12, 12, 4}}, + {m68k_op_move_16_aw_a , 0xfff8, 0x31c8, { 12, 12, 4}}, + {m68k_op_move_16_aw_ai , 0xfff8, 0x31d0, { 16, 16, 8}}, + {m68k_op_move_16_aw_pi , 0xfff8, 0x31d8, { 16, 16, 8}}, + {m68k_op_move_16_aw_pd , 0xfff8, 0x31e0, { 18, 18, 9}}, + {m68k_op_move_16_aw_di , 0xfff8, 0x31e8, { 20, 20, 9}}, + {m68k_op_move_16_aw_ix , 0xfff8, 0x31f0, { 22, 22, 11}}, + {m68k_op_move_16_al_d , 0xfff8, 0x33c0, { 16, 16, 6}}, + {m68k_op_move_16_al_a , 0xfff8, 0x33c8, { 16, 16, 6}}, + {m68k_op_move_16_al_ai , 0xfff8, 0x33d0, { 20, 20, 10}}, + {m68k_op_move_16_al_pi , 0xfff8, 0x33d8, { 20, 20, 10}}, + {m68k_op_move_16_al_pd , 0xfff8, 0x33e0, { 22, 22, 11}}, + {m68k_op_move_16_al_di , 0xfff8, 0x33e8, { 24, 24, 11}}, + {m68k_op_move_16_al_ix , 0xfff8, 0x33f0, { 26, 26, 13}}, + {m68k_op_negx_8_d , 0xfff8, 0x4000, { 4, 4, 2}}, + {m68k_op_negx_8_ai , 0xfff8, 0x4010, { 12, 12, 8}}, + {m68k_op_negx_8_pi , 0xfff8, 0x4018, { 12, 12, 8}}, + {m68k_op_negx_8_pd , 0xfff8, 0x4020, { 14, 14, 9}}, + {m68k_op_negx_8_di , 0xfff8, 0x4028, { 16, 16, 9}}, + {m68k_op_negx_8_ix , 0xfff8, 0x4030, { 18, 18, 11}}, + {m68k_op_negx_16_d , 0xfff8, 0x4040, { 4, 4, 2}}, + {m68k_op_negx_16_ai , 0xfff8, 0x4050, { 12, 12, 8}}, + {m68k_op_negx_16_pi , 0xfff8, 0x4058, { 12, 12, 8}}, + {m68k_op_negx_16_pd , 0xfff8, 0x4060, { 14, 14, 9}}, + {m68k_op_negx_16_di , 0xfff8, 0x4068, { 16, 16, 9}}, + {m68k_op_negx_16_ix , 0xfff8, 0x4070, { 18, 18, 11}}, + {m68k_op_negx_32_d , 0xfff8, 0x4080, { 6, 6, 2}}, + {m68k_op_negx_32_ai , 0xfff8, 0x4090, { 20, 20, 8}}, + {m68k_op_negx_32_pi , 0xfff8, 0x4098, { 20, 20, 8}}, + {m68k_op_negx_32_pd , 0xfff8, 0x40a0, { 22, 22, 9}}, + {m68k_op_negx_32_di , 0xfff8, 0x40a8, { 24, 24, 9}}, + {m68k_op_negx_32_ix , 0xfff8, 0x40b0, { 26, 26, 11}}, + {m68k_op_move_16_frs_d , 0xfff8, 0x40c0, { 6, 4, 8}}, + {m68k_op_move_16_frs_ai , 0xfff8, 0x40d0, { 12, 12, 12}}, + {m68k_op_move_16_frs_pi , 0xfff8, 0x40d8, { 12, 12, 12}}, + {m68k_op_move_16_frs_pd , 0xfff8, 0x40e0, { 14, 14, 13}}, + {m68k_op_move_16_frs_di , 0xfff8, 0x40e8, { 16, 16, 13}}, + {m68k_op_move_16_frs_ix , 0xfff8, 0x40f0, { 18, 18, 15}}, + {m68k_op_clr_8_d , 0xfff8, 0x4200, { 4, 4, 2}}, + {m68k_op_clr_8_ai , 0xfff8, 0x4210, { 12, 8, 8}}, + {m68k_op_clr_8_pi , 0xfff8, 0x4218, { 12, 8, 8}}, + {m68k_op_clr_8_pd , 0xfff8, 0x4220, { 14, 10, 9}}, + {m68k_op_clr_8_di , 0xfff8, 0x4228, { 16, 12, 9}}, + {m68k_op_clr_8_ix , 0xfff8, 0x4230, { 18, 14, 11}}, + {m68k_op_clr_16_d , 0xfff8, 0x4240, { 4, 4, 2}}, + {m68k_op_clr_16_ai , 0xfff8, 0x4250, { 12, 8, 8}}, + {m68k_op_clr_16_pi , 0xfff8, 0x4258, { 12, 8, 8}}, + {m68k_op_clr_16_pd , 0xfff8, 0x4260, { 14, 10, 9}}, + {m68k_op_clr_16_di , 0xfff8, 0x4268, { 16, 12, 9}}, + {m68k_op_clr_16_ix , 0xfff8, 0x4270, { 18, 14, 11}}, + {m68k_op_clr_32_d , 0xfff8, 0x4280, { 6, 6, 2}}, + {m68k_op_clr_32_ai , 0xfff8, 0x4290, { 20, 12, 8}}, + {m68k_op_clr_32_pi , 0xfff8, 0x4298, { 20, 12, 8}}, + {m68k_op_clr_32_pd , 0xfff8, 0x42a0, { 22, 14, 9}}, + {m68k_op_clr_32_di , 0xfff8, 0x42a8, { 24, 16, 9}}, + {m68k_op_clr_32_ix , 0xfff8, 0x42b0, { 26, 20, 11}}, + {m68k_op_move_16_frc_d , 0xfff8, 0x42c0, { 0, 4, 4}}, + {m68k_op_move_16_frc_ai , 0xfff8, 0x42d0, { 0, 12, 8}}, + {m68k_op_move_16_frc_pi , 0xfff8, 0x42d8, { 0, 12, 8}}, + {m68k_op_move_16_frc_pd , 0xfff8, 0x42e0, { 0, 14, 9}}, + {m68k_op_move_16_frc_di , 0xfff8, 0x42e8, { 0, 16, 9}}, + {m68k_op_move_16_frc_ix , 0xfff8, 0x42f0, { 0, 18, 11}}, + {m68k_op_neg_8_d , 0xfff8, 0x4400, { 4, 4, 2}}, + {m68k_op_neg_8_ai , 0xfff8, 0x4410, { 12, 12, 8}}, + {m68k_op_neg_8_pi , 0xfff8, 0x4418, { 12, 12, 8}}, + {m68k_op_neg_8_pd , 0xfff8, 0x4420, { 14, 14, 9}}, + {m68k_op_neg_8_di , 0xfff8, 0x4428, { 16, 16, 9}}, + {m68k_op_neg_8_ix , 0xfff8, 0x4430, { 18, 18, 11}}, + {m68k_op_neg_16_d , 0xfff8, 0x4440, { 4, 4, 2}}, + {m68k_op_neg_16_ai , 0xfff8, 0x4450, { 12, 12, 8}}, + {m68k_op_neg_16_pi , 0xfff8, 0x4458, { 12, 12, 8}}, + {m68k_op_neg_16_pd , 0xfff8, 0x4460, { 14, 14, 9}}, + {m68k_op_neg_16_di , 0xfff8, 0x4468, { 16, 16, 9}}, + {m68k_op_neg_16_ix , 0xfff8, 0x4470, { 18, 18, 11}}, + {m68k_op_neg_32_d , 0xfff8, 0x4480, { 6, 6, 2}}, + {m68k_op_neg_32_ai , 0xfff8, 0x4490, { 20, 20, 8}}, + {m68k_op_neg_32_pi , 0xfff8, 0x4498, { 20, 20, 8}}, + {m68k_op_neg_32_pd , 0xfff8, 0x44a0, { 22, 22, 9}}, + {m68k_op_neg_32_di , 0xfff8, 0x44a8, { 24, 24, 9}}, + {m68k_op_neg_32_ix , 0xfff8, 0x44b0, { 26, 26, 11}}, + {m68k_op_move_16_toc_d , 0xfff8, 0x44c0, { 12, 12, 4}}, + {m68k_op_move_16_toc_ai , 0xfff8, 0x44d0, { 16, 16, 8}}, + {m68k_op_move_16_toc_pi , 0xfff8, 0x44d8, { 16, 16, 8}}, + {m68k_op_move_16_toc_pd , 0xfff8, 0x44e0, { 18, 18, 9}}, + {m68k_op_move_16_toc_di , 0xfff8, 0x44e8, { 20, 20, 9}}, + {m68k_op_move_16_toc_ix , 0xfff8, 0x44f0, { 22, 22, 11}}, + {m68k_op_not_8_d , 0xfff8, 0x4600, { 4, 4, 2}}, + {m68k_op_not_8_ai , 0xfff8, 0x4610, { 12, 12, 8}}, + {m68k_op_not_8_pi , 0xfff8, 0x4618, { 12, 12, 8}}, + {m68k_op_not_8_pd , 0xfff8, 0x4620, { 14, 14, 9}}, + {m68k_op_not_8_di , 0xfff8, 0x4628, { 16, 16, 9}}, + {m68k_op_not_8_ix , 0xfff8, 0x4630, { 18, 18, 11}}, + {m68k_op_not_16_d , 0xfff8, 0x4640, { 4, 4, 2}}, + {m68k_op_not_16_ai , 0xfff8, 0x4650, { 12, 12, 8}}, + {m68k_op_not_16_pi , 0xfff8, 0x4658, { 12, 12, 8}}, + {m68k_op_not_16_pd , 0xfff8, 0x4660, { 14, 14, 9}}, + {m68k_op_not_16_di , 0xfff8, 0x4668, { 16, 16, 9}}, + {m68k_op_not_16_ix , 0xfff8, 0x4670, { 18, 18, 11}}, + {m68k_op_not_32_d , 0xfff8, 0x4680, { 6, 6, 2}}, + {m68k_op_not_32_ai , 0xfff8, 0x4690, { 20, 20, 8}}, + {m68k_op_not_32_pi , 0xfff8, 0x4698, { 20, 20, 8}}, + {m68k_op_not_32_pd , 0xfff8, 0x46a0, { 22, 22, 9}}, + {m68k_op_not_32_di , 0xfff8, 0x46a8, { 24, 24, 9}}, + {m68k_op_not_32_ix , 0xfff8, 0x46b0, { 26, 26, 11}}, + {m68k_op_move_16_tos_d , 0xfff8, 0x46c0, { 12, 12, 8}}, + {m68k_op_move_16_tos_ai , 0xfff8, 0x46d0, { 16, 16, 12}}, + {m68k_op_move_16_tos_pi , 0xfff8, 0x46d8, { 16, 16, 12}}, + {m68k_op_move_16_tos_pd , 0xfff8, 0x46e0, { 18, 18, 13}}, + {m68k_op_move_16_tos_di , 0xfff8, 0x46e8, { 20, 20, 13}}, + {m68k_op_move_16_tos_ix , 0xfff8, 0x46f0, { 22, 22, 15}}, + {m68k_op_nbcd_8_d , 0xfff8, 0x4800, { 6, 6, 6}}, + {m68k_op_link_32 , 0xfff8, 0x4808, { 0, 0, 6}}, + {m68k_op_nbcd_8_ai , 0xfff8, 0x4810, { 12, 12, 10}}, + {m68k_op_nbcd_8_pi , 0xfff8, 0x4818, { 12, 12, 10}}, + {m68k_op_nbcd_8_pd , 0xfff8, 0x4820, { 14, 14, 11}}, + {m68k_op_nbcd_8_di , 0xfff8, 0x4828, { 16, 16, 11}}, + {m68k_op_nbcd_8_ix , 0xfff8, 0x4830, { 18, 18, 13}}, + {m68k_op_swap_32 , 0xfff8, 0x4840, { 4, 4, 4}}, + {m68k_op_bkpt , 0xfff8, 0x4848, { 0, 10, 10}}, + {m68k_op_pea_32_ai , 0xfff8, 0x4850, { 10, 10, 9}}, + {m68k_op_pea_32_di , 0xfff8, 0x4868, { 16, 16, 10}}, + {m68k_op_pea_32_ix , 0xfff8, 0x4870, { 20, 20, 12}}, + {m68k_op_ext_16 , 0xfff8, 0x4880, { 4, 4, 4}}, + {m68k_op_movem_16_re_ai , 0xfff8, 0x4890, { 12, 12, 8}}, + {m68k_op_movem_16_re_pd , 0xfff8, 0x48a0, { 8, 8, 4}}, + {m68k_op_movem_16_re_di , 0xfff8, 0x48a8, { 16, 16, 9}}, + {m68k_op_movem_16_re_ix , 0xfff8, 0x48b0, { 18, 18, 11}}, + {m68k_op_ext_32 , 0xfff8, 0x48c0, { 4, 4, 4}}, + {m68k_op_movem_32_re_ai , 0xfff8, 0x48d0, { 16, 16, 8}}, + {m68k_op_movem_32_re_pd , 0xfff8, 0x48e0, { 8, 8, 4}}, + {m68k_op_movem_32_re_di , 0xfff8, 0x48e8, { 20, 20, 9}}, + {m68k_op_movem_32_re_ix , 0xfff8, 0x48f0, { 22, 22, 11}}, + {m68k_op_extb_32 , 0xfff8, 0x49c0, { 0, 0, 4}}, + {m68k_op_tst_8_d , 0xfff8, 0x4a00, { 4, 4, 2}}, + {m68k_op_tst_8_ai , 0xfff8, 0x4a10, { 8, 8, 6}}, + {m68k_op_tst_8_pi , 0xfff8, 0x4a18, { 8, 8, 6}}, + {m68k_op_tst_8_pd , 0xfff8, 0x4a20, { 10, 10, 7}}, + {m68k_op_tst_8_di , 0xfff8, 0x4a28, { 12, 12, 7}}, + {m68k_op_tst_8_ix , 0xfff8, 0x4a30, { 14, 14, 9}}, + {m68k_op_tst_16_d , 0xfff8, 0x4a40, { 4, 4, 2}}, + {m68k_op_tst_16_a , 0xfff8, 0x4a48, { 0, 0, 2}}, + {m68k_op_tst_16_ai , 0xfff8, 0x4a50, { 8, 8, 6}}, + {m68k_op_tst_16_pi , 0xfff8, 0x4a58, { 8, 8, 6}}, + {m68k_op_tst_16_pd , 0xfff8, 0x4a60, { 10, 10, 7}}, + {m68k_op_tst_16_di , 0xfff8, 0x4a68, { 12, 12, 7}}, + {m68k_op_tst_16_ix , 0xfff8, 0x4a70, { 14, 14, 9}}, + {m68k_op_tst_32_d , 0xfff8, 0x4a80, { 4, 4, 2}}, + {m68k_op_tst_32_a , 0xfff8, 0x4a88, { 0, 0, 2}}, + {m68k_op_tst_32_ai , 0xfff8, 0x4a90, { 12, 12, 6}}, + {m68k_op_tst_32_pi , 0xfff8, 0x4a98, { 12, 12, 6}}, + {m68k_op_tst_32_pd , 0xfff8, 0x4aa0, { 14, 14, 7}}, + {m68k_op_tst_32_di , 0xfff8, 0x4aa8, { 16, 16, 7}}, + {m68k_op_tst_32_ix , 0xfff8, 0x4ab0, { 18, 18, 9}}, + {m68k_op_tas_8_d , 0xfff8, 0x4ac0, { 4, 4, 4}}, + {m68k_op_tas_8_ai , 0xfff8, 0x4ad0, { 18, 18, 16}}, + {m68k_op_tas_8_pi , 0xfff8, 0x4ad8, { 18, 18, 16}}, + {m68k_op_tas_8_pd , 0xfff8, 0x4ae0, { 20, 20, 17}}, + {m68k_op_tas_8_di , 0xfff8, 0x4ae8, { 22, 22, 17}}, + {m68k_op_tas_8_ix , 0xfff8, 0x4af0, { 24, 24, 19}}, + {m68k_op_mull_32_d , 0xfff8, 0x4c00, { 0, 0, 43}}, + {m68k_op_mull_32_ai , 0xfff8, 0x4c10, { 0, 0, 47}}, + {m68k_op_mull_32_pi , 0xfff8, 0x4c18, { 0, 0, 47}}, + {m68k_op_mull_32_pd , 0xfff8, 0x4c20, { 0, 0, 48}}, + {m68k_op_mull_32_di , 0xfff8, 0x4c28, { 0, 0, 48}}, + {m68k_op_mull_32_ix , 0xfff8, 0x4c30, { 0, 0, 50}}, + {m68k_op_divl_32_d , 0xfff8, 0x4c40, { 0, 0, 84}}, + {m68k_op_divl_32_ai , 0xfff8, 0x4c50, { 0, 0, 88}}, + {m68k_op_divl_32_pi , 0xfff8, 0x4c58, { 0, 0, 88}}, + {m68k_op_divl_32_pd , 0xfff8, 0x4c60, { 0, 0, 89}}, + {m68k_op_divl_32_di , 0xfff8, 0x4c68, { 0, 0, 89}}, + {m68k_op_divl_32_ix , 0xfff8, 0x4c70, { 0, 0, 91}}, + {m68k_op_movem_16_er_ai , 0xfff8, 0x4c90, { 16, 16, 12}}, + {m68k_op_movem_16_er_pi , 0xfff8, 0x4c98, { 12, 12, 8}}, + {m68k_op_movem_16_er_di , 0xfff8, 0x4ca8, { 20, 20, 13}}, + {m68k_op_movem_16_er_ix , 0xfff8, 0x4cb0, { 22, 22, 15}}, + {m68k_op_movem_32_er_ai , 0xfff8, 0x4cd0, { 20, 20, 12}}, + {m68k_op_movem_32_er_pi , 0xfff8, 0x4cd8, { 12, 12, 8}}, + {m68k_op_movem_32_er_di , 0xfff8, 0x4ce8, { 24, 24, 13}}, + {m68k_op_movem_32_er_ix , 0xfff8, 0x4cf0, { 26, 26, 15}}, + {m68k_op_link_16 , 0xfff8, 0x4e50, { 16, 16, 5}}, + {m68k_op_unlk_32 , 0xfff8, 0x4e58, { 12, 12, 6}}, + {m68k_op_move_32_tou , 0xfff8, 0x4e60, { 4, 6, 2}}, + {m68k_op_move_32_fru , 0xfff8, 0x4e68, { 4, 6, 2}}, + {m68k_op_jsr_32_ai , 0xfff8, 0x4e90, { 16, 16, 4}}, + {m68k_op_jsr_32_di , 0xfff8, 0x4ea8, { 18, 18, 5}}, + {m68k_op_jsr_32_ix , 0xfff8, 0x4eb0, { 22, 22, 7}}, + {m68k_op_jmp_32_ai , 0xfff8, 0x4ed0, { 8, 8, 4}}, + {m68k_op_jmp_32_di , 0xfff8, 0x4ee8, { 10, 10, 5}}, + {m68k_op_jmp_32_ix , 0xfff8, 0x4ef0, { 12, 12, 7}}, + {m68k_op_st_8_d , 0xfff8, 0x50c0, { 6, 4, 4}}, + {m68k_op_dbt_16 , 0xfff8, 0x50c8, { 12, 12, 6}}, + {m68k_op_st_8_ai , 0xfff8, 0x50d0, { 12, 12, 10}}, + {m68k_op_st_8_pi , 0xfff8, 0x50d8, { 12, 12, 10}}, + {m68k_op_st_8_pd , 0xfff8, 0x50e0, { 14, 14, 11}}, + {m68k_op_st_8_di , 0xfff8, 0x50e8, { 16, 16, 11}}, + {m68k_op_st_8_ix , 0xfff8, 0x50f0, { 18, 18, 13}}, + {m68k_op_sf_8_d , 0xfff8, 0x51c0, { 4, 4, 4}}, + {m68k_op_dbf_16 , 0xfff8, 0x51c8, { 14, 14, 6}}, + {m68k_op_sf_8_ai , 0xfff8, 0x51d0, { 12, 12, 10}}, + {m68k_op_sf_8_pi , 0xfff8, 0x51d8, { 12, 12, 10}}, + {m68k_op_sf_8_pd , 0xfff8, 0x51e0, { 14, 14, 11}}, + {m68k_op_sf_8_di , 0xfff8, 0x51e8, { 16, 16, 11}}, + {m68k_op_sf_8_ix , 0xfff8, 0x51f0, { 18, 18, 13}}, + {m68k_op_shi_8_d , 0xfff8, 0x52c0, { 4, 4, 4}}, + {m68k_op_dbhi_16 , 0xfff8, 0x52c8, { 12, 12, 6}}, + {m68k_op_shi_8_ai , 0xfff8, 0x52d0, { 12, 12, 10}}, + {m68k_op_shi_8_pi , 0xfff8, 0x52d8, { 12, 12, 10}}, + {m68k_op_shi_8_pd , 0xfff8, 0x52e0, { 14, 14, 11}}, + {m68k_op_shi_8_di , 0xfff8, 0x52e8, { 16, 16, 11}}, + {m68k_op_shi_8_ix , 0xfff8, 0x52f0, { 18, 18, 13}}, + {m68k_op_sls_8_d , 0xfff8, 0x53c0, { 4, 4, 4}}, + {m68k_op_dbls_16 , 0xfff8, 0x53c8, { 12, 12, 6}}, + {m68k_op_sls_8_ai , 0xfff8, 0x53d0, { 12, 12, 10}}, + {m68k_op_sls_8_pi , 0xfff8, 0x53d8, { 12, 12, 10}}, + {m68k_op_sls_8_pd , 0xfff8, 0x53e0, { 14, 14, 11}}, + {m68k_op_sls_8_di , 0xfff8, 0x53e8, { 16, 16, 11}}, + {m68k_op_sls_8_ix , 0xfff8, 0x53f0, { 18, 18, 13}}, + {m68k_op_scc_8_d , 0xfff8, 0x54c0, { 4, 4, 4}}, + {m68k_op_dbcc_16 , 0xfff8, 0x54c8, { 12, 12, 6}}, + {m68k_op_scc_8_ai , 0xfff8, 0x54d0, { 12, 12, 10}}, + {m68k_op_scc_8_pi , 0xfff8, 0x54d8, { 12, 12, 10}}, + {m68k_op_scc_8_pd , 0xfff8, 0x54e0, { 14, 14, 11}}, + {m68k_op_scc_8_di , 0xfff8, 0x54e8, { 16, 16, 11}}, + {m68k_op_scc_8_ix , 0xfff8, 0x54f0, { 18, 18, 13}}, + {m68k_op_scs_8_d , 0xfff8, 0x55c0, { 4, 4, 4}}, + {m68k_op_dbcs_16 , 0xfff8, 0x55c8, { 12, 12, 6}}, + {m68k_op_scs_8_ai , 0xfff8, 0x55d0, { 12, 12, 10}}, + {m68k_op_scs_8_pi , 0xfff8, 0x55d8, { 12, 12, 10}}, + {m68k_op_scs_8_pd , 0xfff8, 0x55e0, { 14, 14, 11}}, + {m68k_op_scs_8_di , 0xfff8, 0x55e8, { 16, 16, 11}}, + {m68k_op_scs_8_ix , 0xfff8, 0x55f0, { 18, 18, 13}}, + {m68k_op_sne_8_d , 0xfff8, 0x56c0, { 4, 4, 4}}, + {m68k_op_dbne_16 , 0xfff8, 0x56c8, { 12, 12, 6}}, + {m68k_op_sne_8_ai , 0xfff8, 0x56d0, { 12, 12, 10}}, + {m68k_op_sne_8_pi , 0xfff8, 0x56d8, { 12, 12, 10}}, + {m68k_op_sne_8_pd , 0xfff8, 0x56e0, { 14, 14, 11}}, + {m68k_op_sne_8_di , 0xfff8, 0x56e8, { 16, 16, 11}}, + {m68k_op_sne_8_ix , 0xfff8, 0x56f0, { 18, 18, 13}}, + {m68k_op_seq_8_d , 0xfff8, 0x57c0, { 4, 4, 4}}, + {m68k_op_dbeq_16 , 0xfff8, 0x57c8, { 12, 12, 6}}, + {m68k_op_seq_8_ai , 0xfff8, 0x57d0, { 12, 12, 10}}, + {m68k_op_seq_8_pi , 0xfff8, 0x57d8, { 12, 12, 10}}, + {m68k_op_seq_8_pd , 0xfff8, 0x57e0, { 14, 14, 11}}, + {m68k_op_seq_8_di , 0xfff8, 0x57e8, { 16, 16, 11}}, + {m68k_op_seq_8_ix , 0xfff8, 0x57f0, { 18, 18, 13}}, + {m68k_op_svc_8_d , 0xfff8, 0x58c0, { 4, 4, 4}}, + {m68k_op_dbvc_16 , 0xfff8, 0x58c8, { 12, 12, 6}}, + {m68k_op_svc_8_ai , 0xfff8, 0x58d0, { 12, 12, 10}}, + {m68k_op_svc_8_pi , 0xfff8, 0x58d8, { 12, 12, 10}}, + {m68k_op_svc_8_pd , 0xfff8, 0x58e0, { 14, 14, 11}}, + {m68k_op_svc_8_di , 0xfff8, 0x58e8, { 16, 16, 11}}, + {m68k_op_svc_8_ix , 0xfff8, 0x58f0, { 18, 18, 13}}, + {m68k_op_svs_8_d , 0xfff8, 0x59c0, { 4, 4, 4}}, + {m68k_op_dbvs_16 , 0xfff8, 0x59c8, { 12, 12, 6}}, + {m68k_op_svs_8_ai , 0xfff8, 0x59d0, { 12, 12, 10}}, + {m68k_op_svs_8_pi , 0xfff8, 0x59d8, { 12, 12, 10}}, + {m68k_op_svs_8_pd , 0xfff8, 0x59e0, { 14, 14, 11}}, + {m68k_op_svs_8_di , 0xfff8, 0x59e8, { 16, 16, 11}}, + {m68k_op_svs_8_ix , 0xfff8, 0x59f0, { 18, 18, 13}}, + {m68k_op_spl_8_d , 0xfff8, 0x5ac0, { 4, 4, 4}}, + {m68k_op_dbpl_16 , 0xfff8, 0x5ac8, { 12, 12, 6}}, + {m68k_op_spl_8_ai , 0xfff8, 0x5ad0, { 12, 12, 10}}, + {m68k_op_spl_8_pi , 0xfff8, 0x5ad8, { 12, 12, 10}}, + {m68k_op_spl_8_pd , 0xfff8, 0x5ae0, { 14, 14, 11}}, + {m68k_op_spl_8_di , 0xfff8, 0x5ae8, { 16, 16, 11}}, + {m68k_op_spl_8_ix , 0xfff8, 0x5af0, { 18, 18, 13}}, + {m68k_op_smi_8_d , 0xfff8, 0x5bc0, { 4, 4, 4}}, + {m68k_op_dbmi_16 , 0xfff8, 0x5bc8, { 12, 12, 6}}, + {m68k_op_smi_8_ai , 0xfff8, 0x5bd0, { 12, 12, 10}}, + {m68k_op_smi_8_pi , 0xfff8, 0x5bd8, { 12, 12, 10}}, + {m68k_op_smi_8_pd , 0xfff8, 0x5be0, { 14, 14, 11}}, + {m68k_op_smi_8_di , 0xfff8, 0x5be8, { 16, 16, 11}}, + {m68k_op_smi_8_ix , 0xfff8, 0x5bf0, { 18, 18, 13}}, + {m68k_op_sge_8_d , 0xfff8, 0x5cc0, { 4, 4, 4}}, + {m68k_op_dbge_16 , 0xfff8, 0x5cc8, { 12, 12, 6}}, + {m68k_op_sge_8_ai , 0xfff8, 0x5cd0, { 12, 12, 10}}, + {m68k_op_sge_8_pi , 0xfff8, 0x5cd8, { 12, 12, 10}}, + {m68k_op_sge_8_pd , 0xfff8, 0x5ce0, { 14, 14, 11}}, + {m68k_op_sge_8_di , 0xfff8, 0x5ce8, { 16, 16, 11}}, + {m68k_op_sge_8_ix , 0xfff8, 0x5cf0, { 18, 18, 13}}, + {m68k_op_slt_8_d , 0xfff8, 0x5dc0, { 4, 4, 4}}, + {m68k_op_dblt_16 , 0xfff8, 0x5dc8, { 12, 12, 6}}, + {m68k_op_slt_8_ai , 0xfff8, 0x5dd0, { 12, 12, 10}}, + {m68k_op_slt_8_pi , 0xfff8, 0x5dd8, { 12, 12, 10}}, + {m68k_op_slt_8_pd , 0xfff8, 0x5de0, { 14, 14, 11}}, + {m68k_op_slt_8_di , 0xfff8, 0x5de8, { 16, 16, 11}}, + {m68k_op_slt_8_ix , 0xfff8, 0x5df0, { 18, 18, 13}}, + {m68k_op_sgt_8_d , 0xfff8, 0x5ec0, { 4, 4, 4}}, + {m68k_op_dbgt_16 , 0xfff8, 0x5ec8, { 12, 12, 6}}, + {m68k_op_sgt_8_ai , 0xfff8, 0x5ed0, { 12, 12, 10}}, + {m68k_op_sgt_8_pi , 0xfff8, 0x5ed8, { 12, 12, 10}}, + {m68k_op_sgt_8_pd , 0xfff8, 0x5ee0, { 14, 14, 11}}, + {m68k_op_sgt_8_di , 0xfff8, 0x5ee8, { 16, 16, 11}}, + {m68k_op_sgt_8_ix , 0xfff8, 0x5ef0, { 18, 18, 13}}, + {m68k_op_sle_8_d , 0xfff8, 0x5fc0, { 4, 4, 4}}, + {m68k_op_dble_16 , 0xfff8, 0x5fc8, { 12, 12, 6}}, + {m68k_op_sle_8_ai , 0xfff8, 0x5fd0, { 12, 12, 10}}, + {m68k_op_sle_8_pi , 0xfff8, 0x5fd8, { 12, 12, 10}}, + {m68k_op_sle_8_pd , 0xfff8, 0x5fe0, { 14, 14, 11}}, + {m68k_op_sle_8_di , 0xfff8, 0x5fe8, { 16, 16, 11}}, + {m68k_op_sle_8_ix , 0xfff8, 0x5ff0, { 18, 18, 13}}, + {m68k_op_sbcd_8_mm_ax7 , 0xfff8, 0x8f08, { 18, 18, 16}}, + {m68k_op_pack_16_mm_ax7 , 0xfff8, 0x8f48, { 0, 0, 13}}, + {m68k_op_unpk_16_mm_ax7 , 0xfff8, 0x8f88, { 0, 0, 13}}, + {m68k_op_subx_8_mm_ax7 , 0xfff8, 0x9f08, { 18, 18, 12}}, + {m68k_op_cmpm_8_ax7 , 0xfff8, 0xbf08, { 12, 12, 9}}, + {m68k_op_abcd_8_mm_ax7 , 0xfff8, 0xcf08, { 18, 18, 16}}, + {m68k_op_addx_8_mm_ax7 , 0xfff8, 0xdf08, { 18, 18, 12}}, + {m68k_op_asr_16_ai , 0xfff8, 0xe0d0, { 12, 12, 9}}, + {m68k_op_asr_16_pi , 0xfff8, 0xe0d8, { 12, 12, 9}}, + {m68k_op_asr_16_pd , 0xfff8, 0xe0e0, { 14, 14, 10}}, + {m68k_op_asr_16_di , 0xfff8, 0xe0e8, { 16, 16, 10}}, + {m68k_op_asr_16_ix , 0xfff8, 0xe0f0, { 18, 18, 12}}, + {m68k_op_asl_16_ai , 0xfff8, 0xe1d0, { 12, 12, 10}}, + {m68k_op_asl_16_pi , 0xfff8, 0xe1d8, { 12, 12, 10}}, + {m68k_op_asl_16_pd , 0xfff8, 0xe1e0, { 14, 14, 11}}, + {m68k_op_asl_16_di , 0xfff8, 0xe1e8, { 16, 16, 11}}, + {m68k_op_asl_16_ix , 0xfff8, 0xe1f0, { 18, 18, 13}}, + {m68k_op_lsr_16_ai , 0xfff8, 0xe2d0, { 12, 12, 9}}, + {m68k_op_lsr_16_pi , 0xfff8, 0xe2d8, { 12, 12, 9}}, + {m68k_op_lsr_16_pd , 0xfff8, 0xe2e0, { 14, 14, 10}}, + {m68k_op_lsr_16_di , 0xfff8, 0xe2e8, { 16, 16, 10}}, + {m68k_op_lsr_16_ix , 0xfff8, 0xe2f0, { 18, 18, 12}}, + {m68k_op_lsl_16_ai , 0xfff8, 0xe3d0, { 12, 12, 9}}, + {m68k_op_lsl_16_pi , 0xfff8, 0xe3d8, { 12, 12, 9}}, + {m68k_op_lsl_16_pd , 0xfff8, 0xe3e0, { 14, 14, 10}}, + {m68k_op_lsl_16_di , 0xfff8, 0xe3e8, { 16, 16, 10}}, + {m68k_op_lsl_16_ix , 0xfff8, 0xe3f0, { 18, 18, 12}}, + {m68k_op_roxr_16_ai , 0xfff8, 0xe4d0, { 12, 12, 9}}, + {m68k_op_roxr_16_pi , 0xfff8, 0xe4d8, { 12, 12, 9}}, + {m68k_op_roxr_16_pd , 0xfff8, 0xe4e0, { 14, 14, 10}}, + {m68k_op_roxr_16_di , 0xfff8, 0xe4e8, { 16, 16, 10}}, + {m68k_op_roxr_16_ix , 0xfff8, 0xe4f0, { 18, 18, 12}}, + {m68k_op_roxl_16_ai , 0xfff8, 0xe5d0, { 12, 12, 9}}, + {m68k_op_roxl_16_pi , 0xfff8, 0xe5d8, { 12, 12, 9}}, + {m68k_op_roxl_16_pd , 0xfff8, 0xe5e0, { 14, 14, 10}}, + {m68k_op_roxl_16_di , 0xfff8, 0xe5e8, { 16, 16, 10}}, + {m68k_op_roxl_16_ix , 0xfff8, 0xe5f0, { 18, 18, 12}}, + {m68k_op_ror_16_ai , 0xfff8, 0xe6d0, { 12, 12, 11}}, + {m68k_op_ror_16_pi , 0xfff8, 0xe6d8, { 12, 12, 11}}, + {m68k_op_ror_16_pd , 0xfff8, 0xe6e0, { 14, 14, 12}}, + {m68k_op_ror_16_di , 0xfff8, 0xe6e8, { 16, 16, 12}}, + {m68k_op_ror_16_ix , 0xfff8, 0xe6f0, { 18, 18, 14}}, + {m68k_op_rol_16_ai , 0xfff8, 0xe7d0, { 12, 12, 11}}, + {m68k_op_rol_16_pi , 0xfff8, 0xe7d8, { 12, 12, 11}}, + {m68k_op_rol_16_pd , 0xfff8, 0xe7e0, { 14, 14, 12}}, + {m68k_op_rol_16_di , 0xfff8, 0xe7e8, { 16, 16, 12}}, + {m68k_op_rol_16_ix , 0xfff8, 0xe7f0, { 18, 18, 14}}, + {m68k_op_bftst_32_d , 0xfff8, 0xe8c0, { 0, 0, 6}}, + {m68k_op_bftst_32_ai , 0xfff8, 0xe8d0, { 0, 0, 17}}, + {m68k_op_bftst_32_di , 0xfff8, 0xe8e8, { 0, 0, 18}}, + {m68k_op_bftst_32_ix , 0xfff8, 0xe8f0, { 0, 0, 20}}, + {m68k_op_bfextu_32_d , 0xfff8, 0xe9c0, { 0, 0, 8}}, + {m68k_op_bfextu_32_ai , 0xfff8, 0xe9d0, { 0, 0, 19}}, + {m68k_op_bfextu_32_di , 0xfff8, 0xe9e8, { 0, 0, 20}}, + {m68k_op_bfextu_32_ix , 0xfff8, 0xe9f0, { 0, 0, 22}}, + {m68k_op_bfchg_32_d , 0xfff8, 0xeac0, { 0, 0, 12}}, + {m68k_op_bfchg_32_ai , 0xfff8, 0xead0, { 0, 0, 24}}, + {m68k_op_bfchg_32_di , 0xfff8, 0xeae8, { 0, 0, 25}}, + {m68k_op_bfchg_32_ix , 0xfff8, 0xeaf0, { 0, 0, 27}}, + {m68k_op_bfexts_32_d , 0xfff8, 0xebc0, { 0, 0, 8}}, + {m68k_op_bfexts_32_ai , 0xfff8, 0xebd0, { 0, 0, 19}}, + {m68k_op_bfexts_32_di , 0xfff8, 0xebe8, { 0, 0, 20}}, + {m68k_op_bfexts_32_ix , 0xfff8, 0xebf0, { 0, 0, 22}}, + {m68k_op_bfclr_32_d , 0xfff8, 0xecc0, { 0, 0, 12}}, + {m68k_op_bfclr_32_ai , 0xfff8, 0xecd0, { 0, 0, 24}}, + {m68k_op_bfclr_32_di , 0xfff8, 0xece8, { 0, 0, 25}}, + {m68k_op_bfclr_32_ix , 0xfff8, 0xecf0, { 0, 0, 27}}, + {m68k_op_bfffo_32_d , 0xfff8, 0xedc0, { 0, 0, 18}}, + {m68k_op_bfffo_32_ai , 0xfff8, 0xedd0, { 0, 0, 32}}, + {m68k_op_bfffo_32_di , 0xfff8, 0xede8, { 0, 0, 33}}, + {m68k_op_bfffo_32_ix , 0xfff8, 0xedf0, { 0, 0, 35}}, + {m68k_op_bfset_32_d , 0xfff8, 0xeec0, { 0, 0, 12}}, + {m68k_op_bfset_32_ai , 0xfff8, 0xeed0, { 0, 0, 24}}, + {m68k_op_bfset_32_di , 0xfff8, 0xeee8, { 0, 0, 25}}, + {m68k_op_bfset_32_ix , 0xfff8, 0xeef0, { 0, 0, 27}}, + {m68k_op_bfins_32_d , 0xfff8, 0xefc0, { 0, 0, 10}}, + {m68k_op_bfins_32_ai , 0xfff8, 0xefd0, { 0, 0, 21}}, + {m68k_op_bfins_32_di , 0xfff8, 0xefe8, { 0, 0, 22}}, + {m68k_op_bfins_32_ix , 0xfff8, 0xeff0, { 0, 0, 24}}, + {m68k_op_ori_8_pi7 , 0xffff, 0x001f, { 16, 16, 8}}, + {m68k_op_ori_8_pd7 , 0xffff, 0x0027, { 18, 18, 9}}, + {m68k_op_ori_8_aw , 0xffff, 0x0038, { 20, 20, 8}}, + {m68k_op_ori_8_al , 0xffff, 0x0039, { 24, 24, 8}}, + {m68k_op_ori_16_toc , 0xffff, 0x003c, { 20, 16, 12}}, + {m68k_op_ori_16_aw , 0xffff, 0x0078, { 20, 20, 8}}, + {m68k_op_ori_16_al , 0xffff, 0x0079, { 24, 24, 8}}, + {m68k_op_ori_16_tos , 0xffff, 0x007c, { 20, 16, 12}}, + {m68k_op_ori_32_aw , 0xffff, 0x00b8, { 32, 32, 8}}, + {m68k_op_ori_32_al , 0xffff, 0x00b9, { 36, 36, 8}}, + {m68k_op_chk2cmp2_8_aw , 0xffff, 0x00f8, { 0, 0, 22}}, + {m68k_op_chk2cmp2_8_al , 0xffff, 0x00f9, { 0, 0, 22}}, + {m68k_op_chk2cmp2_8_pcdi , 0xffff, 0x00fa, { 0, 0, 23}}, + {m68k_op_chk2cmp2_8_pcix , 0xffff, 0x00fb, { 0, 0, 23}}, + {m68k_op_andi_8_pi7 , 0xffff, 0x021f, { 16, 16, 8}}, + {m68k_op_andi_8_pd7 , 0xffff, 0x0227, { 18, 18, 9}}, + {m68k_op_andi_8_aw , 0xffff, 0x0238, { 20, 20, 8}}, + {m68k_op_andi_8_al , 0xffff, 0x0239, { 24, 24, 8}}, + {m68k_op_andi_16_toc , 0xffff, 0x023c, { 20, 16, 12}}, + {m68k_op_andi_16_aw , 0xffff, 0x0278, { 20, 20, 8}}, + {m68k_op_andi_16_al , 0xffff, 0x0279, { 24, 24, 8}}, + {m68k_op_andi_16_tos , 0xffff, 0x027c, { 20, 16, 12}}, + {m68k_op_andi_32_aw , 0xffff, 0x02b8, { 32, 32, 8}}, + {m68k_op_andi_32_al , 0xffff, 0x02b9, { 36, 36, 8}}, + {m68k_op_chk2cmp2_16_aw , 0xffff, 0x02f8, { 0, 0, 22}}, + {m68k_op_chk2cmp2_16_al , 0xffff, 0x02f9, { 0, 0, 22}}, + {m68k_op_chk2cmp2_16_pcdi , 0xffff, 0x02fa, { 0, 0, 23}}, + {m68k_op_chk2cmp2_16_pcix , 0xffff, 0x02fb, { 0, 0, 23}}, + {m68k_op_subi_8_pi7 , 0xffff, 0x041f, { 16, 16, 8}}, + {m68k_op_subi_8_pd7 , 0xffff, 0x0427, { 18, 18, 9}}, + {m68k_op_subi_8_aw , 0xffff, 0x0438, { 20, 20, 8}}, + {m68k_op_subi_8_al , 0xffff, 0x0439, { 24, 24, 8}}, + {m68k_op_subi_16_aw , 0xffff, 0x0478, { 20, 20, 8}}, + {m68k_op_subi_16_al , 0xffff, 0x0479, { 24, 24, 8}}, + {m68k_op_subi_32_aw , 0xffff, 0x04b8, { 32, 32, 8}}, + {m68k_op_subi_32_al , 0xffff, 0x04b9, { 36, 36, 8}}, + {m68k_op_chk2cmp2_32_aw , 0xffff, 0x04f8, { 0, 0, 22}}, + {m68k_op_chk2cmp2_32_al , 0xffff, 0x04f9, { 0, 0, 22}}, + {m68k_op_chk2cmp2_32_pcdi , 0xffff, 0x04fa, { 0, 0, 23}}, + {m68k_op_chk2cmp2_32_pcix , 0xffff, 0x04fb, { 0, 0, 23}}, + {m68k_op_addi_8_pi7 , 0xffff, 0x061f, { 16, 16, 8}}, + {m68k_op_addi_8_pd7 , 0xffff, 0x0627, { 18, 18, 9}}, + {m68k_op_addi_8_aw , 0xffff, 0x0638, { 20, 20, 8}}, + {m68k_op_addi_8_al , 0xffff, 0x0639, { 24, 24, 8}}, + {m68k_op_addi_16_aw , 0xffff, 0x0678, { 20, 20, 8}}, + {m68k_op_addi_16_al , 0xffff, 0x0679, { 24, 24, 8}}, + {m68k_op_addi_32_aw , 0xffff, 0x06b8, { 32, 32, 8}}, + {m68k_op_addi_32_al , 0xffff, 0x06b9, { 36, 36, 8}}, + {m68k_op_callm_32_aw , 0xffff, 0x06f8, { 0, 0, 64}}, + {m68k_op_callm_32_al , 0xffff, 0x06f9, { 0, 0, 64}}, + {m68k_op_callm_32_pcdi , 0xffff, 0x06fa, { 0, 0, 65}}, + {m68k_op_callm_32_pcix , 0xffff, 0x06fb, { 0, 0, 67}}, + {m68k_op_btst_8_s_pi7 , 0xffff, 0x081f, { 12, 12, 8}}, + {m68k_op_btst_8_s_pd7 , 0xffff, 0x0827, { 14, 14, 9}}, + {m68k_op_btst_8_s_aw , 0xffff, 0x0838, { 16, 16, 8}}, + {m68k_op_btst_8_s_al , 0xffff, 0x0839, { 20, 20, 8}}, + {m68k_op_btst_8_s_pcdi , 0xffff, 0x083a, { 16, 16, 9}}, + {m68k_op_btst_8_s_pcix , 0xffff, 0x083b, { 18, 18, 11}}, + {m68k_op_bchg_8_s_pi7 , 0xffff, 0x085f, { 16, 16, 8}}, + {m68k_op_bchg_8_s_pd7 , 0xffff, 0x0867, { 18, 18, 9}}, + {m68k_op_bchg_8_s_aw , 0xffff, 0x0878, { 20, 20, 8}}, + {m68k_op_bchg_8_s_al , 0xffff, 0x0879, { 24, 24, 8}}, + {m68k_op_bclr_8_s_pi7 , 0xffff, 0x089f, { 16, 16, 8}}, + {m68k_op_bclr_8_s_pd7 , 0xffff, 0x08a7, { 18, 18, 9}}, + {m68k_op_bclr_8_s_aw , 0xffff, 0x08b8, { 20, 20, 8}}, + {m68k_op_bclr_8_s_al , 0xffff, 0x08b9, { 24, 24, 8}}, + {m68k_op_bset_8_s_pi7 , 0xffff, 0x08df, { 16, 16, 8}}, + {m68k_op_bset_8_s_pd7 , 0xffff, 0x08e7, { 18, 18, 9}}, + {m68k_op_bset_8_s_aw , 0xffff, 0x08f8, { 20, 20, 8}}, + {m68k_op_bset_8_s_al , 0xffff, 0x08f9, { 24, 24, 8}}, + {m68k_op_eori_8_pi7 , 0xffff, 0x0a1f, { 16, 16, 8}}, + {m68k_op_eori_8_pd7 , 0xffff, 0x0a27, { 18, 18, 9}}, + {m68k_op_eori_8_aw , 0xffff, 0x0a38, { 20, 20, 8}}, + {m68k_op_eori_8_al , 0xffff, 0x0a39, { 24, 24, 8}}, + {m68k_op_eori_16_toc , 0xffff, 0x0a3c, { 20, 16, 12}}, + {m68k_op_eori_16_aw , 0xffff, 0x0a78, { 20, 20, 8}}, + {m68k_op_eori_16_al , 0xffff, 0x0a79, { 24, 24, 8}}, + {m68k_op_eori_16_tos , 0xffff, 0x0a7c, { 20, 16, 12}}, + {m68k_op_eori_32_aw , 0xffff, 0x0ab8, { 32, 32, 8}}, + {m68k_op_eori_32_al , 0xffff, 0x0ab9, { 36, 36, 8}}, + {m68k_op_cas_8_pi7 , 0xffff, 0x0adf, { 0, 0, 16}}, + {m68k_op_cas_8_pd7 , 0xffff, 0x0ae7, { 0, 0, 17}}, + {m68k_op_cas_8_aw , 0xffff, 0x0af8, { 0, 0, 16}}, + {m68k_op_cas_8_al , 0xffff, 0x0af9, { 0, 0, 16}}, + {m68k_op_cmpi_8_pi7 , 0xffff, 0x0c1f, { 12, 12, 6}}, + {m68k_op_cmpi_8_pd7 , 0xffff, 0x0c27, { 14, 14, 7}}, + {m68k_op_cmpi_8_aw , 0xffff, 0x0c38, { 16, 16, 6}}, + {m68k_op_cmpi_8_al , 0xffff, 0x0c39, { 20, 20, 6}}, + {m68k_op_cmpi_8_pcdi , 0xffff, 0x0c3a, { 0, 0, 7}}, + {m68k_op_cmpi_8_pcix , 0xffff, 0x0c3b, { 0, 0, 9}}, + {m68k_op_cmpi_16_aw , 0xffff, 0x0c78, { 16, 16, 6}}, + {m68k_op_cmpi_16_al , 0xffff, 0x0c79, { 20, 20, 6}}, + {m68k_op_cmpi_16_pcdi , 0xffff, 0x0c7a, { 0, 0, 7}}, + {m68k_op_cmpi_16_pcix , 0xffff, 0x0c7b, { 0, 0, 9}}, + {m68k_op_cmpi_32_aw , 0xffff, 0x0cb8, { 24, 24, 6}}, + {m68k_op_cmpi_32_al , 0xffff, 0x0cb9, { 28, 28, 6}}, + {m68k_op_cmpi_32_pcdi , 0xffff, 0x0cba, { 0, 0, 7}}, + {m68k_op_cmpi_32_pcix , 0xffff, 0x0cbb, { 0, 0, 9}}, + {m68k_op_cas_16_aw , 0xffff, 0x0cf8, { 0, 0, 16}}, + {m68k_op_cas_16_al , 0xffff, 0x0cf9, { 0, 0, 16}}, + {m68k_op_cas2_16 , 0xffff, 0x0cfc, { 0, 0, 12}}, + {m68k_op_moves_8_pi7 , 0xffff, 0x0e1f, { 0, 18, 9}}, + {m68k_op_moves_8_pd7 , 0xffff, 0x0e27, { 0, 20, 10}}, + {m68k_op_moves_8_aw , 0xffff, 0x0e38, { 0, 26, 9}}, + {m68k_op_moves_8_al , 0xffff, 0x0e39, { 0, 30, 9}}, + {m68k_op_moves_16_aw , 0xffff, 0x0e78, { 0, 26, 9}}, + {m68k_op_moves_16_al , 0xffff, 0x0e79, { 0, 30, 9}}, + {m68k_op_moves_32_aw , 0xffff, 0x0eb8, { 0, 32, 9}}, + {m68k_op_moves_32_al , 0xffff, 0x0eb9, { 0, 36, 9}}, + {m68k_op_cas_32_aw , 0xffff, 0x0ef8, { 0, 0, 16}}, + {m68k_op_cas_32_al , 0xffff, 0x0ef9, { 0, 0, 16}}, + {m68k_op_cas2_32 , 0xffff, 0x0efc, { 0, 0, 12}}, + {m68k_op_move_8_aw_pi7 , 0xffff, 0x11df, { 16, 16, 8}}, + {m68k_op_move_8_aw_pd7 , 0xffff, 0x11e7, { 18, 18, 9}}, + {m68k_op_move_8_aw_aw , 0xffff, 0x11f8, { 20, 20, 8}}, + {m68k_op_move_8_aw_al , 0xffff, 0x11f9, { 24, 24, 8}}, + {m68k_op_move_8_aw_pcdi , 0xffff, 0x11fa, { 20, 20, 9}}, + {m68k_op_move_8_aw_pcix , 0xffff, 0x11fb, { 22, 22, 11}}, + {m68k_op_move_8_aw_i , 0xffff, 0x11fc, { 16, 16, 6}}, + {m68k_op_move_8_al_pi7 , 0xffff, 0x13df, { 20, 20, 10}}, + {m68k_op_move_8_al_pd7 , 0xffff, 0x13e7, { 22, 22, 11}}, + {m68k_op_move_8_al_aw , 0xffff, 0x13f8, { 24, 24, 10}}, + {m68k_op_move_8_al_al , 0xffff, 0x13f9, { 28, 28, 10}}, + {m68k_op_move_8_al_pcdi , 0xffff, 0x13fa, { 24, 24, 11}}, + {m68k_op_move_8_al_pcix , 0xffff, 0x13fb, { 26, 26, 13}}, + {m68k_op_move_8_al_i , 0xffff, 0x13fc, { 20, 20, 8}}, + {m68k_op_move_8_pi7_pi7 , 0xffff, 0x1edf, { 12, 12, 8}}, + {m68k_op_move_8_pi7_pd7 , 0xffff, 0x1ee7, { 14, 14, 9}}, + {m68k_op_move_8_pi7_aw , 0xffff, 0x1ef8, { 16, 16, 8}}, + {m68k_op_move_8_pi7_al , 0xffff, 0x1ef9, { 20, 20, 8}}, + {m68k_op_move_8_pi7_pcdi , 0xffff, 0x1efa, { 16, 16, 9}}, + {m68k_op_move_8_pi7_pcix , 0xffff, 0x1efb, { 18, 18, 11}}, + {m68k_op_move_8_pi7_i , 0xffff, 0x1efc, { 12, 12, 6}}, + {m68k_op_move_8_pd7_pi7 , 0xffff, 0x1f1f, { 12, 12, 9}}, + {m68k_op_move_8_pd7_pd7 , 0xffff, 0x1f27, { 14, 14, 10}}, + {m68k_op_move_8_pd7_aw , 0xffff, 0x1f38, { 16, 16, 9}}, + {m68k_op_move_8_pd7_al , 0xffff, 0x1f39, { 20, 20, 9}}, + {m68k_op_move_8_pd7_pcdi , 0xffff, 0x1f3a, { 16, 16, 10}}, + {m68k_op_move_8_pd7_pcix , 0xffff, 0x1f3b, { 18, 18, 12}}, + {m68k_op_move_8_pd7_i , 0xffff, 0x1f3c, { 12, 12, 7}}, + {m68k_op_move_32_aw_aw , 0xffff, 0x21f8, { 28, 28, 8}}, + {m68k_op_move_32_aw_al , 0xffff, 0x21f9, { 32, 32, 8}}, + {m68k_op_move_32_aw_pcdi , 0xffff, 0x21fa, { 28, 28, 9}}, + {m68k_op_move_32_aw_pcix , 0xffff, 0x21fb, { 30, 30, 11}}, + {m68k_op_move_32_aw_i , 0xffff, 0x21fc, { 24, 24, 8}}, + {m68k_op_move_32_al_aw , 0xffff, 0x23f8, { 32, 32, 10}}, + {m68k_op_move_32_al_al , 0xffff, 0x23f9, { 36, 36, 10}}, + {m68k_op_move_32_al_pcdi , 0xffff, 0x23fa, { 32, 32, 11}}, + {m68k_op_move_32_al_pcix , 0xffff, 0x23fb, { 34, 34, 13}}, + {m68k_op_move_32_al_i , 0xffff, 0x23fc, { 28, 28, 10}}, + {m68k_op_move_16_aw_aw , 0xffff, 0x31f8, { 20, 20, 8}}, + {m68k_op_move_16_aw_al , 0xffff, 0x31f9, { 24, 24, 8}}, + {m68k_op_move_16_aw_pcdi , 0xffff, 0x31fa, { 20, 20, 9}}, + {m68k_op_move_16_aw_pcix , 0xffff, 0x31fb, { 22, 22, 11}}, + {m68k_op_move_16_aw_i , 0xffff, 0x31fc, { 16, 16, 6}}, + {m68k_op_move_16_al_aw , 0xffff, 0x33f8, { 24, 24, 10}}, + {m68k_op_move_16_al_al , 0xffff, 0x33f9, { 28, 28, 10}}, + {m68k_op_move_16_al_pcdi , 0xffff, 0x33fa, { 24, 24, 11}}, + {m68k_op_move_16_al_pcix , 0xffff, 0x33fb, { 26, 26, 13}}, + {m68k_op_move_16_al_i , 0xffff, 0x33fc, { 20, 20, 8}}, + {m68k_op_negx_8_pi7 , 0xffff, 0x401f, { 12, 12, 8}}, + {m68k_op_negx_8_pd7 , 0xffff, 0x4027, { 14, 14, 9}}, + {m68k_op_negx_8_aw , 0xffff, 0x4038, { 16, 16, 8}}, + {m68k_op_negx_8_al , 0xffff, 0x4039, { 20, 20, 8}}, + {m68k_op_negx_16_aw , 0xffff, 0x4078, { 16, 16, 8}}, + {m68k_op_negx_16_al , 0xffff, 0x4079, { 20, 20, 8}}, + {m68k_op_negx_32_aw , 0xffff, 0x40b8, { 24, 24, 8}}, + {m68k_op_negx_32_al , 0xffff, 0x40b9, { 28, 28, 8}}, + {m68k_op_move_16_frs_aw , 0xffff, 0x40f8, { 16, 16, 12}}, + {m68k_op_move_16_frs_al , 0xffff, 0x40f9, { 20, 20, 12}}, + {m68k_op_clr_8_pi7 , 0xffff, 0x421f, { 12, 8, 8}}, + {m68k_op_clr_8_pd7 , 0xffff, 0x4227, { 14, 10, 9}}, + {m68k_op_clr_8_aw , 0xffff, 0x4238, { 16, 12, 8}}, + {m68k_op_clr_8_al , 0xffff, 0x4239, { 20, 14, 8}}, + {m68k_op_clr_16_aw , 0xffff, 0x4278, { 16, 12, 8}}, + {m68k_op_clr_16_al , 0xffff, 0x4279, { 20, 14, 8}}, + {m68k_op_clr_32_aw , 0xffff, 0x42b8, { 24, 16, 8}}, + {m68k_op_clr_32_al , 0xffff, 0x42b9, { 28, 20, 8}}, + {m68k_op_move_16_frc_aw , 0xffff, 0x42f8, { 0, 16, 8}}, + {m68k_op_move_16_frc_al , 0xffff, 0x42f9, { 0, 20, 8}}, + {m68k_op_neg_8_pi7 , 0xffff, 0x441f, { 12, 12, 8}}, + {m68k_op_neg_8_pd7 , 0xffff, 0x4427, { 14, 14, 9}}, + {m68k_op_neg_8_aw , 0xffff, 0x4438, { 16, 16, 8}}, + {m68k_op_neg_8_al , 0xffff, 0x4439, { 20, 20, 8}}, + {m68k_op_neg_16_aw , 0xffff, 0x4478, { 16, 16, 8}}, + {m68k_op_neg_16_al , 0xffff, 0x4479, { 20, 20, 8}}, + {m68k_op_neg_32_aw , 0xffff, 0x44b8, { 24, 24, 8}}, + {m68k_op_neg_32_al , 0xffff, 0x44b9, { 28, 28, 8}}, + {m68k_op_move_16_toc_aw , 0xffff, 0x44f8, { 20, 20, 8}}, + {m68k_op_move_16_toc_al , 0xffff, 0x44f9, { 24, 24, 8}}, + {m68k_op_move_16_toc_pcdi , 0xffff, 0x44fa, { 20, 20, 9}}, + {m68k_op_move_16_toc_pcix , 0xffff, 0x44fb, { 22, 22, 11}}, + {m68k_op_move_16_toc_i , 0xffff, 0x44fc, { 16, 16, 6}}, + {m68k_op_not_8_pi7 , 0xffff, 0x461f, { 12, 12, 8}}, + {m68k_op_not_8_pd7 , 0xffff, 0x4627, { 14, 14, 9}}, + {m68k_op_not_8_aw , 0xffff, 0x4638, { 16, 16, 8}}, + {m68k_op_not_8_al , 0xffff, 0x4639, { 20, 20, 8}}, + {m68k_op_not_16_aw , 0xffff, 0x4678, { 16, 16, 8}}, + {m68k_op_not_16_al , 0xffff, 0x4679, { 20, 20, 8}}, + {m68k_op_not_32_aw , 0xffff, 0x46b8, { 24, 24, 8}}, + {m68k_op_not_32_al , 0xffff, 0x46b9, { 28, 28, 8}}, + {m68k_op_move_16_tos_aw , 0xffff, 0x46f8, { 20, 20, 12}}, + {m68k_op_move_16_tos_al , 0xffff, 0x46f9, { 24, 24, 12}}, + {m68k_op_move_16_tos_pcdi , 0xffff, 0x46fa, { 20, 20, 13}}, + {m68k_op_move_16_tos_pcix , 0xffff, 0x46fb, { 22, 22, 15}}, + {m68k_op_move_16_tos_i , 0xffff, 0x46fc, { 16, 16, 10}}, + {m68k_op_link_32_a7 , 0xffff, 0x480f, { 0, 0, 6}}, + {m68k_op_nbcd_8_pi7 , 0xffff, 0x481f, { 12, 12, 10}}, + {m68k_op_nbcd_8_pd7 , 0xffff, 0x4827, { 14, 14, 11}}, + {m68k_op_nbcd_8_aw , 0xffff, 0x4838, { 16, 16, 10}}, + {m68k_op_nbcd_8_al , 0xffff, 0x4839, { 20, 20, 10}}, + {m68k_op_pea_32_aw , 0xffff, 0x4878, { 16, 16, 9}}, + {m68k_op_pea_32_al , 0xffff, 0x4879, { 20, 20, 9}}, + {m68k_op_pea_32_pcdi , 0xffff, 0x487a, { 16, 16, 10}}, + {m68k_op_pea_32_pcix , 0xffff, 0x487b, { 20, 20, 12}}, + {m68k_op_movem_16_re_aw , 0xffff, 0x48b8, { 16, 16, 8}}, + {m68k_op_movem_16_re_al , 0xffff, 0x48b9, { 20, 20, 8}}, + {m68k_op_movem_32_re_aw , 0xffff, 0x48f8, { 20, 20, 8}}, + {m68k_op_movem_32_re_al , 0xffff, 0x48f9, { 24, 24, 8}}, + {m68k_op_tst_8_pi7 , 0xffff, 0x4a1f, { 8, 8, 6}}, + {m68k_op_tst_8_pd7 , 0xffff, 0x4a27, { 10, 10, 7}}, + {m68k_op_tst_8_aw , 0xffff, 0x4a38, { 12, 12, 6}}, + {m68k_op_tst_8_al , 0xffff, 0x4a39, { 16, 16, 6}}, + {m68k_op_tst_8_pcdi , 0xffff, 0x4a3a, { 0, 0, 7}}, + {m68k_op_tst_8_pcix , 0xffff, 0x4a3b, { 0, 0, 9}}, + {m68k_op_tst_8_i , 0xffff, 0x4a3c, { 0, 0, 6}}, + {m68k_op_tst_16_aw , 0xffff, 0x4a78, { 12, 12, 6}}, + {m68k_op_tst_16_al , 0xffff, 0x4a79, { 16, 16, 6}}, + {m68k_op_tst_16_pcdi , 0xffff, 0x4a7a, { 0, 0, 7}}, + {m68k_op_tst_16_pcix , 0xffff, 0x4a7b, { 0, 0, 9}}, + {m68k_op_tst_16_i , 0xffff, 0x4a7c, { 0, 0, 6}}, + {m68k_op_tst_32_aw , 0xffff, 0x4ab8, { 16, 16, 6}}, + {m68k_op_tst_32_al , 0xffff, 0x4ab9, { 20, 20, 6}}, + {m68k_op_tst_32_pcdi , 0xffff, 0x4aba, { 0, 0, 7}}, + {m68k_op_tst_32_pcix , 0xffff, 0x4abb, { 0, 0, 9}}, + {m68k_op_tst_32_i , 0xffff, 0x4abc, { 0, 0, 6}}, + {m68k_op_tas_8_pi7 , 0xffff, 0x4adf, { 18, 18, 16}}, + {m68k_op_tas_8_pd7 , 0xffff, 0x4ae7, { 20, 20, 17}}, + {m68k_op_tas_8_aw , 0xffff, 0x4af8, { 22, 22, 16}}, + {m68k_op_tas_8_al , 0xffff, 0x4af9, { 26, 26, 16}}, + {m68k_op_illegal , 0xffff, 0x4afc, { 4, 4, 4}}, + {m68k_op_mull_32_aw , 0xffff, 0x4c38, { 0, 0, 47}}, + {m68k_op_mull_32_al , 0xffff, 0x4c39, { 0, 0, 47}}, + {m68k_op_mull_32_pcdi , 0xffff, 0x4c3a, { 0, 0, 48}}, + {m68k_op_mull_32_pcix , 0xffff, 0x4c3b, { 0, 0, 50}}, + {m68k_op_mull_32_i , 0xffff, 0x4c3c, { 0, 0, 47}}, + {m68k_op_divl_32_aw , 0xffff, 0x4c78, { 0, 0, 88}}, + {m68k_op_divl_32_al , 0xffff, 0x4c79, { 0, 0, 88}}, + {m68k_op_divl_32_pcdi , 0xffff, 0x4c7a, { 0, 0, 89}}, + {m68k_op_divl_32_pcix , 0xffff, 0x4c7b, { 0, 0, 91}}, + {m68k_op_divl_32_i , 0xffff, 0x4c7c, { 0, 0, 88}}, + {m68k_op_movem_16_er_aw , 0xffff, 0x4cb8, { 20, 20, 12}}, + {m68k_op_movem_16_er_al , 0xffff, 0x4cb9, { 24, 24, 12}}, + {m68k_op_movem_16_er_pcdi , 0xffff, 0x4cba, { 16, 16, 9}}, + {m68k_op_movem_16_er_pcix , 0xffff, 0x4cbb, { 18, 18, 11}}, + {m68k_op_movem_32_er_aw , 0xffff, 0x4cf8, { 24, 24, 12}}, + {m68k_op_movem_32_er_al , 0xffff, 0x4cf9, { 28, 28, 12}}, + {m68k_op_movem_32_er_pcdi , 0xffff, 0x4cfa, { 20, 20, 9}}, + {m68k_op_movem_32_er_pcix , 0xffff, 0x4cfb, { 22, 22, 11}}, + {m68k_op_link_16_a7 , 0xffff, 0x4e57, { 16, 16, 5}}, + {m68k_op_unlk_32_a7 , 0xffff, 0x4e5f, { 12, 12, 6}}, + {m68k_op_reset , 0xffff, 0x4e70, { 0, 0, 0}}, + {m68k_op_nop , 0xffff, 0x4e71, { 4, 4, 2}}, + {m68k_op_stop , 0xffff, 0x4e72, { 4, 4, 8}}, + {m68k_op_rte_32 , 0xffff, 0x4e73, { 20, 24, 20}}, + {m68k_op_rtd_32 , 0xffff, 0x4e74, { 0, 16, 10}}, + {m68k_op_rts_32 , 0xffff, 0x4e75, { 16, 16, 10}}, + {m68k_op_trapv , 0xffff, 0x4e76, { 4, 4, 4}}, + {m68k_op_rtr_32 , 0xffff, 0x4e77, { 20, 20, 14}}, + {m68k_op_movec_32_cr , 0xffff, 0x4e7a, { 0, 12, 6}}, + {m68k_op_movec_32_rc , 0xffff, 0x4e7b, { 0, 10, 12}}, + {m68k_op_jsr_32_aw , 0xffff, 0x4eb8, { 18, 18, 4}}, + {m68k_op_jsr_32_al , 0xffff, 0x4eb9, { 20, 20, 4}}, + {m68k_op_jsr_32_pcdi , 0xffff, 0x4eba, { 18, 18, 5}}, + {m68k_op_jsr_32_pcix , 0xffff, 0x4ebb, { 22, 22, 7}}, + {m68k_op_jmp_32_aw , 0xffff, 0x4ef8, { 10, 10, 4}}, + {m68k_op_jmp_32_al , 0xffff, 0x4ef9, { 12, 12, 4}}, + {m68k_op_jmp_32_pcdi , 0xffff, 0x4efa, { 10, 10, 5}}, + {m68k_op_jmp_32_pcix , 0xffff, 0x4efb, { 14, 14, 7}}, + {m68k_op_st_8_pi7 , 0xffff, 0x50df, { 12, 12, 10}}, + {m68k_op_st_8_pd7 , 0xffff, 0x50e7, { 14, 14, 11}}, + {m68k_op_st_8_aw , 0xffff, 0x50f8, { 16, 16, 10}}, + {m68k_op_st_8_al , 0xffff, 0x50f9, { 20, 20, 10}}, + {m68k_op_trapt_16 , 0xffff, 0x50fa, { 0, 0, 6}}, + {m68k_op_trapt_32 , 0xffff, 0x50fb, { 0, 0, 8}}, + {m68k_op_trapt , 0xffff, 0x50fc, { 0, 0, 4}}, + {m68k_op_sf_8_pi7 , 0xffff, 0x51df, { 12, 12, 10}}, + {m68k_op_sf_8_pd7 , 0xffff, 0x51e7, { 14, 14, 11}}, + {m68k_op_sf_8_aw , 0xffff, 0x51f8, { 16, 16, 10}}, + {m68k_op_sf_8_al , 0xffff, 0x51f9, { 20, 20, 10}}, + {m68k_op_trapf_16 , 0xffff, 0x51fa, { 0, 0, 6}}, + {m68k_op_trapf_32 , 0xffff, 0x51fb, { 0, 0, 8}}, + {m68k_op_trapf , 0xffff, 0x51fc, { 0, 0, 4}}, + {m68k_op_shi_8_pi7 , 0xffff, 0x52df, { 12, 12, 10}}, + {m68k_op_shi_8_pd7 , 0xffff, 0x52e7, { 14, 14, 11}}, + {m68k_op_shi_8_aw , 0xffff, 0x52f8, { 16, 16, 10}}, + {m68k_op_shi_8_al , 0xffff, 0x52f9, { 20, 20, 10}}, + {m68k_op_traphi_16 , 0xffff, 0x52fa, { 0, 0, 6}}, + {m68k_op_traphi_32 , 0xffff, 0x52fb, { 0, 0, 8}}, + {m68k_op_traphi , 0xffff, 0x52fc, { 0, 0, 4}}, + {m68k_op_sls_8_pi7 , 0xffff, 0x53df, { 12, 12, 10}}, + {m68k_op_sls_8_pd7 , 0xffff, 0x53e7, { 14, 14, 11}}, + {m68k_op_sls_8_aw , 0xffff, 0x53f8, { 16, 16, 10}}, + {m68k_op_sls_8_al , 0xffff, 0x53f9, { 20, 20, 10}}, + {m68k_op_trapls_16 , 0xffff, 0x53fa, { 0, 0, 6}}, + {m68k_op_trapls_32 , 0xffff, 0x53fb, { 0, 0, 8}}, + {m68k_op_trapls , 0xffff, 0x53fc, { 0, 0, 4}}, + {m68k_op_scc_8_pi7 , 0xffff, 0x54df, { 12, 12, 10}}, + {m68k_op_scc_8_pd7 , 0xffff, 0x54e7, { 14, 14, 11}}, + {m68k_op_scc_8_aw , 0xffff, 0x54f8, { 16, 16, 10}}, + {m68k_op_scc_8_al , 0xffff, 0x54f9, { 20, 20, 10}}, + {m68k_op_trapcc_16 , 0xffff, 0x54fa, { 0, 0, 6}}, + {m68k_op_trapcc_32 , 0xffff, 0x54fb, { 0, 0, 8}}, + {m68k_op_trapcc , 0xffff, 0x54fc, { 0, 0, 4}}, + {m68k_op_scs_8_pi7 , 0xffff, 0x55df, { 12, 12, 10}}, + {m68k_op_scs_8_pd7 , 0xffff, 0x55e7, { 14, 14, 11}}, + {m68k_op_scs_8_aw , 0xffff, 0x55f8, { 16, 16, 10}}, + {m68k_op_scs_8_al , 0xffff, 0x55f9, { 20, 20, 10}}, + {m68k_op_trapcs_16 , 0xffff, 0x55fa, { 0, 0, 6}}, + {m68k_op_trapcs_32 , 0xffff, 0x55fb, { 0, 0, 8}}, + {m68k_op_trapcs , 0xffff, 0x55fc, { 0, 0, 4}}, + {m68k_op_sne_8_pi7 , 0xffff, 0x56df, { 12, 12, 10}}, + {m68k_op_sne_8_pd7 , 0xffff, 0x56e7, { 14, 14, 11}}, + {m68k_op_sne_8_aw , 0xffff, 0x56f8, { 16, 16, 10}}, + {m68k_op_sne_8_al , 0xffff, 0x56f9, { 20, 20, 10}}, + {m68k_op_trapne_16 , 0xffff, 0x56fa, { 0, 0, 6}}, + {m68k_op_trapne_32 , 0xffff, 0x56fb, { 0, 0, 8}}, + {m68k_op_trapne , 0xffff, 0x56fc, { 0, 0, 4}}, + {m68k_op_seq_8_pi7 , 0xffff, 0x57df, { 12, 12, 10}}, + {m68k_op_seq_8_pd7 , 0xffff, 0x57e7, { 14, 14, 11}}, + {m68k_op_seq_8_aw , 0xffff, 0x57f8, { 16, 16, 10}}, + {m68k_op_seq_8_al , 0xffff, 0x57f9, { 20, 20, 10}}, + {m68k_op_trapeq_16 , 0xffff, 0x57fa, { 0, 0, 6}}, + {m68k_op_trapeq_32 , 0xffff, 0x57fb, { 0, 0, 8}}, + {m68k_op_trapeq , 0xffff, 0x57fc, { 0, 0, 4}}, + {m68k_op_svc_8_pi7 , 0xffff, 0x58df, { 12, 12, 10}}, + {m68k_op_svc_8_pd7 , 0xffff, 0x58e7, { 14, 14, 11}}, + {m68k_op_svc_8_aw , 0xffff, 0x58f8, { 16, 16, 10}}, + {m68k_op_svc_8_al , 0xffff, 0x58f9, { 20, 20, 10}}, + {m68k_op_trapvc_16 , 0xffff, 0x58fa, { 0, 0, 6}}, + {m68k_op_trapvc_32 , 0xffff, 0x58fb, { 0, 0, 8}}, + {m68k_op_trapvc , 0xffff, 0x58fc, { 0, 0, 4}}, + {m68k_op_svs_8_pi7 , 0xffff, 0x59df, { 12, 12, 10}}, + {m68k_op_svs_8_pd7 , 0xffff, 0x59e7, { 14, 14, 11}}, + {m68k_op_svs_8_aw , 0xffff, 0x59f8, { 16, 16, 10}}, + {m68k_op_svs_8_al , 0xffff, 0x59f9, { 20, 20, 10}}, + {m68k_op_trapvs_16 , 0xffff, 0x59fa, { 0, 0, 6}}, + {m68k_op_trapvs_32 , 0xffff, 0x59fb, { 0, 0, 8}}, + {m68k_op_trapvs , 0xffff, 0x59fc, { 0, 0, 4}}, + {m68k_op_spl_8_pi7 , 0xffff, 0x5adf, { 12, 12, 10}}, + {m68k_op_spl_8_pd7 , 0xffff, 0x5ae7, { 14, 14, 11}}, + {m68k_op_spl_8_aw , 0xffff, 0x5af8, { 16, 16, 10}}, + {m68k_op_spl_8_al , 0xffff, 0x5af9, { 20, 20, 10}}, + {m68k_op_trappl_16 , 0xffff, 0x5afa, { 0, 0, 6}}, + {m68k_op_trappl_32 , 0xffff, 0x5afb, { 0, 0, 8}}, + {m68k_op_trappl , 0xffff, 0x5afc, { 0, 0, 4}}, + {m68k_op_smi_8_pi7 , 0xffff, 0x5bdf, { 12, 12, 10}}, + {m68k_op_smi_8_pd7 , 0xffff, 0x5be7, { 14, 14, 11}}, + {m68k_op_smi_8_aw , 0xffff, 0x5bf8, { 16, 16, 10}}, + {m68k_op_smi_8_al , 0xffff, 0x5bf9, { 20, 20, 10}}, + {m68k_op_trapmi_16 , 0xffff, 0x5bfa, { 0, 0, 6}}, + {m68k_op_trapmi_32 , 0xffff, 0x5bfb, { 0, 0, 8}}, + {m68k_op_trapmi , 0xffff, 0x5bfc, { 0, 0, 4}}, + {m68k_op_sge_8_pi7 , 0xffff, 0x5cdf, { 12, 12, 10}}, + {m68k_op_sge_8_pd7 , 0xffff, 0x5ce7, { 14, 14, 11}}, + {m68k_op_sge_8_aw , 0xffff, 0x5cf8, { 16, 16, 10}}, + {m68k_op_sge_8_al , 0xffff, 0x5cf9, { 20, 20, 10}}, + {m68k_op_trapge_16 , 0xffff, 0x5cfa, { 0, 0, 6}}, + {m68k_op_trapge_32 , 0xffff, 0x5cfb, { 0, 0, 8}}, + {m68k_op_trapge , 0xffff, 0x5cfc, { 0, 0, 4}}, + {m68k_op_slt_8_pi7 , 0xffff, 0x5ddf, { 12, 12, 10}}, + {m68k_op_slt_8_pd7 , 0xffff, 0x5de7, { 14, 14, 11}}, + {m68k_op_slt_8_aw , 0xffff, 0x5df8, { 16, 16, 10}}, + {m68k_op_slt_8_al , 0xffff, 0x5df9, { 20, 20, 10}}, + {m68k_op_traplt_16 , 0xffff, 0x5dfa, { 0, 0, 6}}, + {m68k_op_traplt_32 , 0xffff, 0x5dfb, { 0, 0, 8}}, + {m68k_op_traplt , 0xffff, 0x5dfc, { 0, 0, 4}}, + {m68k_op_sgt_8_pi7 , 0xffff, 0x5edf, { 12, 12, 10}}, + {m68k_op_sgt_8_pd7 , 0xffff, 0x5ee7, { 14, 14, 11}}, + {m68k_op_sgt_8_aw , 0xffff, 0x5ef8, { 16, 16, 10}}, + {m68k_op_sgt_8_al , 0xffff, 0x5ef9, { 20, 20, 10}}, + {m68k_op_trapgt_16 , 0xffff, 0x5efa, { 0, 0, 6}}, + {m68k_op_trapgt_32 , 0xffff, 0x5efb, { 0, 0, 8}}, + {m68k_op_trapgt , 0xffff, 0x5efc, { 0, 0, 4}}, + {m68k_op_sle_8_pi7 , 0xffff, 0x5fdf, { 12, 12, 10}}, + {m68k_op_sle_8_pd7 , 0xffff, 0x5fe7, { 14, 14, 11}}, + {m68k_op_sle_8_aw , 0xffff, 0x5ff8, { 16, 16, 10}}, + {m68k_op_sle_8_al , 0xffff, 0x5ff9, { 20, 20, 10}}, + {m68k_op_traple_16 , 0xffff, 0x5ffa, { 0, 0, 6}}, + {m68k_op_traple_32 , 0xffff, 0x5ffb, { 0, 0, 8}}, + {m68k_op_traple , 0xffff, 0x5ffc, { 0, 0, 4}}, + {m68k_op_bra_16 , 0xffff, 0x6000, { 10, 10, 10}}, + {m68k_op_bra_32 , 0xffff, 0x60ff, { 0, 0, 10}}, + {m68k_op_bsr_16 , 0xffff, 0x6100, { 18, 18, 7}}, + {m68k_op_bsr_32 , 0xffff, 0x61ff, { 0, 0, 7}}, + {m68k_op_bhi_16 , 0xffff, 0x6200, { 10, 10, 6}}, + {m68k_op_bhi_32 , 0xffff, 0x62ff, { 0, 0, 6}}, + {m68k_op_bls_16 , 0xffff, 0x6300, { 10, 10, 6}}, + {m68k_op_bls_32 , 0xffff, 0x63ff, { 0, 0, 6}}, + {m68k_op_bcc_16 , 0xffff, 0x6400, { 10, 10, 6}}, + {m68k_op_bcc_32 , 0xffff, 0x64ff, { 0, 0, 6}}, + {m68k_op_bcs_16 , 0xffff, 0x6500, { 10, 10, 6}}, + {m68k_op_bcs_32 , 0xffff, 0x65ff, { 0, 0, 6}}, + {m68k_op_bne_16 , 0xffff, 0x6600, { 10, 10, 6}}, + {m68k_op_bne_32 , 0xffff, 0x66ff, { 0, 0, 6}}, + {m68k_op_beq_16 , 0xffff, 0x6700, { 10, 10, 6}}, + {m68k_op_beq_32 , 0xffff, 0x67ff, { 0, 0, 6}}, + {m68k_op_bvc_16 , 0xffff, 0x6800, { 10, 10, 6}}, + {m68k_op_bvc_32 , 0xffff, 0x68ff, { 0, 0, 6}}, + {m68k_op_bvs_16 , 0xffff, 0x6900, { 10, 10, 6}}, + {m68k_op_bvs_32 , 0xffff, 0x69ff, { 0, 0, 6}}, + {m68k_op_bpl_16 , 0xffff, 0x6a00, { 10, 10, 6}}, + {m68k_op_bpl_32 , 0xffff, 0x6aff, { 0, 0, 6}}, + {m68k_op_bmi_16 , 0xffff, 0x6b00, { 10, 10, 6}}, + {m68k_op_bmi_32 , 0xffff, 0x6bff, { 0, 0, 6}}, + {m68k_op_bge_16 , 0xffff, 0x6c00, { 10, 10, 6}}, + {m68k_op_bge_32 , 0xffff, 0x6cff, { 0, 0, 6}}, + {m68k_op_blt_16 , 0xffff, 0x6d00, { 10, 10, 6}}, + {m68k_op_blt_32 , 0xffff, 0x6dff, { 0, 0, 6}}, + {m68k_op_bgt_16 , 0xffff, 0x6e00, { 10, 10, 6}}, + {m68k_op_bgt_32 , 0xffff, 0x6eff, { 0, 0, 6}}, + {m68k_op_ble_16 , 0xffff, 0x6f00, { 10, 10, 6}}, + {m68k_op_ble_32 , 0xffff, 0x6fff, { 0, 0, 6}}, + {m68k_op_sbcd_8_mm_axy7 , 0xffff, 0x8f0f, { 18, 18, 16}}, + {m68k_op_pack_16_mm_axy7 , 0xffff, 0x8f4f, { 0, 0, 13}}, + {m68k_op_unpk_16_mm_axy7 , 0xffff, 0x8f8f, { 0, 0, 13}}, + {m68k_op_subx_8_mm_axy7 , 0xffff, 0x9f0f, { 18, 18, 12}}, + {m68k_op_cmpm_8_axy7 , 0xffff, 0xbf0f, { 12, 12, 9}}, + {m68k_op_abcd_8_mm_axy7 , 0xffff, 0xcf0f, { 18, 18, 16}}, + {m68k_op_addx_8_mm_axy7 , 0xffff, 0xdf0f, { 18, 18, 12}}, + {m68k_op_asr_16_aw , 0xffff, 0xe0f8, { 16, 16, 9}}, + {m68k_op_asr_16_al , 0xffff, 0xe0f9, { 20, 20, 9}}, + {m68k_op_asl_16_aw , 0xffff, 0xe1f8, { 16, 16, 10}}, + {m68k_op_asl_16_al , 0xffff, 0xe1f9, { 20, 20, 10}}, + {m68k_op_lsr_16_aw , 0xffff, 0xe2f8, { 16, 16, 9}}, + {m68k_op_lsr_16_al , 0xffff, 0xe2f9, { 20, 20, 9}}, + {m68k_op_lsl_16_aw , 0xffff, 0xe3f8, { 16, 16, 9}}, + {m68k_op_lsl_16_al , 0xffff, 0xe3f9, { 20, 20, 9}}, + {m68k_op_roxr_16_aw , 0xffff, 0xe4f8, { 16, 16, 9}}, + {m68k_op_roxr_16_al , 0xffff, 0xe4f9, { 20, 20, 9}}, + {m68k_op_roxl_16_aw , 0xffff, 0xe5f8, { 16, 16, 9}}, + {m68k_op_roxl_16_al , 0xffff, 0xe5f9, { 20, 20, 9}}, + {m68k_op_ror_16_aw , 0xffff, 0xe6f8, { 16, 16, 11}}, + {m68k_op_ror_16_al , 0xffff, 0xe6f9, { 20, 20, 11}}, + {m68k_op_rol_16_aw , 0xffff, 0xe7f8, { 16, 16, 11}}, + {m68k_op_rol_16_al , 0xffff, 0xe7f9, { 20, 20, 11}}, + {m68k_op_bftst_32_aw , 0xffff, 0xe8f8, { 0, 0, 17}}, + {m68k_op_bftst_32_al , 0xffff, 0xe8f9, { 0, 0, 17}}, + {m68k_op_bftst_32_pcdi , 0xffff, 0xe8fa, { 0, 0, 18}}, + {m68k_op_bftst_32_pcix , 0xffff, 0xe8fb, { 0, 0, 20}}, + {m68k_op_bfextu_32_aw , 0xffff, 0xe9f8, { 0, 0, 19}}, + {m68k_op_bfextu_32_al , 0xffff, 0xe9f9, { 0, 0, 19}}, + {m68k_op_bfextu_32_pcdi , 0xffff, 0xe9fa, { 0, 0, 20}}, + {m68k_op_bfextu_32_pcix , 0xffff, 0xe9fb, { 0, 0, 22}}, + {m68k_op_bfchg_32_aw , 0xffff, 0xeaf8, { 0, 0, 24}}, + {m68k_op_bfchg_32_al , 0xffff, 0xeaf9, { 0, 0, 24}}, + {m68k_op_bfexts_32_aw , 0xffff, 0xebf8, { 0, 0, 19}}, + {m68k_op_bfexts_32_al , 0xffff, 0xebf9, { 0, 0, 19}}, + {m68k_op_bfexts_32_pcdi , 0xffff, 0xebfa, { 0, 0, 20}}, + {m68k_op_bfexts_32_pcix , 0xffff, 0xebfb, { 0, 0, 22}}, + {m68k_op_bfclr_32_aw , 0xffff, 0xecf8, { 0, 0, 24}}, + {m68k_op_bfclr_32_al , 0xffff, 0xecf9, { 0, 0, 24}}, + {m68k_op_bfffo_32_aw , 0xffff, 0xedf8, { 0, 0, 32}}, + {m68k_op_bfffo_32_al , 0xffff, 0xedf9, { 0, 0, 32}}, + {m68k_op_bfffo_32_pcdi , 0xffff, 0xedfa, { 0, 0, 33}}, + {m68k_op_bfffo_32_pcix , 0xffff, 0xedfb, { 0, 0, 35}}, + {m68k_op_bfset_32_aw , 0xffff, 0xeef8, { 0, 0, 24}}, + {m68k_op_bfset_32_al , 0xffff, 0xeef9, { 0, 0, 24}}, + {m68k_op_bfins_32_aw , 0xffff, 0xeff8, { 0, 0, 21}}, + {m68k_op_bfins_32_al , 0xffff, 0xeff9, { 0, 0, 21}}, + {0, 0, 0, {0, 0, 0}} +}; + + +/* Build the opcode handler jump table */ +void m68ki_build_opcode_table(void) +{ + opcode_handler_struct *ostruct; + int instr; + int i; + int j; + int k; + + for(i = 0; i < 0x10000; i++) + { + /* default to illegal */ + m68ki_instruction_jump_table[i] = m68k_op_illegal; + for(k=0;k<NUM_CPU_TYPES;k++) + m68ki_cycles[k][i] = 0; + } + + ostruct = m68k_opcode_handler_table; + while(ostruct->mask != 0xff00) + { + for(i = 0;i < 0x10000;i++) + { + if((i & ostruct->mask) == ostruct->match) + { + m68ki_instruction_jump_table[i] = ostruct->opcode_handler; + for(k=0;k<NUM_CPU_TYPES;k++) + m68ki_cycles[k][i] = ostruct->cycles[k]; + } + } + ostruct++; + } + while(ostruct->mask == 0xff00) + { + for(i = 0;i <= 0xff;i++) + { + m68ki_instruction_jump_table[ostruct->match | i] = ostruct->opcode_handler; + for(k=0;k<NUM_CPU_TYPES;k++) + m68ki_cycles[k][ostruct->match | i] = ostruct->cycles[k]; + } + ostruct++; + } + while(ostruct->mask == 0xf1f8) + { + for(i = 0;i < 8;i++) + { + for(j = 0;j < 8;j++) + { + instr = ostruct->match | (i << 9) | j; + m68ki_instruction_jump_table[instr] = ostruct->opcode_handler; + for(k=0;k<NUM_CPU_TYPES;k++) + m68ki_cycles[k][instr] = ostruct->cycles[k]; + if((instr & 0xf000) == 0xe000 && (!(instr & 0x20))) + m68ki_cycles[0][instr] = m68ki_cycles[1][instr] = ostruct->cycles[k] + ((((j-1)&7)+1)<<1); + } + } + ostruct++; + } + while(ostruct->mask == 0xfff0) + { + for(i = 0;i <= 0x0f;i++) + { + m68ki_instruction_jump_table[ostruct->match | i] = ostruct->opcode_handler; + for(k=0;k<NUM_CPU_TYPES;k++) + m68ki_cycles[k][ostruct->match | i] = ostruct->cycles[k]; + } + ostruct++; + } + while(ostruct->mask == 0xf1ff) + { + for(i = 0;i <= 0x07;i++) + { + m68ki_instruction_jump_table[ostruct->match | (i << 9)] = ostruct->opcode_handler; + for(k=0;k<NUM_CPU_TYPES;k++) + m68ki_cycles[k][ostruct->match | (i << 9)] = ostruct->cycles[k]; + } + ostruct++; + } + while(ostruct->mask == 0xfff8) + { + for(i = 0;i <= 0x07;i++) + { + m68ki_instruction_jump_table[ostruct->match | i] = ostruct->opcode_handler; + for(k=0;k<NUM_CPU_TYPES;k++) + m68ki_cycles[k][ostruct->match | i] = ostruct->cycles[k]; + } + ostruct++; + } + while(ostruct->mask == 0xffff) + { + m68ki_instruction_jump_table[ostruct->match] = ostruct->opcode_handler; + for(k=0;k<NUM_CPU_TYPES;k++) + m68ki_cycles[k][ostruct->match] = ostruct->cycles[k]; + ostruct++; + } +} + + +/* ======================================================================== */ +/* ============================== END OF FILE ============================= */ +/* ======================================================================== */ + + diff --git a/plugins/ao/eng_ssf/m68kops.h b/plugins/ao/eng_ssf/m68kops.h new file mode 100644 index 00000000..94c966fd --- /dev/null +++ b/plugins/ao/eng_ssf/m68kops.h @@ -0,0 +1,1986 @@ +#ifndef M68KOPS__HEADER +#define M68KOPS__HEADER + +#include "m68kcpu.h" + +/* ======================================================================== */ +/* ============================ OPCODE HANDLERS =========================== */ +/* ======================================================================== */ + + +void m68k_op_1010(m68ki_cpu_core *cpu); +void m68k_op_1111(m68ki_cpu_core *cpu); +void m68k_op_abcd_8_rr(m68ki_cpu_core *cpu); +void m68k_op_abcd_8_mm_ax7(m68ki_cpu_core *cpu); +void m68k_op_abcd_8_mm_ay7(m68ki_cpu_core *cpu); +void m68k_op_abcd_8_mm_axy7(m68ki_cpu_core *cpu); +void m68k_op_abcd_8_mm(m68ki_cpu_core *cpu); +void m68k_op_add_8_er_d(m68ki_cpu_core *cpu); +void m68k_op_add_8_er_ai(m68ki_cpu_core *cpu); +void m68k_op_add_8_er_pi(m68ki_cpu_core *cpu); +void m68k_op_add_8_er_pi7(m68ki_cpu_core *cpu); +void m68k_op_add_8_er_pd(m68ki_cpu_core *cpu); +void m68k_op_add_8_er_pd7(m68ki_cpu_core *cpu); +void m68k_op_add_8_er_di(m68ki_cpu_core *cpu); +void m68k_op_add_8_er_ix(m68ki_cpu_core *cpu); +void m68k_op_add_8_er_aw(m68ki_cpu_core *cpu); +void m68k_op_add_8_er_al(m68ki_cpu_core *cpu); +void m68k_op_add_8_er_pcdi(m68ki_cpu_core *cpu); +void m68k_op_add_8_er_pcix(m68ki_cpu_core *cpu); +void m68k_op_add_8_er_i(m68ki_cpu_core *cpu); +void m68k_op_add_16_er_d(m68ki_cpu_core *cpu); +void m68k_op_add_16_er_a(m68ki_cpu_core *cpu); +void m68k_op_add_16_er_ai(m68ki_cpu_core *cpu); +void m68k_op_add_16_er_pi(m68ki_cpu_core *cpu); +void m68k_op_add_16_er_pd(m68ki_cpu_core *cpu); +void m68k_op_add_16_er_di(m68ki_cpu_core *cpu); +void m68k_op_add_16_er_ix(m68ki_cpu_core *cpu); +void m68k_op_add_16_er_aw(m68ki_cpu_core *cpu); +void m68k_op_add_16_er_al(m68ki_cpu_core *cpu); +void m68k_op_add_16_er_pcdi(m68ki_cpu_core *cpu); +void m68k_op_add_16_er_pcix(m68ki_cpu_core *cpu); +void m68k_op_add_16_er_i(m68ki_cpu_core *cpu); +void m68k_op_add_32_er_d(m68ki_cpu_core *cpu); +void m68k_op_add_32_er_a(m68ki_cpu_core *cpu); +void m68k_op_add_32_er_ai(m68ki_cpu_core *cpu); +void m68k_op_add_32_er_pi(m68ki_cpu_core *cpu); +void m68k_op_add_32_er_pd(m68ki_cpu_core *cpu); +void m68k_op_add_32_er_di(m68ki_cpu_core *cpu); +void m68k_op_add_32_er_ix(m68ki_cpu_core *cpu); +void m68k_op_add_32_er_aw(m68ki_cpu_core *cpu); +void m68k_op_add_32_er_al(m68ki_cpu_core *cpu); +void m68k_op_add_32_er_pcdi(m68ki_cpu_core *cpu); +void m68k_op_add_32_er_pcix(m68ki_cpu_core *cpu); +void m68k_op_add_32_er_i(m68ki_cpu_core *cpu); +void m68k_op_add_8_re_ai(m68ki_cpu_core *cpu); +void m68k_op_add_8_re_pi(m68ki_cpu_core *cpu); +void m68k_op_add_8_re_pi7(m68ki_cpu_core *cpu); +void m68k_op_add_8_re_pd(m68ki_cpu_core *cpu); +void m68k_op_add_8_re_pd7(m68ki_cpu_core *cpu); +void m68k_op_add_8_re_di(m68ki_cpu_core *cpu); +void m68k_op_add_8_re_ix(m68ki_cpu_core *cpu); +void m68k_op_add_8_re_aw(m68ki_cpu_core *cpu); +void m68k_op_add_8_re_al(m68ki_cpu_core *cpu); +void m68k_op_add_16_re_ai(m68ki_cpu_core *cpu); +void m68k_op_add_16_re_pi(m68ki_cpu_core *cpu); +void m68k_op_add_16_re_pd(m68ki_cpu_core *cpu); +void m68k_op_add_16_re_di(m68ki_cpu_core *cpu); +void m68k_op_add_16_re_ix(m68ki_cpu_core *cpu); +void m68k_op_add_16_re_aw(m68ki_cpu_core *cpu); +void m68k_op_add_16_re_al(m68ki_cpu_core *cpu); +void m68k_op_add_32_re_ai(m68ki_cpu_core *cpu); +void m68k_op_add_32_re_pi(m68ki_cpu_core *cpu); +void m68k_op_add_32_re_pd(m68ki_cpu_core *cpu); +void m68k_op_add_32_re_di(m68ki_cpu_core *cpu); +void m68k_op_add_32_re_ix(m68ki_cpu_core *cpu); +void m68k_op_add_32_re_aw(m68ki_cpu_core *cpu); +void m68k_op_add_32_re_al(m68ki_cpu_core *cpu); +void m68k_op_adda_16_d(m68ki_cpu_core *cpu); +void m68k_op_adda_16_a(m68ki_cpu_core *cpu); +void m68k_op_adda_16_ai(m68ki_cpu_core *cpu); +void m68k_op_adda_16_pi(m68ki_cpu_core *cpu); +void m68k_op_adda_16_pd(m68ki_cpu_core *cpu); +void m68k_op_adda_16_di(m68ki_cpu_core *cpu); +void m68k_op_adda_16_ix(m68ki_cpu_core *cpu); +void m68k_op_adda_16_aw(m68ki_cpu_core *cpu); +void m68k_op_adda_16_al(m68ki_cpu_core *cpu); +void m68k_op_adda_16_pcdi(m68ki_cpu_core *cpu); +void m68k_op_adda_16_pcix(m68ki_cpu_core *cpu); +void m68k_op_adda_16_i(m68ki_cpu_core *cpu); +void m68k_op_adda_32_d(m68ki_cpu_core *cpu); +void m68k_op_adda_32_a(m68ki_cpu_core *cpu); +void m68k_op_adda_32_ai(m68ki_cpu_core *cpu); +void m68k_op_adda_32_pi(m68ki_cpu_core *cpu); +void m68k_op_adda_32_pd(m68ki_cpu_core *cpu); +void m68k_op_adda_32_di(m68ki_cpu_core *cpu); +void m68k_op_adda_32_ix(m68ki_cpu_core *cpu); +void m68k_op_adda_32_aw(m68ki_cpu_core *cpu); +void m68k_op_adda_32_al(m68ki_cpu_core *cpu); +void m68k_op_adda_32_pcdi(m68ki_cpu_core *cpu); +void m68k_op_adda_32_pcix(m68ki_cpu_core *cpu); +void m68k_op_adda_32_i(m68ki_cpu_core *cpu); +void m68k_op_addi_8_d(m68ki_cpu_core *cpu); +void m68k_op_addi_8_ai(m68ki_cpu_core *cpu); +void m68k_op_addi_8_pi(m68ki_cpu_core *cpu); +void m68k_op_addi_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_addi_8_pd(m68ki_cpu_core *cpu); +void m68k_op_addi_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_addi_8_di(m68ki_cpu_core *cpu); +void m68k_op_addi_8_ix(m68ki_cpu_core *cpu); +void m68k_op_addi_8_aw(m68ki_cpu_core *cpu); +void m68k_op_addi_8_al(m68ki_cpu_core *cpu); +void m68k_op_addi_16_d(m68ki_cpu_core *cpu); +void m68k_op_addi_16_ai(m68ki_cpu_core *cpu); +void m68k_op_addi_16_pi(m68ki_cpu_core *cpu); +void m68k_op_addi_16_pd(m68ki_cpu_core *cpu); +void m68k_op_addi_16_di(m68ki_cpu_core *cpu); +void m68k_op_addi_16_ix(m68ki_cpu_core *cpu); +void m68k_op_addi_16_aw(m68ki_cpu_core *cpu); +void m68k_op_addi_16_al(m68ki_cpu_core *cpu); +void m68k_op_addi_32_d(m68ki_cpu_core *cpu); +void m68k_op_addi_32_ai(m68ki_cpu_core *cpu); +void m68k_op_addi_32_pi(m68ki_cpu_core *cpu); +void m68k_op_addi_32_pd(m68ki_cpu_core *cpu); +void m68k_op_addi_32_di(m68ki_cpu_core *cpu); +void m68k_op_addi_32_ix(m68ki_cpu_core *cpu); +void m68k_op_addi_32_aw(m68ki_cpu_core *cpu); +void m68k_op_addi_32_al(m68ki_cpu_core *cpu); +void m68k_op_addq_8_d(m68ki_cpu_core *cpu); +void m68k_op_addq_8_ai(m68ki_cpu_core *cpu); +void m68k_op_addq_8_pi(m68ki_cpu_core *cpu); +void m68k_op_addq_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_addq_8_pd(m68ki_cpu_core *cpu); +void m68k_op_addq_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_addq_8_di(m68ki_cpu_core *cpu); +void m68k_op_addq_8_ix(m68ki_cpu_core *cpu); +void m68k_op_addq_8_aw(m68ki_cpu_core *cpu); +void m68k_op_addq_8_al(m68ki_cpu_core *cpu); +void m68k_op_addq_16_d(m68ki_cpu_core *cpu); +void m68k_op_addq_16_a(m68ki_cpu_core *cpu); +void m68k_op_addq_16_ai(m68ki_cpu_core *cpu); +void m68k_op_addq_16_pi(m68ki_cpu_core *cpu); +void m68k_op_addq_16_pd(m68ki_cpu_core *cpu); +void m68k_op_addq_16_di(m68ki_cpu_core *cpu); +void m68k_op_addq_16_ix(m68ki_cpu_core *cpu); +void m68k_op_addq_16_aw(m68ki_cpu_core *cpu); +void m68k_op_addq_16_al(m68ki_cpu_core *cpu); +void m68k_op_addq_32_d(m68ki_cpu_core *cpu); +void m68k_op_addq_32_a(m68ki_cpu_core *cpu); +void m68k_op_addq_32_ai(m68ki_cpu_core *cpu); +void m68k_op_addq_32_pi(m68ki_cpu_core *cpu); +void m68k_op_addq_32_pd(m68ki_cpu_core *cpu); +void m68k_op_addq_32_di(m68ki_cpu_core *cpu); +void m68k_op_addq_32_ix(m68ki_cpu_core *cpu); +void m68k_op_addq_32_aw(m68ki_cpu_core *cpu); +void m68k_op_addq_32_al(m68ki_cpu_core *cpu); +void m68k_op_addx_8_rr(m68ki_cpu_core *cpu); +void m68k_op_addx_16_rr(m68ki_cpu_core *cpu); +void m68k_op_addx_32_rr(m68ki_cpu_core *cpu); +void m68k_op_addx_8_mm_ax7(m68ki_cpu_core *cpu); +void m68k_op_addx_8_mm_ay7(m68ki_cpu_core *cpu); +void m68k_op_addx_8_mm_axy7(m68ki_cpu_core *cpu); +void m68k_op_addx_8_mm(m68ki_cpu_core *cpu); +void m68k_op_addx_16_mm(m68ki_cpu_core *cpu); +void m68k_op_addx_32_mm(m68ki_cpu_core *cpu); +void m68k_op_and_8_er_d(m68ki_cpu_core *cpu); +void m68k_op_and_8_er_ai(m68ki_cpu_core *cpu); +void m68k_op_and_8_er_pi(m68ki_cpu_core *cpu); +void m68k_op_and_8_er_pi7(m68ki_cpu_core *cpu); +void m68k_op_and_8_er_pd(m68ki_cpu_core *cpu); +void m68k_op_and_8_er_pd7(m68ki_cpu_core *cpu); +void m68k_op_and_8_er_di(m68ki_cpu_core *cpu); +void m68k_op_and_8_er_ix(m68ki_cpu_core *cpu); +void m68k_op_and_8_er_aw(m68ki_cpu_core *cpu); +void m68k_op_and_8_er_al(m68ki_cpu_core *cpu); +void m68k_op_and_8_er_pcdi(m68ki_cpu_core *cpu); +void m68k_op_and_8_er_pcix(m68ki_cpu_core *cpu); +void m68k_op_and_8_er_i(m68ki_cpu_core *cpu); +void m68k_op_and_16_er_d(m68ki_cpu_core *cpu); +void m68k_op_and_16_er_ai(m68ki_cpu_core *cpu); +void m68k_op_and_16_er_pi(m68ki_cpu_core *cpu); +void m68k_op_and_16_er_pd(m68ki_cpu_core *cpu); +void m68k_op_and_16_er_di(m68ki_cpu_core *cpu); +void m68k_op_and_16_er_ix(m68ki_cpu_core *cpu); +void m68k_op_and_16_er_aw(m68ki_cpu_core *cpu); +void m68k_op_and_16_er_al(m68ki_cpu_core *cpu); +void m68k_op_and_16_er_pcdi(m68ki_cpu_core *cpu); +void m68k_op_and_16_er_pcix(m68ki_cpu_core *cpu); +void m68k_op_and_16_er_i(m68ki_cpu_core *cpu); +void m68k_op_and_32_er_d(m68ki_cpu_core *cpu); +void m68k_op_and_32_er_ai(m68ki_cpu_core *cpu); +void m68k_op_and_32_er_pi(m68ki_cpu_core *cpu); +void m68k_op_and_32_er_pd(m68ki_cpu_core *cpu); +void m68k_op_and_32_er_di(m68ki_cpu_core *cpu); +void m68k_op_and_32_er_ix(m68ki_cpu_core *cpu); +void m68k_op_and_32_er_aw(m68ki_cpu_core *cpu); +void m68k_op_and_32_er_al(m68ki_cpu_core *cpu); +void m68k_op_and_32_er_pcdi(m68ki_cpu_core *cpu); +void m68k_op_and_32_er_pcix(m68ki_cpu_core *cpu); +void m68k_op_and_32_er_i(m68ki_cpu_core *cpu); +void m68k_op_and_8_re_ai(m68ki_cpu_core *cpu); +void m68k_op_and_8_re_pi(m68ki_cpu_core *cpu); +void m68k_op_and_8_re_pi7(m68ki_cpu_core *cpu); +void m68k_op_and_8_re_pd(m68ki_cpu_core *cpu); +void m68k_op_and_8_re_pd7(m68ki_cpu_core *cpu); +void m68k_op_and_8_re_di(m68ki_cpu_core *cpu); +void m68k_op_and_8_re_ix(m68ki_cpu_core *cpu); +void m68k_op_and_8_re_aw(m68ki_cpu_core *cpu); +void m68k_op_and_8_re_al(m68ki_cpu_core *cpu); +void m68k_op_and_16_re_ai(m68ki_cpu_core *cpu); +void m68k_op_and_16_re_pi(m68ki_cpu_core *cpu); +void m68k_op_and_16_re_pd(m68ki_cpu_core *cpu); +void m68k_op_and_16_re_di(m68ki_cpu_core *cpu); +void m68k_op_and_16_re_ix(m68ki_cpu_core *cpu); +void m68k_op_and_16_re_aw(m68ki_cpu_core *cpu); +void m68k_op_and_16_re_al(m68ki_cpu_core *cpu); +void m68k_op_and_32_re_ai(m68ki_cpu_core *cpu); +void m68k_op_and_32_re_pi(m68ki_cpu_core *cpu); +void m68k_op_and_32_re_pd(m68ki_cpu_core *cpu); +void m68k_op_and_32_re_di(m68ki_cpu_core *cpu); +void m68k_op_and_32_re_ix(m68ki_cpu_core *cpu); +void m68k_op_and_32_re_aw(m68ki_cpu_core *cpu); +void m68k_op_and_32_re_al(m68ki_cpu_core *cpu); +void m68k_op_andi_8_d(m68ki_cpu_core *cpu); +void m68k_op_andi_8_ai(m68ki_cpu_core *cpu); +void m68k_op_andi_8_pi(m68ki_cpu_core *cpu); +void m68k_op_andi_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_andi_8_pd(m68ki_cpu_core *cpu); +void m68k_op_andi_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_andi_8_di(m68ki_cpu_core *cpu); +void m68k_op_andi_8_ix(m68ki_cpu_core *cpu); +void m68k_op_andi_8_aw(m68ki_cpu_core *cpu); +void m68k_op_andi_8_al(m68ki_cpu_core *cpu); +void m68k_op_andi_16_d(m68ki_cpu_core *cpu); +void m68k_op_andi_16_ai(m68ki_cpu_core *cpu); +void m68k_op_andi_16_pi(m68ki_cpu_core *cpu); +void m68k_op_andi_16_pd(m68ki_cpu_core *cpu); +void m68k_op_andi_16_di(m68ki_cpu_core *cpu); +void m68k_op_andi_16_ix(m68ki_cpu_core *cpu); +void m68k_op_andi_16_aw(m68ki_cpu_core *cpu); +void m68k_op_andi_16_al(m68ki_cpu_core *cpu); +void m68k_op_andi_32_d(m68ki_cpu_core *cpu); +void m68k_op_andi_32_ai(m68ki_cpu_core *cpu); +void m68k_op_andi_32_pi(m68ki_cpu_core *cpu); +void m68k_op_andi_32_pd(m68ki_cpu_core *cpu); +void m68k_op_andi_32_di(m68ki_cpu_core *cpu); +void m68k_op_andi_32_ix(m68ki_cpu_core *cpu); +void m68k_op_andi_32_aw(m68ki_cpu_core *cpu); +void m68k_op_andi_32_al(m68ki_cpu_core *cpu); +void m68k_op_andi_16_toc(m68ki_cpu_core *cpu); +void m68k_op_andi_16_tos(m68ki_cpu_core *cpu); +void m68k_op_asr_8_s(m68ki_cpu_core *cpu); +void m68k_op_asr_16_s(m68ki_cpu_core *cpu); +void m68k_op_asr_32_s(m68ki_cpu_core *cpu); +void m68k_op_asr_8_r(m68ki_cpu_core *cpu); +void m68k_op_asr_16_r(m68ki_cpu_core *cpu); +void m68k_op_asr_32_r(m68ki_cpu_core *cpu); +void m68k_op_asr_16_ai(m68ki_cpu_core *cpu); +void m68k_op_asr_16_pi(m68ki_cpu_core *cpu); +void m68k_op_asr_16_pd(m68ki_cpu_core *cpu); +void m68k_op_asr_16_di(m68ki_cpu_core *cpu); +void m68k_op_asr_16_ix(m68ki_cpu_core *cpu); +void m68k_op_asr_16_aw(m68ki_cpu_core *cpu); +void m68k_op_asr_16_al(m68ki_cpu_core *cpu); +void m68k_op_asl_8_s(m68ki_cpu_core *cpu); +void m68k_op_asl_16_s(m68ki_cpu_core *cpu); +void m68k_op_asl_32_s(m68ki_cpu_core *cpu); +void m68k_op_asl_8_r(m68ki_cpu_core *cpu); +void m68k_op_asl_16_r(m68ki_cpu_core *cpu); +void m68k_op_asl_32_r(m68ki_cpu_core *cpu); +void m68k_op_asl_16_ai(m68ki_cpu_core *cpu); +void m68k_op_asl_16_pi(m68ki_cpu_core *cpu); +void m68k_op_asl_16_pd(m68ki_cpu_core *cpu); +void m68k_op_asl_16_di(m68ki_cpu_core *cpu); +void m68k_op_asl_16_ix(m68ki_cpu_core *cpu); +void m68k_op_asl_16_aw(m68ki_cpu_core *cpu); +void m68k_op_asl_16_al(m68ki_cpu_core *cpu); +void m68k_op_bhi_8(m68ki_cpu_core *cpu); +void m68k_op_bls_8(m68ki_cpu_core *cpu); +void m68k_op_bcc_8(m68ki_cpu_core *cpu); +void m68k_op_bcs_8(m68ki_cpu_core *cpu); +void m68k_op_bne_8(m68ki_cpu_core *cpu); +void m68k_op_beq_8(m68ki_cpu_core *cpu); +void m68k_op_bvc_8(m68ki_cpu_core *cpu); +void m68k_op_bvs_8(m68ki_cpu_core *cpu); +void m68k_op_bpl_8(m68ki_cpu_core *cpu); +void m68k_op_bmi_8(m68ki_cpu_core *cpu); +void m68k_op_bge_8(m68ki_cpu_core *cpu); +void m68k_op_blt_8(m68ki_cpu_core *cpu); +void m68k_op_bgt_8(m68ki_cpu_core *cpu); +void m68k_op_ble_8(m68ki_cpu_core *cpu); +void m68k_op_bhi_16(m68ki_cpu_core *cpu); +void m68k_op_bls_16(m68ki_cpu_core *cpu); +void m68k_op_bcc_16(m68ki_cpu_core *cpu); +void m68k_op_bcs_16(m68ki_cpu_core *cpu); +void m68k_op_bne_16(m68ki_cpu_core *cpu); +void m68k_op_beq_16(m68ki_cpu_core *cpu); +void m68k_op_bvc_16(m68ki_cpu_core *cpu); +void m68k_op_bvs_16(m68ki_cpu_core *cpu); +void m68k_op_bpl_16(m68ki_cpu_core *cpu); +void m68k_op_bmi_16(m68ki_cpu_core *cpu); +void m68k_op_bge_16(m68ki_cpu_core *cpu); +void m68k_op_blt_16(m68ki_cpu_core *cpu); +void m68k_op_bgt_16(m68ki_cpu_core *cpu); +void m68k_op_ble_16(m68ki_cpu_core *cpu); +void m68k_op_bhi_32(m68ki_cpu_core *cpu); +void m68k_op_bls_32(m68ki_cpu_core *cpu); +void m68k_op_bcc_32(m68ki_cpu_core *cpu); +void m68k_op_bcs_32(m68ki_cpu_core *cpu); +void m68k_op_bne_32(m68ki_cpu_core *cpu); +void m68k_op_beq_32(m68ki_cpu_core *cpu); +void m68k_op_bvc_32(m68ki_cpu_core *cpu); +void m68k_op_bvs_32(m68ki_cpu_core *cpu); +void m68k_op_bpl_32(m68ki_cpu_core *cpu); +void m68k_op_bmi_32(m68ki_cpu_core *cpu); +void m68k_op_bge_32(m68ki_cpu_core *cpu); +void m68k_op_blt_32(m68ki_cpu_core *cpu); +void m68k_op_bgt_32(m68ki_cpu_core *cpu); +void m68k_op_ble_32(m68ki_cpu_core *cpu); +void m68k_op_bchg_32_r_d(m68ki_cpu_core *cpu); +void m68k_op_bchg_8_r_ai(m68ki_cpu_core *cpu); +void m68k_op_bchg_8_r_pi(m68ki_cpu_core *cpu); +void m68k_op_bchg_8_r_pi7(m68ki_cpu_core *cpu); +void m68k_op_bchg_8_r_pd(m68ki_cpu_core *cpu); +void m68k_op_bchg_8_r_pd7(m68ki_cpu_core *cpu); +void m68k_op_bchg_8_r_di(m68ki_cpu_core *cpu); +void m68k_op_bchg_8_r_ix(m68ki_cpu_core *cpu); +void m68k_op_bchg_8_r_aw(m68ki_cpu_core *cpu); +void m68k_op_bchg_8_r_al(m68ki_cpu_core *cpu); +void m68k_op_bchg_32_s_d(m68ki_cpu_core *cpu); +void m68k_op_bchg_8_s_ai(m68ki_cpu_core *cpu); +void m68k_op_bchg_8_s_pi(m68ki_cpu_core *cpu); +void m68k_op_bchg_8_s_pi7(m68ki_cpu_core *cpu); +void m68k_op_bchg_8_s_pd(m68ki_cpu_core *cpu); +void m68k_op_bchg_8_s_pd7(m68ki_cpu_core *cpu); +void m68k_op_bchg_8_s_di(m68ki_cpu_core *cpu); +void m68k_op_bchg_8_s_ix(m68ki_cpu_core *cpu); +void m68k_op_bchg_8_s_aw(m68ki_cpu_core *cpu); +void m68k_op_bchg_8_s_al(m68ki_cpu_core *cpu); +void m68k_op_bclr_32_r_d(m68ki_cpu_core *cpu); +void m68k_op_bclr_8_r_ai(m68ki_cpu_core *cpu); +void m68k_op_bclr_8_r_pi(m68ki_cpu_core *cpu); +void m68k_op_bclr_8_r_pi7(m68ki_cpu_core *cpu); +void m68k_op_bclr_8_r_pd(m68ki_cpu_core *cpu); +void m68k_op_bclr_8_r_pd7(m68ki_cpu_core *cpu); +void m68k_op_bclr_8_r_di(m68ki_cpu_core *cpu); +void m68k_op_bclr_8_r_ix(m68ki_cpu_core *cpu); +void m68k_op_bclr_8_r_aw(m68ki_cpu_core *cpu); +void m68k_op_bclr_8_r_al(m68ki_cpu_core *cpu); +void m68k_op_bclr_32_s_d(m68ki_cpu_core *cpu); +void m68k_op_bclr_8_s_ai(m68ki_cpu_core *cpu); +void m68k_op_bclr_8_s_pi(m68ki_cpu_core *cpu); +void m68k_op_bclr_8_s_pi7(m68ki_cpu_core *cpu); +void m68k_op_bclr_8_s_pd(m68ki_cpu_core *cpu); +void m68k_op_bclr_8_s_pd7(m68ki_cpu_core *cpu); +void m68k_op_bclr_8_s_di(m68ki_cpu_core *cpu); +void m68k_op_bclr_8_s_ix(m68ki_cpu_core *cpu); +void m68k_op_bclr_8_s_aw(m68ki_cpu_core *cpu); +void m68k_op_bclr_8_s_al(m68ki_cpu_core *cpu); +void m68k_op_bfchg_32_d(m68ki_cpu_core *cpu); +void m68k_op_bfchg_32_ai(m68ki_cpu_core *cpu); +void m68k_op_bfchg_32_di(m68ki_cpu_core *cpu); +void m68k_op_bfchg_32_ix(m68ki_cpu_core *cpu); +void m68k_op_bfchg_32_aw(m68ki_cpu_core *cpu); +void m68k_op_bfchg_32_al(m68ki_cpu_core *cpu); +void m68k_op_bfclr_32_d(m68ki_cpu_core *cpu); +void m68k_op_bfclr_32_ai(m68ki_cpu_core *cpu); +void m68k_op_bfclr_32_di(m68ki_cpu_core *cpu); +void m68k_op_bfclr_32_ix(m68ki_cpu_core *cpu); +void m68k_op_bfclr_32_aw(m68ki_cpu_core *cpu); +void m68k_op_bfclr_32_al(m68ki_cpu_core *cpu); +void m68k_op_bfexts_32_d(m68ki_cpu_core *cpu); +void m68k_op_bfexts_32_ai(m68ki_cpu_core *cpu); +void m68k_op_bfexts_32_di(m68ki_cpu_core *cpu); +void m68k_op_bfexts_32_ix(m68ki_cpu_core *cpu); +void m68k_op_bfexts_32_aw(m68ki_cpu_core *cpu); +void m68k_op_bfexts_32_al(m68ki_cpu_core *cpu); +void m68k_op_bfexts_32_pcdi(m68ki_cpu_core *cpu); +void m68k_op_bfexts_32_pcix(m68ki_cpu_core *cpu); +void m68k_op_bfextu_32_d(m68ki_cpu_core *cpu); +void m68k_op_bfextu_32_ai(m68ki_cpu_core *cpu); +void m68k_op_bfextu_32_di(m68ki_cpu_core *cpu); +void m68k_op_bfextu_32_ix(m68ki_cpu_core *cpu); +void m68k_op_bfextu_32_aw(m68ki_cpu_core *cpu); +void m68k_op_bfextu_32_al(m68ki_cpu_core *cpu); +void m68k_op_bfextu_32_pcdi(m68ki_cpu_core *cpu); +void m68k_op_bfextu_32_pcix(m68ki_cpu_core *cpu); +void m68k_op_bfffo_32_d(m68ki_cpu_core *cpu); +void m68k_op_bfffo_32_ai(m68ki_cpu_core *cpu); +void m68k_op_bfffo_32_di(m68ki_cpu_core *cpu); +void m68k_op_bfffo_32_ix(m68ki_cpu_core *cpu); +void m68k_op_bfffo_32_aw(m68ki_cpu_core *cpu); +void m68k_op_bfffo_32_al(m68ki_cpu_core *cpu); +void m68k_op_bfffo_32_pcdi(m68ki_cpu_core *cpu); +void m68k_op_bfffo_32_pcix(m68ki_cpu_core *cpu); +void m68k_op_bfins_32_d(m68ki_cpu_core *cpu); +void m68k_op_bfins_32_ai(m68ki_cpu_core *cpu); +void m68k_op_bfins_32_di(m68ki_cpu_core *cpu); +void m68k_op_bfins_32_ix(m68ki_cpu_core *cpu); +void m68k_op_bfins_32_aw(m68ki_cpu_core *cpu); +void m68k_op_bfins_32_al(m68ki_cpu_core *cpu); +void m68k_op_bfset_32_d(m68ki_cpu_core *cpu); +void m68k_op_bfset_32_ai(m68ki_cpu_core *cpu); +void m68k_op_bfset_32_di(m68ki_cpu_core *cpu); +void m68k_op_bfset_32_ix(m68ki_cpu_core *cpu); +void m68k_op_bfset_32_aw(m68ki_cpu_core *cpu); +void m68k_op_bfset_32_al(m68ki_cpu_core *cpu); +void m68k_op_bftst_32_d(m68ki_cpu_core *cpu); +void m68k_op_bftst_32_ai(m68ki_cpu_core *cpu); +void m68k_op_bftst_32_di(m68ki_cpu_core *cpu); +void m68k_op_bftst_32_ix(m68ki_cpu_core *cpu); +void m68k_op_bftst_32_aw(m68ki_cpu_core *cpu); +void m68k_op_bftst_32_al(m68ki_cpu_core *cpu); +void m68k_op_bftst_32_pcdi(m68ki_cpu_core *cpu); +void m68k_op_bftst_32_pcix(m68ki_cpu_core *cpu); +void m68k_op_bkpt(m68ki_cpu_core *cpu); +void m68k_op_bra_8(m68ki_cpu_core *cpu); +void m68k_op_bra_16(m68ki_cpu_core *cpu); +void m68k_op_bra_32(m68ki_cpu_core *cpu); +void m68k_op_bset_32_r_d(m68ki_cpu_core *cpu); +void m68k_op_bset_8_r_ai(m68ki_cpu_core *cpu); +void m68k_op_bset_8_r_pi(m68ki_cpu_core *cpu); +void m68k_op_bset_8_r_pi7(m68ki_cpu_core *cpu); +void m68k_op_bset_8_r_pd(m68ki_cpu_core *cpu); +void m68k_op_bset_8_r_pd7(m68ki_cpu_core *cpu); +void m68k_op_bset_8_r_di(m68ki_cpu_core *cpu); +void m68k_op_bset_8_r_ix(m68ki_cpu_core *cpu); +void m68k_op_bset_8_r_aw(m68ki_cpu_core *cpu); +void m68k_op_bset_8_r_al(m68ki_cpu_core *cpu); +void m68k_op_bset_32_s_d(m68ki_cpu_core *cpu); +void m68k_op_bset_8_s_ai(m68ki_cpu_core *cpu); +void m68k_op_bset_8_s_pi(m68ki_cpu_core *cpu); +void m68k_op_bset_8_s_pi7(m68ki_cpu_core *cpu); +void m68k_op_bset_8_s_pd(m68ki_cpu_core *cpu); +void m68k_op_bset_8_s_pd7(m68ki_cpu_core *cpu); +void m68k_op_bset_8_s_di(m68ki_cpu_core *cpu); +void m68k_op_bset_8_s_ix(m68ki_cpu_core *cpu); +void m68k_op_bset_8_s_aw(m68ki_cpu_core *cpu); +void m68k_op_bset_8_s_al(m68ki_cpu_core *cpu); +void m68k_op_bsr_8(m68ki_cpu_core *cpu); +void m68k_op_bsr_16(m68ki_cpu_core *cpu); +void m68k_op_bsr_32(m68ki_cpu_core *cpu); +void m68k_op_btst_32_r_d(m68ki_cpu_core *cpu); +void m68k_op_btst_8_r_ai(m68ki_cpu_core *cpu); +void m68k_op_btst_8_r_pi(m68ki_cpu_core *cpu); +void m68k_op_btst_8_r_pi7(m68ki_cpu_core *cpu); +void m68k_op_btst_8_r_pd(m68ki_cpu_core *cpu); +void m68k_op_btst_8_r_pd7(m68ki_cpu_core *cpu); +void m68k_op_btst_8_r_di(m68ki_cpu_core *cpu); +void m68k_op_btst_8_r_ix(m68ki_cpu_core *cpu); +void m68k_op_btst_8_r_aw(m68ki_cpu_core *cpu); +void m68k_op_btst_8_r_al(m68ki_cpu_core *cpu); +void m68k_op_btst_8_r_pcdi(m68ki_cpu_core *cpu); +void m68k_op_btst_8_r_pcix(m68ki_cpu_core *cpu); +void m68k_op_btst_8_r_i(m68ki_cpu_core *cpu); +void m68k_op_btst_32_s_d(m68ki_cpu_core *cpu); +void m68k_op_btst_8_s_ai(m68ki_cpu_core *cpu); +void m68k_op_btst_8_s_pi(m68ki_cpu_core *cpu); +void m68k_op_btst_8_s_pi7(m68ki_cpu_core *cpu); +void m68k_op_btst_8_s_pd(m68ki_cpu_core *cpu); +void m68k_op_btst_8_s_pd7(m68ki_cpu_core *cpu); +void m68k_op_btst_8_s_di(m68ki_cpu_core *cpu); +void m68k_op_btst_8_s_ix(m68ki_cpu_core *cpu); +void m68k_op_btst_8_s_aw(m68ki_cpu_core *cpu); +void m68k_op_btst_8_s_al(m68ki_cpu_core *cpu); +void m68k_op_btst_8_s_pcdi(m68ki_cpu_core *cpu); +void m68k_op_btst_8_s_pcix(m68ki_cpu_core *cpu); +void m68k_op_callm_32_ai(m68ki_cpu_core *cpu); +void m68k_op_callm_32_di(m68ki_cpu_core *cpu); +void m68k_op_callm_32_ix(m68ki_cpu_core *cpu); +void m68k_op_callm_32_aw(m68ki_cpu_core *cpu); +void m68k_op_callm_32_al(m68ki_cpu_core *cpu); +void m68k_op_callm_32_pcdi(m68ki_cpu_core *cpu); +void m68k_op_callm_32_pcix(m68ki_cpu_core *cpu); +void m68k_op_cas_8_ai(m68ki_cpu_core *cpu); +void m68k_op_cas_8_pi(m68ki_cpu_core *cpu); +void m68k_op_cas_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_cas_8_pd(m68ki_cpu_core *cpu); +void m68k_op_cas_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_cas_8_di(m68ki_cpu_core *cpu); +void m68k_op_cas_8_ix(m68ki_cpu_core *cpu); +void m68k_op_cas_8_aw(m68ki_cpu_core *cpu); +void m68k_op_cas_8_al(m68ki_cpu_core *cpu); +void m68k_op_cas_16_ai(m68ki_cpu_core *cpu); +void m68k_op_cas_16_pi(m68ki_cpu_core *cpu); +void m68k_op_cas_16_pd(m68ki_cpu_core *cpu); +void m68k_op_cas_16_di(m68ki_cpu_core *cpu); +void m68k_op_cas_16_ix(m68ki_cpu_core *cpu); +void m68k_op_cas_16_aw(m68ki_cpu_core *cpu); +void m68k_op_cas_16_al(m68ki_cpu_core *cpu); +void m68k_op_cas_32_ai(m68ki_cpu_core *cpu); +void m68k_op_cas_32_pi(m68ki_cpu_core *cpu); +void m68k_op_cas_32_pd(m68ki_cpu_core *cpu); +void m68k_op_cas_32_di(m68ki_cpu_core *cpu); +void m68k_op_cas_32_ix(m68ki_cpu_core *cpu); +void m68k_op_cas_32_aw(m68ki_cpu_core *cpu); +void m68k_op_cas_32_al(m68ki_cpu_core *cpu); +void m68k_op_cas2_16(m68ki_cpu_core *cpu); +void m68k_op_cas2_32(m68ki_cpu_core *cpu); +void m68k_op_chk_16_d(m68ki_cpu_core *cpu); +void m68k_op_chk_16_ai(m68ki_cpu_core *cpu); +void m68k_op_chk_16_pi(m68ki_cpu_core *cpu); +void m68k_op_chk_16_pd(m68ki_cpu_core *cpu); +void m68k_op_chk_16_di(m68ki_cpu_core *cpu); +void m68k_op_chk_16_ix(m68ki_cpu_core *cpu); +void m68k_op_chk_16_aw(m68ki_cpu_core *cpu); +void m68k_op_chk_16_al(m68ki_cpu_core *cpu); +void m68k_op_chk_16_pcdi(m68ki_cpu_core *cpu); +void m68k_op_chk_16_pcix(m68ki_cpu_core *cpu); +void m68k_op_chk_16_i(m68ki_cpu_core *cpu); +void m68k_op_chk_32_d(m68ki_cpu_core *cpu); +void m68k_op_chk_32_ai(m68ki_cpu_core *cpu); +void m68k_op_chk_32_pi(m68ki_cpu_core *cpu); +void m68k_op_chk_32_pd(m68ki_cpu_core *cpu); +void m68k_op_chk_32_di(m68ki_cpu_core *cpu); +void m68k_op_chk_32_ix(m68ki_cpu_core *cpu); +void m68k_op_chk_32_aw(m68ki_cpu_core *cpu); +void m68k_op_chk_32_al(m68ki_cpu_core *cpu); +void m68k_op_chk_32_pcdi(m68ki_cpu_core *cpu); +void m68k_op_chk_32_pcix(m68ki_cpu_core *cpu); +void m68k_op_chk_32_i(m68ki_cpu_core *cpu); +void m68k_op_chk2cmp2_8_pcdi(m68ki_cpu_core *cpu); +void m68k_op_chk2cmp2_8_pcix(m68ki_cpu_core *cpu); +void m68k_op_chk2cmp2_8_ai(m68ki_cpu_core *cpu); +void m68k_op_chk2cmp2_8_di(m68ki_cpu_core *cpu); +void m68k_op_chk2cmp2_8_ix(m68ki_cpu_core *cpu); +void m68k_op_chk2cmp2_8_aw(m68ki_cpu_core *cpu); +void m68k_op_chk2cmp2_8_al(m68ki_cpu_core *cpu); +void m68k_op_chk2cmp2_16_pcdi(m68ki_cpu_core *cpu); +void m68k_op_chk2cmp2_16_pcix(m68ki_cpu_core *cpu); +void m68k_op_chk2cmp2_16_ai(m68ki_cpu_core *cpu); +void m68k_op_chk2cmp2_16_di(m68ki_cpu_core *cpu); +void m68k_op_chk2cmp2_16_ix(m68ki_cpu_core *cpu); +void m68k_op_chk2cmp2_16_aw(m68ki_cpu_core *cpu); +void m68k_op_chk2cmp2_16_al(m68ki_cpu_core *cpu); +void m68k_op_chk2cmp2_32_pcdi(m68ki_cpu_core *cpu); +void m68k_op_chk2cmp2_32_pcix(m68ki_cpu_core *cpu); +void m68k_op_chk2cmp2_32_ai(m68ki_cpu_core *cpu); +void m68k_op_chk2cmp2_32_di(m68ki_cpu_core *cpu); +void m68k_op_chk2cmp2_32_ix(m68ki_cpu_core *cpu); +void m68k_op_chk2cmp2_32_aw(m68ki_cpu_core *cpu); +void m68k_op_chk2cmp2_32_al(m68ki_cpu_core *cpu); +void m68k_op_clr_8_d(m68ki_cpu_core *cpu); +void m68k_op_clr_8_ai(m68ki_cpu_core *cpu); +void m68k_op_clr_8_pi(m68ki_cpu_core *cpu); +void m68k_op_clr_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_clr_8_pd(m68ki_cpu_core *cpu); +void m68k_op_clr_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_clr_8_di(m68ki_cpu_core *cpu); +void m68k_op_clr_8_ix(m68ki_cpu_core *cpu); +void m68k_op_clr_8_aw(m68ki_cpu_core *cpu); +void m68k_op_clr_8_al(m68ki_cpu_core *cpu); +void m68k_op_clr_16_d(m68ki_cpu_core *cpu); +void m68k_op_clr_16_ai(m68ki_cpu_core *cpu); +void m68k_op_clr_16_pi(m68ki_cpu_core *cpu); +void m68k_op_clr_16_pd(m68ki_cpu_core *cpu); +void m68k_op_clr_16_di(m68ki_cpu_core *cpu); +void m68k_op_clr_16_ix(m68ki_cpu_core *cpu); +void m68k_op_clr_16_aw(m68ki_cpu_core *cpu); +void m68k_op_clr_16_al(m68ki_cpu_core *cpu); +void m68k_op_clr_32_d(m68ki_cpu_core *cpu); +void m68k_op_clr_32_ai(m68ki_cpu_core *cpu); +void m68k_op_clr_32_pi(m68ki_cpu_core *cpu); +void m68k_op_clr_32_pd(m68ki_cpu_core *cpu); +void m68k_op_clr_32_di(m68ki_cpu_core *cpu); +void m68k_op_clr_32_ix(m68ki_cpu_core *cpu); +void m68k_op_clr_32_aw(m68ki_cpu_core *cpu); +void m68k_op_clr_32_al(m68ki_cpu_core *cpu); +void m68k_op_cmp_8_d(m68ki_cpu_core *cpu); +void m68k_op_cmp_8_ai(m68ki_cpu_core *cpu); +void m68k_op_cmp_8_pi(m68ki_cpu_core *cpu); +void m68k_op_cmp_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_cmp_8_pd(m68ki_cpu_core *cpu); +void m68k_op_cmp_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_cmp_8_di(m68ki_cpu_core *cpu); +void m68k_op_cmp_8_ix(m68ki_cpu_core *cpu); +void m68k_op_cmp_8_aw(m68ki_cpu_core *cpu); +void m68k_op_cmp_8_al(m68ki_cpu_core *cpu); +void m68k_op_cmp_8_pcdi(m68ki_cpu_core *cpu); +void m68k_op_cmp_8_pcix(m68ki_cpu_core *cpu); +void m68k_op_cmp_8_i(m68ki_cpu_core *cpu); +void m68k_op_cmp_16_d(m68ki_cpu_core *cpu); +void m68k_op_cmp_16_a(m68ki_cpu_core *cpu); +void m68k_op_cmp_16_ai(m68ki_cpu_core *cpu); +void m68k_op_cmp_16_pi(m68ki_cpu_core *cpu); +void m68k_op_cmp_16_pd(m68ki_cpu_core *cpu); +void m68k_op_cmp_16_di(m68ki_cpu_core *cpu); +void m68k_op_cmp_16_ix(m68ki_cpu_core *cpu); +void m68k_op_cmp_16_aw(m68ki_cpu_core *cpu); +void m68k_op_cmp_16_al(m68ki_cpu_core *cpu); +void m68k_op_cmp_16_pcdi(m68ki_cpu_core *cpu); +void m68k_op_cmp_16_pcix(m68ki_cpu_core *cpu); +void m68k_op_cmp_16_i(m68ki_cpu_core *cpu); +void m68k_op_cmp_32_d(m68ki_cpu_core *cpu); +void m68k_op_cmp_32_a(m68ki_cpu_core *cpu); +void m68k_op_cmp_32_ai(m68ki_cpu_core *cpu); +void m68k_op_cmp_32_pi(m68ki_cpu_core *cpu); +void m68k_op_cmp_32_pd(m68ki_cpu_core *cpu); +void m68k_op_cmp_32_di(m68ki_cpu_core *cpu); +void m68k_op_cmp_32_ix(m68ki_cpu_core *cpu); +void m68k_op_cmp_32_aw(m68ki_cpu_core *cpu); +void m68k_op_cmp_32_al(m68ki_cpu_core *cpu); +void m68k_op_cmp_32_pcdi(m68ki_cpu_core *cpu); +void m68k_op_cmp_32_pcix(m68ki_cpu_core *cpu); +void m68k_op_cmp_32_i(m68ki_cpu_core *cpu); +void m68k_op_cmpa_16_d(m68ki_cpu_core *cpu); +void m68k_op_cmpa_16_a(m68ki_cpu_core *cpu); +void m68k_op_cmpa_16_ai(m68ki_cpu_core *cpu); +void m68k_op_cmpa_16_pi(m68ki_cpu_core *cpu); +void m68k_op_cmpa_16_pd(m68ki_cpu_core *cpu); +void m68k_op_cmpa_16_di(m68ki_cpu_core *cpu); +void m68k_op_cmpa_16_ix(m68ki_cpu_core *cpu); +void m68k_op_cmpa_16_aw(m68ki_cpu_core *cpu); +void m68k_op_cmpa_16_al(m68ki_cpu_core *cpu); +void m68k_op_cmpa_16_pcdi(m68ki_cpu_core *cpu); +void m68k_op_cmpa_16_pcix(m68ki_cpu_core *cpu); +void m68k_op_cmpa_16_i(m68ki_cpu_core *cpu); +void m68k_op_cmpa_32_d(m68ki_cpu_core *cpu); +void m68k_op_cmpa_32_a(m68ki_cpu_core *cpu); +void m68k_op_cmpa_32_ai(m68ki_cpu_core *cpu); +void m68k_op_cmpa_32_pi(m68ki_cpu_core *cpu); +void m68k_op_cmpa_32_pd(m68ki_cpu_core *cpu); +void m68k_op_cmpa_32_di(m68ki_cpu_core *cpu); +void m68k_op_cmpa_32_ix(m68ki_cpu_core *cpu); +void m68k_op_cmpa_32_aw(m68ki_cpu_core *cpu); +void m68k_op_cmpa_32_al(m68ki_cpu_core *cpu); +void m68k_op_cmpa_32_pcdi(m68ki_cpu_core *cpu); +void m68k_op_cmpa_32_pcix(m68ki_cpu_core *cpu); +void m68k_op_cmpa_32_i(m68ki_cpu_core *cpu); +void m68k_op_cmpi_8_d(m68ki_cpu_core *cpu); +void m68k_op_cmpi_8_ai(m68ki_cpu_core *cpu); +void m68k_op_cmpi_8_pi(m68ki_cpu_core *cpu); +void m68k_op_cmpi_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_cmpi_8_pd(m68ki_cpu_core *cpu); +void m68k_op_cmpi_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_cmpi_8_di(m68ki_cpu_core *cpu); +void m68k_op_cmpi_8_ix(m68ki_cpu_core *cpu); +void m68k_op_cmpi_8_aw(m68ki_cpu_core *cpu); +void m68k_op_cmpi_8_al(m68ki_cpu_core *cpu); +void m68k_op_cmpi_8_pcdi(m68ki_cpu_core *cpu); +void m68k_op_cmpi_8_pcix(m68ki_cpu_core *cpu); +void m68k_op_cmpi_16_d(m68ki_cpu_core *cpu); +void m68k_op_cmpi_16_ai(m68ki_cpu_core *cpu); +void m68k_op_cmpi_16_pi(m68ki_cpu_core *cpu); +void m68k_op_cmpi_16_pd(m68ki_cpu_core *cpu); +void m68k_op_cmpi_16_di(m68ki_cpu_core *cpu); +void m68k_op_cmpi_16_ix(m68ki_cpu_core *cpu); +void m68k_op_cmpi_16_aw(m68ki_cpu_core *cpu); +void m68k_op_cmpi_16_al(m68ki_cpu_core *cpu); +void m68k_op_cmpi_16_pcdi(m68ki_cpu_core *cpu); +void m68k_op_cmpi_16_pcix(m68ki_cpu_core *cpu); +void m68k_op_cmpi_32_d(m68ki_cpu_core *cpu); +void m68k_op_cmpi_32_ai(m68ki_cpu_core *cpu); +void m68k_op_cmpi_32_pi(m68ki_cpu_core *cpu); +void m68k_op_cmpi_32_pd(m68ki_cpu_core *cpu); +void m68k_op_cmpi_32_di(m68ki_cpu_core *cpu); +void m68k_op_cmpi_32_ix(m68ki_cpu_core *cpu); +void m68k_op_cmpi_32_aw(m68ki_cpu_core *cpu); +void m68k_op_cmpi_32_al(m68ki_cpu_core *cpu); +void m68k_op_cmpi_32_pcdi(m68ki_cpu_core *cpu); +void m68k_op_cmpi_32_pcix(m68ki_cpu_core *cpu); +void m68k_op_cmpm_8_ax7(m68ki_cpu_core *cpu); +void m68k_op_cmpm_8_ay7(m68ki_cpu_core *cpu); +void m68k_op_cmpm_8_axy7(m68ki_cpu_core *cpu); +void m68k_op_cmpm_8(m68ki_cpu_core *cpu); +void m68k_op_cmpm_16(m68ki_cpu_core *cpu); +void m68k_op_cmpm_32(m68ki_cpu_core *cpu); +void m68k_op_cpbcc_32(m68ki_cpu_core *cpu); +void m68k_op_cpdbcc_32(m68ki_cpu_core *cpu); +void m68k_op_cpgen_32(m68ki_cpu_core *cpu); +void m68k_op_cpscc_32(m68ki_cpu_core *cpu); +void m68k_op_cptrapcc_32(m68ki_cpu_core *cpu); +void m68k_op_dbt_16(m68ki_cpu_core *cpu); +void m68k_op_dbf_16(m68ki_cpu_core *cpu); +void m68k_op_dbhi_16(m68ki_cpu_core *cpu); +void m68k_op_dbls_16(m68ki_cpu_core *cpu); +void m68k_op_dbcc_16(m68ki_cpu_core *cpu); +void m68k_op_dbcs_16(m68ki_cpu_core *cpu); +void m68k_op_dbne_16(m68ki_cpu_core *cpu); +void m68k_op_dbeq_16(m68ki_cpu_core *cpu); +void m68k_op_dbvc_16(m68ki_cpu_core *cpu); +void m68k_op_dbvs_16(m68ki_cpu_core *cpu); +void m68k_op_dbpl_16(m68ki_cpu_core *cpu); +void m68k_op_dbmi_16(m68ki_cpu_core *cpu); +void m68k_op_dbge_16(m68ki_cpu_core *cpu); +void m68k_op_dblt_16(m68ki_cpu_core *cpu); +void m68k_op_dbgt_16(m68ki_cpu_core *cpu); +void m68k_op_dble_16(m68ki_cpu_core *cpu); +void m68k_op_divs_16_d(m68ki_cpu_core *cpu); +void m68k_op_divs_16_ai(m68ki_cpu_core *cpu); +void m68k_op_divs_16_pi(m68ki_cpu_core *cpu); +void m68k_op_divs_16_pd(m68ki_cpu_core *cpu); +void m68k_op_divs_16_di(m68ki_cpu_core *cpu); +void m68k_op_divs_16_ix(m68ki_cpu_core *cpu); +void m68k_op_divs_16_aw(m68ki_cpu_core *cpu); +void m68k_op_divs_16_al(m68ki_cpu_core *cpu); +void m68k_op_divs_16_pcdi(m68ki_cpu_core *cpu); +void m68k_op_divs_16_pcix(m68ki_cpu_core *cpu); +void m68k_op_divs_16_i(m68ki_cpu_core *cpu); +void m68k_op_divu_16_d(m68ki_cpu_core *cpu); +void m68k_op_divu_16_ai(m68ki_cpu_core *cpu); +void m68k_op_divu_16_pi(m68ki_cpu_core *cpu); +void m68k_op_divu_16_pd(m68ki_cpu_core *cpu); +void m68k_op_divu_16_di(m68ki_cpu_core *cpu); +void m68k_op_divu_16_ix(m68ki_cpu_core *cpu); +void m68k_op_divu_16_aw(m68ki_cpu_core *cpu); +void m68k_op_divu_16_al(m68ki_cpu_core *cpu); +void m68k_op_divu_16_pcdi(m68ki_cpu_core *cpu); +void m68k_op_divu_16_pcix(m68ki_cpu_core *cpu); +void m68k_op_divu_16_i(m68ki_cpu_core *cpu); +void m68k_op_divl_32_d(m68ki_cpu_core *cpu); +void m68k_op_divl_32_ai(m68ki_cpu_core *cpu); +void m68k_op_divl_32_pi(m68ki_cpu_core *cpu); +void m68k_op_divl_32_pd(m68ki_cpu_core *cpu); +void m68k_op_divl_32_di(m68ki_cpu_core *cpu); +void m68k_op_divl_32_ix(m68ki_cpu_core *cpu); +void m68k_op_divl_32_aw(m68ki_cpu_core *cpu); +void m68k_op_divl_32_al(m68ki_cpu_core *cpu); +void m68k_op_divl_32_pcdi(m68ki_cpu_core *cpu); +void m68k_op_divl_32_pcix(m68ki_cpu_core *cpu); +void m68k_op_divl_32_i(m68ki_cpu_core *cpu); +void m68k_op_eor_8_d(m68ki_cpu_core *cpu); +void m68k_op_eor_8_ai(m68ki_cpu_core *cpu); +void m68k_op_eor_8_pi(m68ki_cpu_core *cpu); +void m68k_op_eor_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_eor_8_pd(m68ki_cpu_core *cpu); +void m68k_op_eor_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_eor_8_di(m68ki_cpu_core *cpu); +void m68k_op_eor_8_ix(m68ki_cpu_core *cpu); +void m68k_op_eor_8_aw(m68ki_cpu_core *cpu); +void m68k_op_eor_8_al(m68ki_cpu_core *cpu); +void m68k_op_eor_16_d(m68ki_cpu_core *cpu); +void m68k_op_eor_16_ai(m68ki_cpu_core *cpu); +void m68k_op_eor_16_pi(m68ki_cpu_core *cpu); +void m68k_op_eor_16_pd(m68ki_cpu_core *cpu); +void m68k_op_eor_16_di(m68ki_cpu_core *cpu); +void m68k_op_eor_16_ix(m68ki_cpu_core *cpu); +void m68k_op_eor_16_aw(m68ki_cpu_core *cpu); +void m68k_op_eor_16_al(m68ki_cpu_core *cpu); +void m68k_op_eor_32_d(m68ki_cpu_core *cpu); +void m68k_op_eor_32_ai(m68ki_cpu_core *cpu); +void m68k_op_eor_32_pi(m68ki_cpu_core *cpu); +void m68k_op_eor_32_pd(m68ki_cpu_core *cpu); +void m68k_op_eor_32_di(m68ki_cpu_core *cpu); +void m68k_op_eor_32_ix(m68ki_cpu_core *cpu); +void m68k_op_eor_32_aw(m68ki_cpu_core *cpu); +void m68k_op_eor_32_al(m68ki_cpu_core *cpu); +void m68k_op_eori_8_d(m68ki_cpu_core *cpu); +void m68k_op_eori_8_ai(m68ki_cpu_core *cpu); +void m68k_op_eori_8_pi(m68ki_cpu_core *cpu); +void m68k_op_eori_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_eori_8_pd(m68ki_cpu_core *cpu); +void m68k_op_eori_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_eori_8_di(m68ki_cpu_core *cpu); +void m68k_op_eori_8_ix(m68ki_cpu_core *cpu); +void m68k_op_eori_8_aw(m68ki_cpu_core *cpu); +void m68k_op_eori_8_al(m68ki_cpu_core *cpu); +void m68k_op_eori_16_d(m68ki_cpu_core *cpu); +void m68k_op_eori_16_ai(m68ki_cpu_core *cpu); +void m68k_op_eori_16_pi(m68ki_cpu_core *cpu); +void m68k_op_eori_16_pd(m68ki_cpu_core *cpu); +void m68k_op_eori_16_di(m68ki_cpu_core *cpu); +void m68k_op_eori_16_ix(m68ki_cpu_core *cpu); +void m68k_op_eori_16_aw(m68ki_cpu_core *cpu); +void m68k_op_eori_16_al(m68ki_cpu_core *cpu); +void m68k_op_eori_32_d(m68ki_cpu_core *cpu); +void m68k_op_eori_32_ai(m68ki_cpu_core *cpu); +void m68k_op_eori_32_pi(m68ki_cpu_core *cpu); +void m68k_op_eori_32_pd(m68ki_cpu_core *cpu); +void m68k_op_eori_32_di(m68ki_cpu_core *cpu); +void m68k_op_eori_32_ix(m68ki_cpu_core *cpu); +void m68k_op_eori_32_aw(m68ki_cpu_core *cpu); +void m68k_op_eori_32_al(m68ki_cpu_core *cpu); +void m68k_op_eori_16_toc(m68ki_cpu_core *cpu); +void m68k_op_eori_16_tos(m68ki_cpu_core *cpu); +void m68k_op_exg_32_dd(m68ki_cpu_core *cpu); +void m68k_op_exg_32_aa(m68ki_cpu_core *cpu); +void m68k_op_exg_32_da(m68ki_cpu_core *cpu); +void m68k_op_ext_16(m68ki_cpu_core *cpu); +void m68k_op_ext_32(m68ki_cpu_core *cpu); +void m68k_op_extb_32(m68ki_cpu_core *cpu); +void m68k_op_illegal(m68ki_cpu_core *cpu); +void m68k_op_jmp_32_ai(m68ki_cpu_core *cpu); +void m68k_op_jmp_32_di(m68ki_cpu_core *cpu); +void m68k_op_jmp_32_ix(m68ki_cpu_core *cpu); +void m68k_op_jmp_32_aw(m68ki_cpu_core *cpu); +void m68k_op_jmp_32_al(m68ki_cpu_core *cpu); +void m68k_op_jmp_32_pcdi(m68ki_cpu_core *cpu); +void m68k_op_jmp_32_pcix(m68ki_cpu_core *cpu); +void m68k_op_jsr_32_ai(m68ki_cpu_core *cpu); +void m68k_op_jsr_32_di(m68ki_cpu_core *cpu); +void m68k_op_jsr_32_ix(m68ki_cpu_core *cpu); +void m68k_op_jsr_32_aw(m68ki_cpu_core *cpu); +void m68k_op_jsr_32_al(m68ki_cpu_core *cpu); +void m68k_op_jsr_32_pcdi(m68ki_cpu_core *cpu); +void m68k_op_jsr_32_pcix(m68ki_cpu_core *cpu); +void m68k_op_lea_32_ai(m68ki_cpu_core *cpu); +void m68k_op_lea_32_di(m68ki_cpu_core *cpu); +void m68k_op_lea_32_ix(m68ki_cpu_core *cpu); +void m68k_op_lea_32_aw(m68ki_cpu_core *cpu); +void m68k_op_lea_32_al(m68ki_cpu_core *cpu); +void m68k_op_lea_32_pcdi(m68ki_cpu_core *cpu); +void m68k_op_lea_32_pcix(m68ki_cpu_core *cpu); +void m68k_op_link_16_a7(m68ki_cpu_core *cpu); +void m68k_op_link_16(m68ki_cpu_core *cpu); +void m68k_op_link_32_a7(m68ki_cpu_core *cpu); +void m68k_op_link_32(m68ki_cpu_core *cpu); +void m68k_op_lsr_8_s(m68ki_cpu_core *cpu); +void m68k_op_lsr_16_s(m68ki_cpu_core *cpu); +void m68k_op_lsr_32_s(m68ki_cpu_core *cpu); +void m68k_op_lsr_8_r(m68ki_cpu_core *cpu); +void m68k_op_lsr_16_r(m68ki_cpu_core *cpu); +void m68k_op_lsr_32_r(m68ki_cpu_core *cpu); +void m68k_op_lsr_16_ai(m68ki_cpu_core *cpu); +void m68k_op_lsr_16_pi(m68ki_cpu_core *cpu); +void m68k_op_lsr_16_pd(m68ki_cpu_core *cpu); +void m68k_op_lsr_16_di(m68ki_cpu_core *cpu); +void m68k_op_lsr_16_ix(m68ki_cpu_core *cpu); +void m68k_op_lsr_16_aw(m68ki_cpu_core *cpu); +void m68k_op_lsr_16_al(m68ki_cpu_core *cpu); +void m68k_op_lsl_8_s(m68ki_cpu_core *cpu); +void m68k_op_lsl_16_s(m68ki_cpu_core *cpu); +void m68k_op_lsl_32_s(m68ki_cpu_core *cpu); +void m68k_op_lsl_8_r(m68ki_cpu_core *cpu); +void m68k_op_lsl_16_r(m68ki_cpu_core *cpu); +void m68k_op_lsl_32_r(m68ki_cpu_core *cpu); +void m68k_op_lsl_16_ai(m68ki_cpu_core *cpu); +void m68k_op_lsl_16_pi(m68ki_cpu_core *cpu); +void m68k_op_lsl_16_pd(m68ki_cpu_core *cpu); +void m68k_op_lsl_16_di(m68ki_cpu_core *cpu); +void m68k_op_lsl_16_ix(m68ki_cpu_core *cpu); +void m68k_op_lsl_16_aw(m68ki_cpu_core *cpu); +void m68k_op_lsl_16_al(m68ki_cpu_core *cpu); +void m68k_op_move_8_d_d(m68ki_cpu_core *cpu); +void m68k_op_move_8_d_ai(m68ki_cpu_core *cpu); +void m68k_op_move_8_d_pi(m68ki_cpu_core *cpu); +void m68k_op_move_8_d_pi7(m68ki_cpu_core *cpu); +void m68k_op_move_8_d_pd(m68ki_cpu_core *cpu); +void m68k_op_move_8_d_pd7(m68ki_cpu_core *cpu); +void m68k_op_move_8_d_di(m68ki_cpu_core *cpu); +void m68k_op_move_8_d_ix(m68ki_cpu_core *cpu); +void m68k_op_move_8_d_aw(m68ki_cpu_core *cpu); +void m68k_op_move_8_d_al(m68ki_cpu_core *cpu); +void m68k_op_move_8_d_pcdi(m68ki_cpu_core *cpu); +void m68k_op_move_8_d_pcix(m68ki_cpu_core *cpu); +void m68k_op_move_8_d_i(m68ki_cpu_core *cpu); +void m68k_op_move_8_ai_d(m68ki_cpu_core *cpu); +void m68k_op_move_8_ai_ai(m68ki_cpu_core *cpu); +void m68k_op_move_8_ai_pi(m68ki_cpu_core *cpu); +void m68k_op_move_8_ai_pi7(m68ki_cpu_core *cpu); +void m68k_op_move_8_ai_pd(m68ki_cpu_core *cpu); +void m68k_op_move_8_ai_pd7(m68ki_cpu_core *cpu); +void m68k_op_move_8_ai_di(m68ki_cpu_core *cpu); +void m68k_op_move_8_ai_ix(m68ki_cpu_core *cpu); +void m68k_op_move_8_ai_aw(m68ki_cpu_core *cpu); +void m68k_op_move_8_ai_al(m68ki_cpu_core *cpu); +void m68k_op_move_8_ai_pcdi(m68ki_cpu_core *cpu); +void m68k_op_move_8_ai_pcix(m68ki_cpu_core *cpu); +void m68k_op_move_8_ai_i(m68ki_cpu_core *cpu); +void m68k_op_move_8_pi7_d(m68ki_cpu_core *cpu); +void m68k_op_move_8_pi_d(m68ki_cpu_core *cpu); +void m68k_op_move_8_pi7_ai(m68ki_cpu_core *cpu); +void m68k_op_move_8_pi7_pi(m68ki_cpu_core *cpu); +void m68k_op_move_8_pi7_pi7(m68ki_cpu_core *cpu); +void m68k_op_move_8_pi7_pd(m68ki_cpu_core *cpu); +void m68k_op_move_8_pi7_pd7(m68ki_cpu_core *cpu); +void m68k_op_move_8_pi7_di(m68ki_cpu_core *cpu); +void m68k_op_move_8_pi7_ix(m68ki_cpu_core *cpu); +void m68k_op_move_8_pi7_aw(m68ki_cpu_core *cpu); +void m68k_op_move_8_pi7_al(m68ki_cpu_core *cpu); +void m68k_op_move_8_pi7_pcdi(m68ki_cpu_core *cpu); +void m68k_op_move_8_pi7_pcix(m68ki_cpu_core *cpu); +void m68k_op_move_8_pi7_i(m68ki_cpu_core *cpu); +void m68k_op_move_8_pi_ai(m68ki_cpu_core *cpu); +void m68k_op_move_8_pi_pi(m68ki_cpu_core *cpu); +void m68k_op_move_8_pi_pi7(m68ki_cpu_core *cpu); +void m68k_op_move_8_pi_pd(m68ki_cpu_core *cpu); +void m68k_op_move_8_pi_pd7(m68ki_cpu_core *cpu); +void m68k_op_move_8_pi_di(m68ki_cpu_core *cpu); +void m68k_op_move_8_pi_ix(m68ki_cpu_core *cpu); +void m68k_op_move_8_pi_aw(m68ki_cpu_core *cpu); +void m68k_op_move_8_pi_al(m68ki_cpu_core *cpu); +void m68k_op_move_8_pi_pcdi(m68ki_cpu_core *cpu); +void m68k_op_move_8_pi_pcix(m68ki_cpu_core *cpu); +void m68k_op_move_8_pi_i(m68ki_cpu_core *cpu); +void m68k_op_move_8_pd7_d(m68ki_cpu_core *cpu); +void m68k_op_move_8_pd_d(m68ki_cpu_core *cpu); +void m68k_op_move_8_pd7_ai(m68ki_cpu_core *cpu); +void m68k_op_move_8_pd7_pi(m68ki_cpu_core *cpu); +void m68k_op_move_8_pd7_pi7(m68ki_cpu_core *cpu); +void m68k_op_move_8_pd7_pd(m68ki_cpu_core *cpu); +void m68k_op_move_8_pd7_pd7(m68ki_cpu_core *cpu); +void m68k_op_move_8_pd7_di(m68ki_cpu_core *cpu); +void m68k_op_move_8_pd7_ix(m68ki_cpu_core *cpu); +void m68k_op_move_8_pd7_aw(m68ki_cpu_core *cpu); +void m68k_op_move_8_pd7_al(m68ki_cpu_core *cpu); +void m68k_op_move_8_pd7_pcdi(m68ki_cpu_core *cpu); +void m68k_op_move_8_pd7_pcix(m68ki_cpu_core *cpu); +void m68k_op_move_8_pd7_i(m68ki_cpu_core *cpu); +void m68k_op_move_8_pd_ai(m68ki_cpu_core *cpu); +void m68k_op_move_8_pd_pi(m68ki_cpu_core *cpu); +void m68k_op_move_8_pd_pi7(m68ki_cpu_core *cpu); +void m68k_op_move_8_pd_pd(m68ki_cpu_core *cpu); +void m68k_op_move_8_pd_pd7(m68ki_cpu_core *cpu); +void m68k_op_move_8_pd_di(m68ki_cpu_core *cpu); +void m68k_op_move_8_pd_ix(m68ki_cpu_core *cpu); +void m68k_op_move_8_pd_aw(m68ki_cpu_core *cpu); +void m68k_op_move_8_pd_al(m68ki_cpu_core *cpu); +void m68k_op_move_8_pd_pcdi(m68ki_cpu_core *cpu); +void m68k_op_move_8_pd_pcix(m68ki_cpu_core *cpu); +void m68k_op_move_8_pd_i(m68ki_cpu_core *cpu); +void m68k_op_move_8_di_d(m68ki_cpu_core *cpu); +void m68k_op_move_8_di_ai(m68ki_cpu_core *cpu); +void m68k_op_move_8_di_pi(m68ki_cpu_core *cpu); +void m68k_op_move_8_di_pi7(m68ki_cpu_core *cpu); +void m68k_op_move_8_di_pd(m68ki_cpu_core *cpu); +void m68k_op_move_8_di_pd7(m68ki_cpu_core *cpu); +void m68k_op_move_8_di_di(m68ki_cpu_core *cpu); +void m68k_op_move_8_di_ix(m68ki_cpu_core *cpu); +void m68k_op_move_8_di_aw(m68ki_cpu_core *cpu); +void m68k_op_move_8_di_al(m68ki_cpu_core *cpu); +void m68k_op_move_8_di_pcdi(m68ki_cpu_core *cpu); +void m68k_op_move_8_di_pcix(m68ki_cpu_core *cpu); +void m68k_op_move_8_di_i(m68ki_cpu_core *cpu); +void m68k_op_move_8_ix_d(m68ki_cpu_core *cpu); +void m68k_op_move_8_ix_ai(m68ki_cpu_core *cpu); +void m68k_op_move_8_ix_pi(m68ki_cpu_core *cpu); +void m68k_op_move_8_ix_pi7(m68ki_cpu_core *cpu); +void m68k_op_move_8_ix_pd(m68ki_cpu_core *cpu); +void m68k_op_move_8_ix_pd7(m68ki_cpu_core *cpu); +void m68k_op_move_8_ix_di(m68ki_cpu_core *cpu); +void m68k_op_move_8_ix_ix(m68ki_cpu_core *cpu); +void m68k_op_move_8_ix_aw(m68ki_cpu_core *cpu); +void m68k_op_move_8_ix_al(m68ki_cpu_core *cpu); +void m68k_op_move_8_ix_pcdi(m68ki_cpu_core *cpu); +void m68k_op_move_8_ix_pcix(m68ki_cpu_core *cpu); +void m68k_op_move_8_ix_i(m68ki_cpu_core *cpu); +void m68k_op_move_8_aw_d(m68ki_cpu_core *cpu); +void m68k_op_move_8_aw_ai(m68ki_cpu_core *cpu); +void m68k_op_move_8_aw_pi(m68ki_cpu_core *cpu); +void m68k_op_move_8_aw_pi7(m68ki_cpu_core *cpu); +void m68k_op_move_8_aw_pd(m68ki_cpu_core *cpu); +void m68k_op_move_8_aw_pd7(m68ki_cpu_core *cpu); +void m68k_op_move_8_aw_di(m68ki_cpu_core *cpu); +void m68k_op_move_8_aw_ix(m68ki_cpu_core *cpu); +void m68k_op_move_8_aw_aw(m68ki_cpu_core *cpu); +void m68k_op_move_8_aw_al(m68ki_cpu_core *cpu); +void m68k_op_move_8_aw_pcdi(m68ki_cpu_core *cpu); +void m68k_op_move_8_aw_pcix(m68ki_cpu_core *cpu); +void m68k_op_move_8_aw_i(m68ki_cpu_core *cpu); +void m68k_op_move_8_al_d(m68ki_cpu_core *cpu); +void m68k_op_move_8_al_ai(m68ki_cpu_core *cpu); +void m68k_op_move_8_al_pi(m68ki_cpu_core *cpu); +void m68k_op_move_8_al_pi7(m68ki_cpu_core *cpu); +void m68k_op_move_8_al_pd(m68ki_cpu_core *cpu); +void m68k_op_move_8_al_pd7(m68ki_cpu_core *cpu); +void m68k_op_move_8_al_di(m68ki_cpu_core *cpu); +void m68k_op_move_8_al_ix(m68ki_cpu_core *cpu); +void m68k_op_move_8_al_aw(m68ki_cpu_core *cpu); +void m68k_op_move_8_al_al(m68ki_cpu_core *cpu); +void m68k_op_move_8_al_pcdi(m68ki_cpu_core *cpu); +void m68k_op_move_8_al_pcix(m68ki_cpu_core *cpu); +void m68k_op_move_8_al_i(m68ki_cpu_core *cpu); +void m68k_op_move_16_d_d(m68ki_cpu_core *cpu); +void m68k_op_move_16_d_a(m68ki_cpu_core *cpu); +void m68k_op_move_16_d_ai(m68ki_cpu_core *cpu); +void m68k_op_move_16_d_pi(m68ki_cpu_core *cpu); +void m68k_op_move_16_d_pd(m68ki_cpu_core *cpu); +void m68k_op_move_16_d_di(m68ki_cpu_core *cpu); +void m68k_op_move_16_d_ix(m68ki_cpu_core *cpu); +void m68k_op_move_16_d_aw(m68ki_cpu_core *cpu); +void m68k_op_move_16_d_al(m68ki_cpu_core *cpu); +void m68k_op_move_16_d_pcdi(m68ki_cpu_core *cpu); +void m68k_op_move_16_d_pcix(m68ki_cpu_core *cpu); +void m68k_op_move_16_d_i(m68ki_cpu_core *cpu); +void m68k_op_move_16_ai_d(m68ki_cpu_core *cpu); +void m68k_op_move_16_ai_a(m68ki_cpu_core *cpu); +void m68k_op_move_16_ai_ai(m68ki_cpu_core *cpu); +void m68k_op_move_16_ai_pi(m68ki_cpu_core *cpu); +void m68k_op_move_16_ai_pd(m68ki_cpu_core *cpu); +void m68k_op_move_16_ai_di(m68ki_cpu_core *cpu); +void m68k_op_move_16_ai_ix(m68ki_cpu_core *cpu); +void m68k_op_move_16_ai_aw(m68ki_cpu_core *cpu); +void m68k_op_move_16_ai_al(m68ki_cpu_core *cpu); +void m68k_op_move_16_ai_pcdi(m68ki_cpu_core *cpu); +void m68k_op_move_16_ai_pcix(m68ki_cpu_core *cpu); +void m68k_op_move_16_ai_i(m68ki_cpu_core *cpu); +void m68k_op_move_16_pi_d(m68ki_cpu_core *cpu); +void m68k_op_move_16_pi_a(m68ki_cpu_core *cpu); +void m68k_op_move_16_pi_ai(m68ki_cpu_core *cpu); +void m68k_op_move_16_pi_pi(m68ki_cpu_core *cpu); +void m68k_op_move_16_pi_pd(m68ki_cpu_core *cpu); +void m68k_op_move_16_pi_di(m68ki_cpu_core *cpu); +void m68k_op_move_16_pi_ix(m68ki_cpu_core *cpu); +void m68k_op_move_16_pi_aw(m68ki_cpu_core *cpu); +void m68k_op_move_16_pi_al(m68ki_cpu_core *cpu); +void m68k_op_move_16_pi_pcdi(m68ki_cpu_core *cpu); +void m68k_op_move_16_pi_pcix(m68ki_cpu_core *cpu); +void m68k_op_move_16_pi_i(m68ki_cpu_core *cpu); +void m68k_op_move_16_pd_d(m68ki_cpu_core *cpu); +void m68k_op_move_16_pd_a(m68ki_cpu_core *cpu); +void m68k_op_move_16_pd_ai(m68ki_cpu_core *cpu); +void m68k_op_move_16_pd_pi(m68ki_cpu_core *cpu); +void m68k_op_move_16_pd_pd(m68ki_cpu_core *cpu); +void m68k_op_move_16_pd_di(m68ki_cpu_core *cpu); +void m68k_op_move_16_pd_ix(m68ki_cpu_core *cpu); +void m68k_op_move_16_pd_aw(m68ki_cpu_core *cpu); +void m68k_op_move_16_pd_al(m68ki_cpu_core *cpu); +void m68k_op_move_16_pd_pcdi(m68ki_cpu_core *cpu); +void m68k_op_move_16_pd_pcix(m68ki_cpu_core *cpu); +void m68k_op_move_16_pd_i(m68ki_cpu_core *cpu); +void m68k_op_move_16_di_d(m68ki_cpu_core *cpu); +void m68k_op_move_16_di_a(m68ki_cpu_core *cpu); +void m68k_op_move_16_di_ai(m68ki_cpu_core *cpu); +void m68k_op_move_16_di_pi(m68ki_cpu_core *cpu); +void m68k_op_move_16_di_pd(m68ki_cpu_core *cpu); +void m68k_op_move_16_di_di(m68ki_cpu_core *cpu); +void m68k_op_move_16_di_ix(m68ki_cpu_core *cpu); +void m68k_op_move_16_di_aw(m68ki_cpu_core *cpu); +void m68k_op_move_16_di_al(m68ki_cpu_core *cpu); +void m68k_op_move_16_di_pcdi(m68ki_cpu_core *cpu); +void m68k_op_move_16_di_pcix(m68ki_cpu_core *cpu); +void m68k_op_move_16_di_i(m68ki_cpu_core *cpu); +void m68k_op_move_16_ix_d(m68ki_cpu_core *cpu); +void m68k_op_move_16_ix_a(m68ki_cpu_core *cpu); +void m68k_op_move_16_ix_ai(m68ki_cpu_core *cpu); +void m68k_op_move_16_ix_pi(m68ki_cpu_core *cpu); +void m68k_op_move_16_ix_pd(m68ki_cpu_core *cpu); +void m68k_op_move_16_ix_di(m68ki_cpu_core *cpu); +void m68k_op_move_16_ix_ix(m68ki_cpu_core *cpu); +void m68k_op_move_16_ix_aw(m68ki_cpu_core *cpu); +void m68k_op_move_16_ix_al(m68ki_cpu_core *cpu); +void m68k_op_move_16_ix_pcdi(m68ki_cpu_core *cpu); +void m68k_op_move_16_ix_pcix(m68ki_cpu_core *cpu); +void m68k_op_move_16_ix_i(m68ki_cpu_core *cpu); +void m68k_op_move_16_aw_d(m68ki_cpu_core *cpu); +void m68k_op_move_16_aw_a(m68ki_cpu_core *cpu); +void m68k_op_move_16_aw_ai(m68ki_cpu_core *cpu); +void m68k_op_move_16_aw_pi(m68ki_cpu_core *cpu); +void m68k_op_move_16_aw_pd(m68ki_cpu_core *cpu); +void m68k_op_move_16_aw_di(m68ki_cpu_core *cpu); +void m68k_op_move_16_aw_ix(m68ki_cpu_core *cpu); +void m68k_op_move_16_aw_aw(m68ki_cpu_core *cpu); +void m68k_op_move_16_aw_al(m68ki_cpu_core *cpu); +void m68k_op_move_16_aw_pcdi(m68ki_cpu_core *cpu); +void m68k_op_move_16_aw_pcix(m68ki_cpu_core *cpu); +void m68k_op_move_16_aw_i(m68ki_cpu_core *cpu); +void m68k_op_move_16_al_d(m68ki_cpu_core *cpu); +void m68k_op_move_16_al_a(m68ki_cpu_core *cpu); +void m68k_op_move_16_al_ai(m68ki_cpu_core *cpu); +void m68k_op_move_16_al_pi(m68ki_cpu_core *cpu); +void m68k_op_move_16_al_pd(m68ki_cpu_core *cpu); +void m68k_op_move_16_al_di(m68ki_cpu_core *cpu); +void m68k_op_move_16_al_ix(m68ki_cpu_core *cpu); +void m68k_op_move_16_al_aw(m68ki_cpu_core *cpu); +void m68k_op_move_16_al_al(m68ki_cpu_core *cpu); +void m68k_op_move_16_al_pcdi(m68ki_cpu_core *cpu); +void m68k_op_move_16_al_pcix(m68ki_cpu_core *cpu); +void m68k_op_move_16_al_i(m68ki_cpu_core *cpu); +void m68k_op_move_32_d_d(m68ki_cpu_core *cpu); +void m68k_op_move_32_d_a(m68ki_cpu_core *cpu); +void m68k_op_move_32_d_ai(m68ki_cpu_core *cpu); +void m68k_op_move_32_d_pi(m68ki_cpu_core *cpu); +void m68k_op_move_32_d_pd(m68ki_cpu_core *cpu); +void m68k_op_move_32_d_di(m68ki_cpu_core *cpu); +void m68k_op_move_32_d_ix(m68ki_cpu_core *cpu); +void m68k_op_move_32_d_aw(m68ki_cpu_core *cpu); +void m68k_op_move_32_d_al(m68ki_cpu_core *cpu); +void m68k_op_move_32_d_pcdi(m68ki_cpu_core *cpu); +void m68k_op_move_32_d_pcix(m68ki_cpu_core *cpu); +void m68k_op_move_32_d_i(m68ki_cpu_core *cpu); +void m68k_op_move_32_ai_d(m68ki_cpu_core *cpu); +void m68k_op_move_32_ai_a(m68ki_cpu_core *cpu); +void m68k_op_move_32_ai_ai(m68ki_cpu_core *cpu); +void m68k_op_move_32_ai_pi(m68ki_cpu_core *cpu); +void m68k_op_move_32_ai_pd(m68ki_cpu_core *cpu); +void m68k_op_move_32_ai_di(m68ki_cpu_core *cpu); +void m68k_op_move_32_ai_ix(m68ki_cpu_core *cpu); +void m68k_op_move_32_ai_aw(m68ki_cpu_core *cpu); +void m68k_op_move_32_ai_al(m68ki_cpu_core *cpu); +void m68k_op_move_32_ai_pcdi(m68ki_cpu_core *cpu); +void m68k_op_move_32_ai_pcix(m68ki_cpu_core *cpu); +void m68k_op_move_32_ai_i(m68ki_cpu_core *cpu); +void m68k_op_move_32_pi_d(m68ki_cpu_core *cpu); +void m68k_op_move_32_pi_a(m68ki_cpu_core *cpu); +void m68k_op_move_32_pi_ai(m68ki_cpu_core *cpu); +void m68k_op_move_32_pi_pi(m68ki_cpu_core *cpu); +void m68k_op_move_32_pi_pd(m68ki_cpu_core *cpu); +void m68k_op_move_32_pi_di(m68ki_cpu_core *cpu); +void m68k_op_move_32_pi_ix(m68ki_cpu_core *cpu); +void m68k_op_move_32_pi_aw(m68ki_cpu_core *cpu); +void m68k_op_move_32_pi_al(m68ki_cpu_core *cpu); +void m68k_op_move_32_pi_pcdi(m68ki_cpu_core *cpu); +void m68k_op_move_32_pi_pcix(m68ki_cpu_core *cpu); +void m68k_op_move_32_pi_i(m68ki_cpu_core *cpu); +void m68k_op_move_32_pd_d(m68ki_cpu_core *cpu); +void m68k_op_move_32_pd_a(m68ki_cpu_core *cpu); +void m68k_op_move_32_pd_ai(m68ki_cpu_core *cpu); +void m68k_op_move_32_pd_pi(m68ki_cpu_core *cpu); +void m68k_op_move_32_pd_pd(m68ki_cpu_core *cpu); +void m68k_op_move_32_pd_di(m68ki_cpu_core *cpu); +void m68k_op_move_32_pd_ix(m68ki_cpu_core *cpu); +void m68k_op_move_32_pd_aw(m68ki_cpu_core *cpu); +void m68k_op_move_32_pd_al(m68ki_cpu_core *cpu); +void m68k_op_move_32_pd_pcdi(m68ki_cpu_core *cpu); +void m68k_op_move_32_pd_pcix(m68ki_cpu_core *cpu); +void m68k_op_move_32_pd_i(m68ki_cpu_core *cpu); +void m68k_op_move_32_di_d(m68ki_cpu_core *cpu); +void m68k_op_move_32_di_a(m68ki_cpu_core *cpu); +void m68k_op_move_32_di_ai(m68ki_cpu_core *cpu); +void m68k_op_move_32_di_pi(m68ki_cpu_core *cpu); +void m68k_op_move_32_di_pd(m68ki_cpu_core *cpu); +void m68k_op_move_32_di_di(m68ki_cpu_core *cpu); +void m68k_op_move_32_di_ix(m68ki_cpu_core *cpu); +void m68k_op_move_32_di_aw(m68ki_cpu_core *cpu); +void m68k_op_move_32_di_al(m68ki_cpu_core *cpu); +void m68k_op_move_32_di_pcdi(m68ki_cpu_core *cpu); +void m68k_op_move_32_di_pcix(m68ki_cpu_core *cpu); +void m68k_op_move_32_di_i(m68ki_cpu_core *cpu); +void m68k_op_move_32_ix_d(m68ki_cpu_core *cpu); +void m68k_op_move_32_ix_a(m68ki_cpu_core *cpu); +void m68k_op_move_32_ix_ai(m68ki_cpu_core *cpu); +void m68k_op_move_32_ix_pi(m68ki_cpu_core *cpu); +void m68k_op_move_32_ix_pd(m68ki_cpu_core *cpu); +void m68k_op_move_32_ix_di(m68ki_cpu_core *cpu); +void m68k_op_move_32_ix_ix(m68ki_cpu_core *cpu); +void m68k_op_move_32_ix_aw(m68ki_cpu_core *cpu); +void m68k_op_move_32_ix_al(m68ki_cpu_core *cpu); +void m68k_op_move_32_ix_pcdi(m68ki_cpu_core *cpu); +void m68k_op_move_32_ix_pcix(m68ki_cpu_core *cpu); +void m68k_op_move_32_ix_i(m68ki_cpu_core *cpu); +void m68k_op_move_32_aw_d(m68ki_cpu_core *cpu); +void m68k_op_move_32_aw_a(m68ki_cpu_core *cpu); +void m68k_op_move_32_aw_ai(m68ki_cpu_core *cpu); +void m68k_op_move_32_aw_pi(m68ki_cpu_core *cpu); +void m68k_op_move_32_aw_pd(m68ki_cpu_core *cpu); +void m68k_op_move_32_aw_di(m68ki_cpu_core *cpu); +void m68k_op_move_32_aw_ix(m68ki_cpu_core *cpu); +void m68k_op_move_32_aw_aw(m68ki_cpu_core *cpu); +void m68k_op_move_32_aw_al(m68ki_cpu_core *cpu); +void m68k_op_move_32_aw_pcdi(m68ki_cpu_core *cpu); +void m68k_op_move_32_aw_pcix(m68ki_cpu_core *cpu); +void m68k_op_move_32_aw_i(m68ki_cpu_core *cpu); +void m68k_op_move_32_al_d(m68ki_cpu_core *cpu); +void m68k_op_move_32_al_a(m68ki_cpu_core *cpu); +void m68k_op_move_32_al_ai(m68ki_cpu_core *cpu); +void m68k_op_move_32_al_pi(m68ki_cpu_core *cpu); +void m68k_op_move_32_al_pd(m68ki_cpu_core *cpu); +void m68k_op_move_32_al_di(m68ki_cpu_core *cpu); +void m68k_op_move_32_al_ix(m68ki_cpu_core *cpu); +void m68k_op_move_32_al_aw(m68ki_cpu_core *cpu); +void m68k_op_move_32_al_al(m68ki_cpu_core *cpu); +void m68k_op_move_32_al_pcdi(m68ki_cpu_core *cpu); +void m68k_op_move_32_al_pcix(m68ki_cpu_core *cpu); +void m68k_op_move_32_al_i(m68ki_cpu_core *cpu); +void m68k_op_movea_16_d(m68ki_cpu_core *cpu); +void m68k_op_movea_16_a(m68ki_cpu_core *cpu); +void m68k_op_movea_16_ai(m68ki_cpu_core *cpu); +void m68k_op_movea_16_pi(m68ki_cpu_core *cpu); +void m68k_op_movea_16_pd(m68ki_cpu_core *cpu); +void m68k_op_movea_16_di(m68ki_cpu_core *cpu); +void m68k_op_movea_16_ix(m68ki_cpu_core *cpu); +void m68k_op_movea_16_aw(m68ki_cpu_core *cpu); +void m68k_op_movea_16_al(m68ki_cpu_core *cpu); +void m68k_op_movea_16_pcdi(m68ki_cpu_core *cpu); +void m68k_op_movea_16_pcix(m68ki_cpu_core *cpu); +void m68k_op_movea_16_i(m68ki_cpu_core *cpu); +void m68k_op_movea_32_d(m68ki_cpu_core *cpu); +void m68k_op_movea_32_a(m68ki_cpu_core *cpu); +void m68k_op_movea_32_ai(m68ki_cpu_core *cpu); +void m68k_op_movea_32_pi(m68ki_cpu_core *cpu); +void m68k_op_movea_32_pd(m68ki_cpu_core *cpu); +void m68k_op_movea_32_di(m68ki_cpu_core *cpu); +void m68k_op_movea_32_ix(m68ki_cpu_core *cpu); +void m68k_op_movea_32_aw(m68ki_cpu_core *cpu); +void m68k_op_movea_32_al(m68ki_cpu_core *cpu); +void m68k_op_movea_32_pcdi(m68ki_cpu_core *cpu); +void m68k_op_movea_32_pcix(m68ki_cpu_core *cpu); +void m68k_op_movea_32_i(m68ki_cpu_core *cpu); +void m68k_op_move_16_frc_d(m68ki_cpu_core *cpu); +void m68k_op_move_16_frc_ai(m68ki_cpu_core *cpu); +void m68k_op_move_16_frc_pi(m68ki_cpu_core *cpu); +void m68k_op_move_16_frc_pd(m68ki_cpu_core *cpu); +void m68k_op_move_16_frc_di(m68ki_cpu_core *cpu); +void m68k_op_move_16_frc_ix(m68ki_cpu_core *cpu); +void m68k_op_move_16_frc_aw(m68ki_cpu_core *cpu); +void m68k_op_move_16_frc_al(m68ki_cpu_core *cpu); +void m68k_op_move_16_toc_d(m68ki_cpu_core *cpu); +void m68k_op_move_16_toc_ai(m68ki_cpu_core *cpu); +void m68k_op_move_16_toc_pi(m68ki_cpu_core *cpu); +void m68k_op_move_16_toc_pd(m68ki_cpu_core *cpu); +void m68k_op_move_16_toc_di(m68ki_cpu_core *cpu); +void m68k_op_move_16_toc_ix(m68ki_cpu_core *cpu); +void m68k_op_move_16_toc_aw(m68ki_cpu_core *cpu); +void m68k_op_move_16_toc_al(m68ki_cpu_core *cpu); +void m68k_op_move_16_toc_pcdi(m68ki_cpu_core *cpu); +void m68k_op_move_16_toc_pcix(m68ki_cpu_core *cpu); +void m68k_op_move_16_toc_i(m68ki_cpu_core *cpu); +void m68k_op_move_16_frs_d(m68ki_cpu_core *cpu); +void m68k_op_move_16_frs_ai(m68ki_cpu_core *cpu); +void m68k_op_move_16_frs_pi(m68ki_cpu_core *cpu); +void m68k_op_move_16_frs_pd(m68ki_cpu_core *cpu); +void m68k_op_move_16_frs_di(m68ki_cpu_core *cpu); +void m68k_op_move_16_frs_ix(m68ki_cpu_core *cpu); +void m68k_op_move_16_frs_aw(m68ki_cpu_core *cpu); +void m68k_op_move_16_frs_al(m68ki_cpu_core *cpu); +void m68k_op_move_16_tos_d(m68ki_cpu_core *cpu); +void m68k_op_move_16_tos_ai(m68ki_cpu_core *cpu); +void m68k_op_move_16_tos_pi(m68ki_cpu_core *cpu); +void m68k_op_move_16_tos_pd(m68ki_cpu_core *cpu); +void m68k_op_move_16_tos_di(m68ki_cpu_core *cpu); +void m68k_op_move_16_tos_ix(m68ki_cpu_core *cpu); +void m68k_op_move_16_tos_aw(m68ki_cpu_core *cpu); +void m68k_op_move_16_tos_al(m68ki_cpu_core *cpu); +void m68k_op_move_16_tos_pcdi(m68ki_cpu_core *cpu); +void m68k_op_move_16_tos_pcix(m68ki_cpu_core *cpu); +void m68k_op_move_16_tos_i(m68ki_cpu_core *cpu); +void m68k_op_move_32_fru(m68ki_cpu_core *cpu); +void m68k_op_move_32_tou(m68ki_cpu_core *cpu); +void m68k_op_movec_32_cr(m68ki_cpu_core *cpu); +void m68k_op_movec_32_rc(m68ki_cpu_core *cpu); +void m68k_op_movem_16_re_pd(m68ki_cpu_core *cpu); +void m68k_op_movem_16_re_ai(m68ki_cpu_core *cpu); +void m68k_op_movem_16_re_di(m68ki_cpu_core *cpu); +void m68k_op_movem_16_re_ix(m68ki_cpu_core *cpu); +void m68k_op_movem_16_re_aw(m68ki_cpu_core *cpu); +void m68k_op_movem_16_re_al(m68ki_cpu_core *cpu); +void m68k_op_movem_32_re_pd(m68ki_cpu_core *cpu); +void m68k_op_movem_32_re_ai(m68ki_cpu_core *cpu); +void m68k_op_movem_32_re_di(m68ki_cpu_core *cpu); +void m68k_op_movem_32_re_ix(m68ki_cpu_core *cpu); +void m68k_op_movem_32_re_aw(m68ki_cpu_core *cpu); +void m68k_op_movem_32_re_al(m68ki_cpu_core *cpu); +void m68k_op_movem_16_er_pi(m68ki_cpu_core *cpu); +void m68k_op_movem_16_er_pcdi(m68ki_cpu_core *cpu); +void m68k_op_movem_16_er_pcix(m68ki_cpu_core *cpu); +void m68k_op_movem_16_er_ai(m68ki_cpu_core *cpu); +void m68k_op_movem_16_er_di(m68ki_cpu_core *cpu); +void m68k_op_movem_16_er_ix(m68ki_cpu_core *cpu); +void m68k_op_movem_16_er_aw(m68ki_cpu_core *cpu); +void m68k_op_movem_16_er_al(m68ki_cpu_core *cpu); +void m68k_op_movem_32_er_pi(m68ki_cpu_core *cpu); +void m68k_op_movem_32_er_pcdi(m68ki_cpu_core *cpu); +void m68k_op_movem_32_er_pcix(m68ki_cpu_core *cpu); +void m68k_op_movem_32_er_ai(m68ki_cpu_core *cpu); +void m68k_op_movem_32_er_di(m68ki_cpu_core *cpu); +void m68k_op_movem_32_er_ix(m68ki_cpu_core *cpu); +void m68k_op_movem_32_er_aw(m68ki_cpu_core *cpu); +void m68k_op_movem_32_er_al(m68ki_cpu_core *cpu); +void m68k_op_movep_16_re(m68ki_cpu_core *cpu); +void m68k_op_movep_32_re(m68ki_cpu_core *cpu); +void m68k_op_movep_16_er(m68ki_cpu_core *cpu); +void m68k_op_movep_32_er(m68ki_cpu_core *cpu); +void m68k_op_moves_8_ai(m68ki_cpu_core *cpu); +void m68k_op_moves_8_pi(m68ki_cpu_core *cpu); +void m68k_op_moves_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_moves_8_pd(m68ki_cpu_core *cpu); +void m68k_op_moves_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_moves_8_di(m68ki_cpu_core *cpu); +void m68k_op_moves_8_ix(m68ki_cpu_core *cpu); +void m68k_op_moves_8_aw(m68ki_cpu_core *cpu); +void m68k_op_moves_8_al(m68ki_cpu_core *cpu); +void m68k_op_moves_16_ai(m68ki_cpu_core *cpu); +void m68k_op_moves_16_pi(m68ki_cpu_core *cpu); +void m68k_op_moves_16_pd(m68ki_cpu_core *cpu); +void m68k_op_moves_16_di(m68ki_cpu_core *cpu); +void m68k_op_moves_16_ix(m68ki_cpu_core *cpu); +void m68k_op_moves_16_aw(m68ki_cpu_core *cpu); +void m68k_op_moves_16_al(m68ki_cpu_core *cpu); +void m68k_op_moves_32_ai(m68ki_cpu_core *cpu); +void m68k_op_moves_32_pi(m68ki_cpu_core *cpu); +void m68k_op_moves_32_pd(m68ki_cpu_core *cpu); +void m68k_op_moves_32_di(m68ki_cpu_core *cpu); +void m68k_op_moves_32_ix(m68ki_cpu_core *cpu); +void m68k_op_moves_32_aw(m68ki_cpu_core *cpu); +void m68k_op_moves_32_al(m68ki_cpu_core *cpu); +void m68k_op_moveq_32(m68ki_cpu_core *cpu); +void m68k_op_muls_16_d(m68ki_cpu_core *cpu); +void m68k_op_muls_16_ai(m68ki_cpu_core *cpu); +void m68k_op_muls_16_pi(m68ki_cpu_core *cpu); +void m68k_op_muls_16_pd(m68ki_cpu_core *cpu); +void m68k_op_muls_16_di(m68ki_cpu_core *cpu); +void m68k_op_muls_16_ix(m68ki_cpu_core *cpu); +void m68k_op_muls_16_aw(m68ki_cpu_core *cpu); +void m68k_op_muls_16_al(m68ki_cpu_core *cpu); +void m68k_op_muls_16_pcdi(m68ki_cpu_core *cpu); +void m68k_op_muls_16_pcix(m68ki_cpu_core *cpu); +void m68k_op_muls_16_i(m68ki_cpu_core *cpu); +void m68k_op_mulu_16_d(m68ki_cpu_core *cpu); +void m68k_op_mulu_16_ai(m68ki_cpu_core *cpu); +void m68k_op_mulu_16_pi(m68ki_cpu_core *cpu); +void m68k_op_mulu_16_pd(m68ki_cpu_core *cpu); +void m68k_op_mulu_16_di(m68ki_cpu_core *cpu); +void m68k_op_mulu_16_ix(m68ki_cpu_core *cpu); +void m68k_op_mulu_16_aw(m68ki_cpu_core *cpu); +void m68k_op_mulu_16_al(m68ki_cpu_core *cpu); +void m68k_op_mulu_16_pcdi(m68ki_cpu_core *cpu); +void m68k_op_mulu_16_pcix(m68ki_cpu_core *cpu); +void m68k_op_mulu_16_i(m68ki_cpu_core *cpu); +void m68k_op_mull_32_d(m68ki_cpu_core *cpu); +void m68k_op_mull_32_ai(m68ki_cpu_core *cpu); +void m68k_op_mull_32_pi(m68ki_cpu_core *cpu); +void m68k_op_mull_32_pd(m68ki_cpu_core *cpu); +void m68k_op_mull_32_di(m68ki_cpu_core *cpu); +void m68k_op_mull_32_ix(m68ki_cpu_core *cpu); +void m68k_op_mull_32_aw(m68ki_cpu_core *cpu); +void m68k_op_mull_32_al(m68ki_cpu_core *cpu); +void m68k_op_mull_32_pcdi(m68ki_cpu_core *cpu); +void m68k_op_mull_32_pcix(m68ki_cpu_core *cpu); +void m68k_op_mull_32_i(m68ki_cpu_core *cpu); +void m68k_op_nbcd_8_d(m68ki_cpu_core *cpu); +void m68k_op_nbcd_8_ai(m68ki_cpu_core *cpu); +void m68k_op_nbcd_8_pi(m68ki_cpu_core *cpu); +void m68k_op_nbcd_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_nbcd_8_pd(m68ki_cpu_core *cpu); +void m68k_op_nbcd_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_nbcd_8_di(m68ki_cpu_core *cpu); +void m68k_op_nbcd_8_ix(m68ki_cpu_core *cpu); +void m68k_op_nbcd_8_aw(m68ki_cpu_core *cpu); +void m68k_op_nbcd_8_al(m68ki_cpu_core *cpu); +void m68k_op_neg_8_d(m68ki_cpu_core *cpu); +void m68k_op_neg_8_ai(m68ki_cpu_core *cpu); +void m68k_op_neg_8_pi(m68ki_cpu_core *cpu); +void m68k_op_neg_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_neg_8_pd(m68ki_cpu_core *cpu); +void m68k_op_neg_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_neg_8_di(m68ki_cpu_core *cpu); +void m68k_op_neg_8_ix(m68ki_cpu_core *cpu); +void m68k_op_neg_8_aw(m68ki_cpu_core *cpu); +void m68k_op_neg_8_al(m68ki_cpu_core *cpu); +void m68k_op_neg_16_d(m68ki_cpu_core *cpu); +void m68k_op_neg_16_ai(m68ki_cpu_core *cpu); +void m68k_op_neg_16_pi(m68ki_cpu_core *cpu); +void m68k_op_neg_16_pd(m68ki_cpu_core *cpu); +void m68k_op_neg_16_di(m68ki_cpu_core *cpu); +void m68k_op_neg_16_ix(m68ki_cpu_core *cpu); +void m68k_op_neg_16_aw(m68ki_cpu_core *cpu); +void m68k_op_neg_16_al(m68ki_cpu_core *cpu); +void m68k_op_neg_32_d(m68ki_cpu_core *cpu); +void m68k_op_neg_32_ai(m68ki_cpu_core *cpu); +void m68k_op_neg_32_pi(m68ki_cpu_core *cpu); +void m68k_op_neg_32_pd(m68ki_cpu_core *cpu); +void m68k_op_neg_32_di(m68ki_cpu_core *cpu); +void m68k_op_neg_32_ix(m68ki_cpu_core *cpu); +void m68k_op_neg_32_aw(m68ki_cpu_core *cpu); +void m68k_op_neg_32_al(m68ki_cpu_core *cpu); +void m68k_op_negx_8_d(m68ki_cpu_core *cpu); +void m68k_op_negx_8_ai(m68ki_cpu_core *cpu); +void m68k_op_negx_8_pi(m68ki_cpu_core *cpu); +void m68k_op_negx_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_negx_8_pd(m68ki_cpu_core *cpu); +void m68k_op_negx_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_negx_8_di(m68ki_cpu_core *cpu); +void m68k_op_negx_8_ix(m68ki_cpu_core *cpu); +void m68k_op_negx_8_aw(m68ki_cpu_core *cpu); +void m68k_op_negx_8_al(m68ki_cpu_core *cpu); +void m68k_op_negx_16_d(m68ki_cpu_core *cpu); +void m68k_op_negx_16_ai(m68ki_cpu_core *cpu); +void m68k_op_negx_16_pi(m68ki_cpu_core *cpu); +void m68k_op_negx_16_pd(m68ki_cpu_core *cpu); +void m68k_op_negx_16_di(m68ki_cpu_core *cpu); +void m68k_op_negx_16_ix(m68ki_cpu_core *cpu); +void m68k_op_negx_16_aw(m68ki_cpu_core *cpu); +void m68k_op_negx_16_al(m68ki_cpu_core *cpu); +void m68k_op_negx_32_d(m68ki_cpu_core *cpu); +void m68k_op_negx_32_ai(m68ki_cpu_core *cpu); +void m68k_op_negx_32_pi(m68ki_cpu_core *cpu); +void m68k_op_negx_32_pd(m68ki_cpu_core *cpu); +void m68k_op_negx_32_di(m68ki_cpu_core *cpu); +void m68k_op_negx_32_ix(m68ki_cpu_core *cpu); +void m68k_op_negx_32_aw(m68ki_cpu_core *cpu); +void m68k_op_negx_32_al(m68ki_cpu_core *cpu); +void m68k_op_nop(m68ki_cpu_core *cpu); +void m68k_op_not_8_d(m68ki_cpu_core *cpu); +void m68k_op_not_8_ai(m68ki_cpu_core *cpu); +void m68k_op_not_8_pi(m68ki_cpu_core *cpu); +void m68k_op_not_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_not_8_pd(m68ki_cpu_core *cpu); +void m68k_op_not_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_not_8_di(m68ki_cpu_core *cpu); +void m68k_op_not_8_ix(m68ki_cpu_core *cpu); +void m68k_op_not_8_aw(m68ki_cpu_core *cpu); +void m68k_op_not_8_al(m68ki_cpu_core *cpu); +void m68k_op_not_16_d(m68ki_cpu_core *cpu); +void m68k_op_not_16_ai(m68ki_cpu_core *cpu); +void m68k_op_not_16_pi(m68ki_cpu_core *cpu); +void m68k_op_not_16_pd(m68ki_cpu_core *cpu); +void m68k_op_not_16_di(m68ki_cpu_core *cpu); +void m68k_op_not_16_ix(m68ki_cpu_core *cpu); +void m68k_op_not_16_aw(m68ki_cpu_core *cpu); +void m68k_op_not_16_al(m68ki_cpu_core *cpu); +void m68k_op_not_32_d(m68ki_cpu_core *cpu); +void m68k_op_not_32_ai(m68ki_cpu_core *cpu); +void m68k_op_not_32_pi(m68ki_cpu_core *cpu); +void m68k_op_not_32_pd(m68ki_cpu_core *cpu); +void m68k_op_not_32_di(m68ki_cpu_core *cpu); +void m68k_op_not_32_ix(m68ki_cpu_core *cpu); +void m68k_op_not_32_aw(m68ki_cpu_core *cpu); +void m68k_op_not_32_al(m68ki_cpu_core *cpu); +void m68k_op_or_8_er_d(m68ki_cpu_core *cpu); +void m68k_op_or_8_er_ai(m68ki_cpu_core *cpu); +void m68k_op_or_8_er_pi(m68ki_cpu_core *cpu); +void m68k_op_or_8_er_pi7(m68ki_cpu_core *cpu); +void m68k_op_or_8_er_pd(m68ki_cpu_core *cpu); +void m68k_op_or_8_er_pd7(m68ki_cpu_core *cpu); +void m68k_op_or_8_er_di(m68ki_cpu_core *cpu); +void m68k_op_or_8_er_ix(m68ki_cpu_core *cpu); +void m68k_op_or_8_er_aw(m68ki_cpu_core *cpu); +void m68k_op_or_8_er_al(m68ki_cpu_core *cpu); +void m68k_op_or_8_er_pcdi(m68ki_cpu_core *cpu); +void m68k_op_or_8_er_pcix(m68ki_cpu_core *cpu); +void m68k_op_or_8_er_i(m68ki_cpu_core *cpu); +void m68k_op_or_16_er_d(m68ki_cpu_core *cpu); +void m68k_op_or_16_er_ai(m68ki_cpu_core *cpu); +void m68k_op_or_16_er_pi(m68ki_cpu_core *cpu); +void m68k_op_or_16_er_pd(m68ki_cpu_core *cpu); +void m68k_op_or_16_er_di(m68ki_cpu_core *cpu); +void m68k_op_or_16_er_ix(m68ki_cpu_core *cpu); +void m68k_op_or_16_er_aw(m68ki_cpu_core *cpu); +void m68k_op_or_16_er_al(m68ki_cpu_core *cpu); +void m68k_op_or_16_er_pcdi(m68ki_cpu_core *cpu); +void m68k_op_or_16_er_pcix(m68ki_cpu_core *cpu); +void m68k_op_or_16_er_i(m68ki_cpu_core *cpu); +void m68k_op_or_32_er_d(m68ki_cpu_core *cpu); +void m68k_op_or_32_er_ai(m68ki_cpu_core *cpu); +void m68k_op_or_32_er_pi(m68ki_cpu_core *cpu); +void m68k_op_or_32_er_pd(m68ki_cpu_core *cpu); +void m68k_op_or_32_er_di(m68ki_cpu_core *cpu); +void m68k_op_or_32_er_ix(m68ki_cpu_core *cpu); +void m68k_op_or_32_er_aw(m68ki_cpu_core *cpu); +void m68k_op_or_32_er_al(m68ki_cpu_core *cpu); +void m68k_op_or_32_er_pcdi(m68ki_cpu_core *cpu); +void m68k_op_or_32_er_pcix(m68ki_cpu_core *cpu); +void m68k_op_or_32_er_i(m68ki_cpu_core *cpu); +void m68k_op_or_8_re_ai(m68ki_cpu_core *cpu); +void m68k_op_or_8_re_pi(m68ki_cpu_core *cpu); +void m68k_op_or_8_re_pi7(m68ki_cpu_core *cpu); +void m68k_op_or_8_re_pd(m68ki_cpu_core *cpu); +void m68k_op_or_8_re_pd7(m68ki_cpu_core *cpu); +void m68k_op_or_8_re_di(m68ki_cpu_core *cpu); +void m68k_op_or_8_re_ix(m68ki_cpu_core *cpu); +void m68k_op_or_8_re_aw(m68ki_cpu_core *cpu); +void m68k_op_or_8_re_al(m68ki_cpu_core *cpu); +void m68k_op_or_16_re_ai(m68ki_cpu_core *cpu); +void m68k_op_or_16_re_pi(m68ki_cpu_core *cpu); +void m68k_op_or_16_re_pd(m68ki_cpu_core *cpu); +void m68k_op_or_16_re_di(m68ki_cpu_core *cpu); +void m68k_op_or_16_re_ix(m68ki_cpu_core *cpu); +void m68k_op_or_16_re_aw(m68ki_cpu_core *cpu); +void m68k_op_or_16_re_al(m68ki_cpu_core *cpu); +void m68k_op_or_32_re_ai(m68ki_cpu_core *cpu); +void m68k_op_or_32_re_pi(m68ki_cpu_core *cpu); +void m68k_op_or_32_re_pd(m68ki_cpu_core *cpu); +void m68k_op_or_32_re_di(m68ki_cpu_core *cpu); +void m68k_op_or_32_re_ix(m68ki_cpu_core *cpu); +void m68k_op_or_32_re_aw(m68ki_cpu_core *cpu); +void m68k_op_or_32_re_al(m68ki_cpu_core *cpu); +void m68k_op_ori_8_d(m68ki_cpu_core *cpu); +void m68k_op_ori_8_ai(m68ki_cpu_core *cpu); +void m68k_op_ori_8_pi(m68ki_cpu_core *cpu); +void m68k_op_ori_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_ori_8_pd(m68ki_cpu_core *cpu); +void m68k_op_ori_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_ori_8_di(m68ki_cpu_core *cpu); +void m68k_op_ori_8_ix(m68ki_cpu_core *cpu); +void m68k_op_ori_8_aw(m68ki_cpu_core *cpu); +void m68k_op_ori_8_al(m68ki_cpu_core *cpu); +void m68k_op_ori_16_d(m68ki_cpu_core *cpu); +void m68k_op_ori_16_ai(m68ki_cpu_core *cpu); +void m68k_op_ori_16_pi(m68ki_cpu_core *cpu); +void m68k_op_ori_16_pd(m68ki_cpu_core *cpu); +void m68k_op_ori_16_di(m68ki_cpu_core *cpu); +void m68k_op_ori_16_ix(m68ki_cpu_core *cpu); +void m68k_op_ori_16_aw(m68ki_cpu_core *cpu); +void m68k_op_ori_16_al(m68ki_cpu_core *cpu); +void m68k_op_ori_32_d(m68ki_cpu_core *cpu); +void m68k_op_ori_32_ai(m68ki_cpu_core *cpu); +void m68k_op_ori_32_pi(m68ki_cpu_core *cpu); +void m68k_op_ori_32_pd(m68ki_cpu_core *cpu); +void m68k_op_ori_32_di(m68ki_cpu_core *cpu); +void m68k_op_ori_32_ix(m68ki_cpu_core *cpu); +void m68k_op_ori_32_aw(m68ki_cpu_core *cpu); +void m68k_op_ori_32_al(m68ki_cpu_core *cpu); +void m68k_op_ori_16_toc(m68ki_cpu_core *cpu); +void m68k_op_ori_16_tos(m68ki_cpu_core *cpu); +void m68k_op_pack_16_rr(m68ki_cpu_core *cpu); +void m68k_op_pack_16_mm_ax7(m68ki_cpu_core *cpu); +void m68k_op_pack_16_mm_ay7(m68ki_cpu_core *cpu); +void m68k_op_pack_16_mm_axy7(m68ki_cpu_core *cpu); +void m68k_op_pack_16_mm(m68ki_cpu_core *cpu); +void m68k_op_pea_32_ai(m68ki_cpu_core *cpu); +void m68k_op_pea_32_di(m68ki_cpu_core *cpu); +void m68k_op_pea_32_ix(m68ki_cpu_core *cpu); +void m68k_op_pea_32_aw(m68ki_cpu_core *cpu); +void m68k_op_pea_32_al(m68ki_cpu_core *cpu); +void m68k_op_pea_32_pcdi(m68ki_cpu_core *cpu); +void m68k_op_pea_32_pcix(m68ki_cpu_core *cpu); +void m68k_op_reset(m68ki_cpu_core *cpu); +void m68k_op_ror_8_s(m68ki_cpu_core *cpu); +void m68k_op_ror_16_s(m68ki_cpu_core *cpu); +void m68k_op_ror_32_s(m68ki_cpu_core *cpu); +void m68k_op_ror_8_r(m68ki_cpu_core *cpu); +void m68k_op_ror_16_r(m68ki_cpu_core *cpu); +void m68k_op_ror_32_r(m68ki_cpu_core *cpu); +void m68k_op_ror_16_ai(m68ki_cpu_core *cpu); +void m68k_op_ror_16_pi(m68ki_cpu_core *cpu); +void m68k_op_ror_16_pd(m68ki_cpu_core *cpu); +void m68k_op_ror_16_di(m68ki_cpu_core *cpu); +void m68k_op_ror_16_ix(m68ki_cpu_core *cpu); +void m68k_op_ror_16_aw(m68ki_cpu_core *cpu); +void m68k_op_ror_16_al(m68ki_cpu_core *cpu); +void m68k_op_rol_8_s(m68ki_cpu_core *cpu); +void m68k_op_rol_16_s(m68ki_cpu_core *cpu); +void m68k_op_rol_32_s(m68ki_cpu_core *cpu); +void m68k_op_rol_8_r(m68ki_cpu_core *cpu); +void m68k_op_rol_16_r(m68ki_cpu_core *cpu); +void m68k_op_rol_32_r(m68ki_cpu_core *cpu); +void m68k_op_rol_16_ai(m68ki_cpu_core *cpu); +void m68k_op_rol_16_pi(m68ki_cpu_core *cpu); +void m68k_op_rol_16_pd(m68ki_cpu_core *cpu); +void m68k_op_rol_16_di(m68ki_cpu_core *cpu); +void m68k_op_rol_16_ix(m68ki_cpu_core *cpu); +void m68k_op_rol_16_aw(m68ki_cpu_core *cpu); +void m68k_op_rol_16_al(m68ki_cpu_core *cpu); +void m68k_op_roxr_8_s(m68ki_cpu_core *cpu); +void m68k_op_roxr_16_s(m68ki_cpu_core *cpu); +void m68k_op_roxr_32_s(m68ki_cpu_core *cpu); +void m68k_op_roxr_8_r(m68ki_cpu_core *cpu); +void m68k_op_roxr_16_r(m68ki_cpu_core *cpu); +void m68k_op_roxr_32_r(m68ki_cpu_core *cpu); +void m68k_op_roxr_16_ai(m68ki_cpu_core *cpu); +void m68k_op_roxr_16_pi(m68ki_cpu_core *cpu); +void m68k_op_roxr_16_pd(m68ki_cpu_core *cpu); +void m68k_op_roxr_16_di(m68ki_cpu_core *cpu); +void m68k_op_roxr_16_ix(m68ki_cpu_core *cpu); +void m68k_op_roxr_16_aw(m68ki_cpu_core *cpu); +void m68k_op_roxr_16_al(m68ki_cpu_core *cpu); +void m68k_op_roxl_8_s(m68ki_cpu_core *cpu); +void m68k_op_roxl_16_s(m68ki_cpu_core *cpu); +void m68k_op_roxl_32_s(m68ki_cpu_core *cpu); +void m68k_op_roxl_8_r(m68ki_cpu_core *cpu); +void m68k_op_roxl_16_r(m68ki_cpu_core *cpu); +void m68k_op_roxl_32_r(m68ki_cpu_core *cpu); +void m68k_op_roxl_16_ai(m68ki_cpu_core *cpu); +void m68k_op_roxl_16_pi(m68ki_cpu_core *cpu); +void m68k_op_roxl_16_pd(m68ki_cpu_core *cpu); +void m68k_op_roxl_16_di(m68ki_cpu_core *cpu); +void m68k_op_roxl_16_ix(m68ki_cpu_core *cpu); +void m68k_op_roxl_16_aw(m68ki_cpu_core *cpu); +void m68k_op_roxl_16_al(m68ki_cpu_core *cpu); +void m68k_op_rtd_32(m68ki_cpu_core *cpu); +void m68k_op_rte_32(m68ki_cpu_core *cpu); +void m68k_op_rtm_32(m68ki_cpu_core *cpu); +void m68k_op_rtr_32(m68ki_cpu_core *cpu); +void m68k_op_rts_32(m68ki_cpu_core *cpu); +void m68k_op_sbcd_8_rr(m68ki_cpu_core *cpu); +void m68k_op_sbcd_8_mm_ax7(m68ki_cpu_core *cpu); +void m68k_op_sbcd_8_mm_ay7(m68ki_cpu_core *cpu); +void m68k_op_sbcd_8_mm_axy7(m68ki_cpu_core *cpu); +void m68k_op_sbcd_8_mm(m68ki_cpu_core *cpu); +void m68k_op_st_8_d(m68ki_cpu_core *cpu); +void m68k_op_st_8_ai(m68ki_cpu_core *cpu); +void m68k_op_st_8_pi(m68ki_cpu_core *cpu); +void m68k_op_st_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_st_8_pd(m68ki_cpu_core *cpu); +void m68k_op_st_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_st_8_di(m68ki_cpu_core *cpu); +void m68k_op_st_8_ix(m68ki_cpu_core *cpu); +void m68k_op_st_8_aw(m68ki_cpu_core *cpu); +void m68k_op_st_8_al(m68ki_cpu_core *cpu); +void m68k_op_sf_8_d(m68ki_cpu_core *cpu); +void m68k_op_sf_8_ai(m68ki_cpu_core *cpu); +void m68k_op_sf_8_pi(m68ki_cpu_core *cpu); +void m68k_op_sf_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_sf_8_pd(m68ki_cpu_core *cpu); +void m68k_op_sf_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_sf_8_di(m68ki_cpu_core *cpu); +void m68k_op_sf_8_ix(m68ki_cpu_core *cpu); +void m68k_op_sf_8_aw(m68ki_cpu_core *cpu); +void m68k_op_sf_8_al(m68ki_cpu_core *cpu); +void m68k_op_shi_8_d(m68ki_cpu_core *cpu); +void m68k_op_sls_8_d(m68ki_cpu_core *cpu); +void m68k_op_scc_8_d(m68ki_cpu_core *cpu); +void m68k_op_scs_8_d(m68ki_cpu_core *cpu); +void m68k_op_sne_8_d(m68ki_cpu_core *cpu); +void m68k_op_seq_8_d(m68ki_cpu_core *cpu); +void m68k_op_svc_8_d(m68ki_cpu_core *cpu); +void m68k_op_svs_8_d(m68ki_cpu_core *cpu); +void m68k_op_spl_8_d(m68ki_cpu_core *cpu); +void m68k_op_smi_8_d(m68ki_cpu_core *cpu); +void m68k_op_sge_8_d(m68ki_cpu_core *cpu); +void m68k_op_slt_8_d(m68ki_cpu_core *cpu); +void m68k_op_sgt_8_d(m68ki_cpu_core *cpu); +void m68k_op_sle_8_d(m68ki_cpu_core *cpu); +void m68k_op_shi_8_ai(m68ki_cpu_core *cpu); +void m68k_op_shi_8_pi(m68ki_cpu_core *cpu); +void m68k_op_shi_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_shi_8_pd(m68ki_cpu_core *cpu); +void m68k_op_shi_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_shi_8_di(m68ki_cpu_core *cpu); +void m68k_op_shi_8_ix(m68ki_cpu_core *cpu); +void m68k_op_shi_8_aw(m68ki_cpu_core *cpu); +void m68k_op_shi_8_al(m68ki_cpu_core *cpu); +void m68k_op_sls_8_ai(m68ki_cpu_core *cpu); +void m68k_op_sls_8_pi(m68ki_cpu_core *cpu); +void m68k_op_sls_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_sls_8_pd(m68ki_cpu_core *cpu); +void m68k_op_sls_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_sls_8_di(m68ki_cpu_core *cpu); +void m68k_op_sls_8_ix(m68ki_cpu_core *cpu); +void m68k_op_sls_8_aw(m68ki_cpu_core *cpu); +void m68k_op_sls_8_al(m68ki_cpu_core *cpu); +void m68k_op_scc_8_ai(m68ki_cpu_core *cpu); +void m68k_op_scc_8_pi(m68ki_cpu_core *cpu); +void m68k_op_scc_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_scc_8_pd(m68ki_cpu_core *cpu); +void m68k_op_scc_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_scc_8_di(m68ki_cpu_core *cpu); +void m68k_op_scc_8_ix(m68ki_cpu_core *cpu); +void m68k_op_scc_8_aw(m68ki_cpu_core *cpu); +void m68k_op_scc_8_al(m68ki_cpu_core *cpu); +void m68k_op_scs_8_ai(m68ki_cpu_core *cpu); +void m68k_op_scs_8_pi(m68ki_cpu_core *cpu); +void m68k_op_scs_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_scs_8_pd(m68ki_cpu_core *cpu); +void m68k_op_scs_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_scs_8_di(m68ki_cpu_core *cpu); +void m68k_op_scs_8_ix(m68ki_cpu_core *cpu); +void m68k_op_scs_8_aw(m68ki_cpu_core *cpu); +void m68k_op_scs_8_al(m68ki_cpu_core *cpu); +void m68k_op_sne_8_ai(m68ki_cpu_core *cpu); +void m68k_op_sne_8_pi(m68ki_cpu_core *cpu); +void m68k_op_sne_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_sne_8_pd(m68ki_cpu_core *cpu); +void m68k_op_sne_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_sne_8_di(m68ki_cpu_core *cpu); +void m68k_op_sne_8_ix(m68ki_cpu_core *cpu); +void m68k_op_sne_8_aw(m68ki_cpu_core *cpu); +void m68k_op_sne_8_al(m68ki_cpu_core *cpu); +void m68k_op_seq_8_ai(m68ki_cpu_core *cpu); +void m68k_op_seq_8_pi(m68ki_cpu_core *cpu); +void m68k_op_seq_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_seq_8_pd(m68ki_cpu_core *cpu); +void m68k_op_seq_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_seq_8_di(m68ki_cpu_core *cpu); +void m68k_op_seq_8_ix(m68ki_cpu_core *cpu); +void m68k_op_seq_8_aw(m68ki_cpu_core *cpu); +void m68k_op_seq_8_al(m68ki_cpu_core *cpu); +void m68k_op_svc_8_ai(m68ki_cpu_core *cpu); +void m68k_op_svc_8_pi(m68ki_cpu_core *cpu); +void m68k_op_svc_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_svc_8_pd(m68ki_cpu_core *cpu); +void m68k_op_svc_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_svc_8_di(m68ki_cpu_core *cpu); +void m68k_op_svc_8_ix(m68ki_cpu_core *cpu); +void m68k_op_svc_8_aw(m68ki_cpu_core *cpu); +void m68k_op_svc_8_al(m68ki_cpu_core *cpu); +void m68k_op_svs_8_ai(m68ki_cpu_core *cpu); +void m68k_op_svs_8_pi(m68ki_cpu_core *cpu); +void m68k_op_svs_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_svs_8_pd(m68ki_cpu_core *cpu); +void m68k_op_svs_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_svs_8_di(m68ki_cpu_core *cpu); +void m68k_op_svs_8_ix(m68ki_cpu_core *cpu); +void m68k_op_svs_8_aw(m68ki_cpu_core *cpu); +void m68k_op_svs_8_al(m68ki_cpu_core *cpu); +void m68k_op_spl_8_ai(m68ki_cpu_core *cpu); +void m68k_op_spl_8_pi(m68ki_cpu_core *cpu); +void m68k_op_spl_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_spl_8_pd(m68ki_cpu_core *cpu); +void m68k_op_spl_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_spl_8_di(m68ki_cpu_core *cpu); +void m68k_op_spl_8_ix(m68ki_cpu_core *cpu); +void m68k_op_spl_8_aw(m68ki_cpu_core *cpu); +void m68k_op_spl_8_al(m68ki_cpu_core *cpu); +void m68k_op_smi_8_ai(m68ki_cpu_core *cpu); +void m68k_op_smi_8_pi(m68ki_cpu_core *cpu); +void m68k_op_smi_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_smi_8_pd(m68ki_cpu_core *cpu); +void m68k_op_smi_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_smi_8_di(m68ki_cpu_core *cpu); +void m68k_op_smi_8_ix(m68ki_cpu_core *cpu); +void m68k_op_smi_8_aw(m68ki_cpu_core *cpu); +void m68k_op_smi_8_al(m68ki_cpu_core *cpu); +void m68k_op_sge_8_ai(m68ki_cpu_core *cpu); +void m68k_op_sge_8_pi(m68ki_cpu_core *cpu); +void m68k_op_sge_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_sge_8_pd(m68ki_cpu_core *cpu); +void m68k_op_sge_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_sge_8_di(m68ki_cpu_core *cpu); +void m68k_op_sge_8_ix(m68ki_cpu_core *cpu); +void m68k_op_sge_8_aw(m68ki_cpu_core *cpu); +void m68k_op_sge_8_al(m68ki_cpu_core *cpu); +void m68k_op_slt_8_ai(m68ki_cpu_core *cpu); +void m68k_op_slt_8_pi(m68ki_cpu_core *cpu); +void m68k_op_slt_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_slt_8_pd(m68ki_cpu_core *cpu); +void m68k_op_slt_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_slt_8_di(m68ki_cpu_core *cpu); +void m68k_op_slt_8_ix(m68ki_cpu_core *cpu); +void m68k_op_slt_8_aw(m68ki_cpu_core *cpu); +void m68k_op_slt_8_al(m68ki_cpu_core *cpu); +void m68k_op_sgt_8_ai(m68ki_cpu_core *cpu); +void m68k_op_sgt_8_pi(m68ki_cpu_core *cpu); +void m68k_op_sgt_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_sgt_8_pd(m68ki_cpu_core *cpu); +void m68k_op_sgt_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_sgt_8_di(m68ki_cpu_core *cpu); +void m68k_op_sgt_8_ix(m68ki_cpu_core *cpu); +void m68k_op_sgt_8_aw(m68ki_cpu_core *cpu); +void m68k_op_sgt_8_al(m68ki_cpu_core *cpu); +void m68k_op_sle_8_ai(m68ki_cpu_core *cpu); +void m68k_op_sle_8_pi(m68ki_cpu_core *cpu); +void m68k_op_sle_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_sle_8_pd(m68ki_cpu_core *cpu); +void m68k_op_sle_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_sle_8_di(m68ki_cpu_core *cpu); +void m68k_op_sle_8_ix(m68ki_cpu_core *cpu); +void m68k_op_sle_8_aw(m68ki_cpu_core *cpu); +void m68k_op_sle_8_al(m68ki_cpu_core *cpu); +void m68k_op_stop(m68ki_cpu_core *cpu); +void m68k_op_sub_8_er_d(m68ki_cpu_core *cpu); +void m68k_op_sub_8_er_ai(m68ki_cpu_core *cpu); +void m68k_op_sub_8_er_pi(m68ki_cpu_core *cpu); +void m68k_op_sub_8_er_pi7(m68ki_cpu_core *cpu); +void m68k_op_sub_8_er_pd(m68ki_cpu_core *cpu); +void m68k_op_sub_8_er_pd7(m68ki_cpu_core *cpu); +void m68k_op_sub_8_er_di(m68ki_cpu_core *cpu); +void m68k_op_sub_8_er_ix(m68ki_cpu_core *cpu); +void m68k_op_sub_8_er_aw(m68ki_cpu_core *cpu); +void m68k_op_sub_8_er_al(m68ki_cpu_core *cpu); +void m68k_op_sub_8_er_pcdi(m68ki_cpu_core *cpu); +void m68k_op_sub_8_er_pcix(m68ki_cpu_core *cpu); +void m68k_op_sub_8_er_i(m68ki_cpu_core *cpu); +void m68k_op_sub_16_er_d(m68ki_cpu_core *cpu); +void m68k_op_sub_16_er_a(m68ki_cpu_core *cpu); +void m68k_op_sub_16_er_ai(m68ki_cpu_core *cpu); +void m68k_op_sub_16_er_pi(m68ki_cpu_core *cpu); +void m68k_op_sub_16_er_pd(m68ki_cpu_core *cpu); +void m68k_op_sub_16_er_di(m68ki_cpu_core *cpu); +void m68k_op_sub_16_er_ix(m68ki_cpu_core *cpu); +void m68k_op_sub_16_er_aw(m68ki_cpu_core *cpu); +void m68k_op_sub_16_er_al(m68ki_cpu_core *cpu); +void m68k_op_sub_16_er_pcdi(m68ki_cpu_core *cpu); +void m68k_op_sub_16_er_pcix(m68ki_cpu_core *cpu); +void m68k_op_sub_16_er_i(m68ki_cpu_core *cpu); +void m68k_op_sub_32_er_d(m68ki_cpu_core *cpu); +void m68k_op_sub_32_er_a(m68ki_cpu_core *cpu); +void m68k_op_sub_32_er_ai(m68ki_cpu_core *cpu); +void m68k_op_sub_32_er_pi(m68ki_cpu_core *cpu); +void m68k_op_sub_32_er_pd(m68ki_cpu_core *cpu); +void m68k_op_sub_32_er_di(m68ki_cpu_core *cpu); +void m68k_op_sub_32_er_ix(m68ki_cpu_core *cpu); +void m68k_op_sub_32_er_aw(m68ki_cpu_core *cpu); +void m68k_op_sub_32_er_al(m68ki_cpu_core *cpu); +void m68k_op_sub_32_er_pcdi(m68ki_cpu_core *cpu); +void m68k_op_sub_32_er_pcix(m68ki_cpu_core *cpu); +void m68k_op_sub_32_er_i(m68ki_cpu_core *cpu); +void m68k_op_sub_8_re_ai(m68ki_cpu_core *cpu); +void m68k_op_sub_8_re_pi(m68ki_cpu_core *cpu); +void m68k_op_sub_8_re_pi7(m68ki_cpu_core *cpu); +void m68k_op_sub_8_re_pd(m68ki_cpu_core *cpu); +void m68k_op_sub_8_re_pd7(m68ki_cpu_core *cpu); +void m68k_op_sub_8_re_di(m68ki_cpu_core *cpu); +void m68k_op_sub_8_re_ix(m68ki_cpu_core *cpu); +void m68k_op_sub_8_re_aw(m68ki_cpu_core *cpu); +void m68k_op_sub_8_re_al(m68ki_cpu_core *cpu); +void m68k_op_sub_16_re_ai(m68ki_cpu_core *cpu); +void m68k_op_sub_16_re_pi(m68ki_cpu_core *cpu); +void m68k_op_sub_16_re_pd(m68ki_cpu_core *cpu); +void m68k_op_sub_16_re_di(m68ki_cpu_core *cpu); +void m68k_op_sub_16_re_ix(m68ki_cpu_core *cpu); +void m68k_op_sub_16_re_aw(m68ki_cpu_core *cpu); +void m68k_op_sub_16_re_al(m68ki_cpu_core *cpu); +void m68k_op_sub_32_re_ai(m68ki_cpu_core *cpu); +void m68k_op_sub_32_re_pi(m68ki_cpu_core *cpu); +void m68k_op_sub_32_re_pd(m68ki_cpu_core *cpu); +void m68k_op_sub_32_re_di(m68ki_cpu_core *cpu); +void m68k_op_sub_32_re_ix(m68ki_cpu_core *cpu); +void m68k_op_sub_32_re_aw(m68ki_cpu_core *cpu); +void m68k_op_sub_32_re_al(m68ki_cpu_core *cpu); +void m68k_op_suba_16_d(m68ki_cpu_core *cpu); +void m68k_op_suba_16_a(m68ki_cpu_core *cpu); +void m68k_op_suba_16_ai(m68ki_cpu_core *cpu); +void m68k_op_suba_16_pi(m68ki_cpu_core *cpu); +void m68k_op_suba_16_pd(m68ki_cpu_core *cpu); +void m68k_op_suba_16_di(m68ki_cpu_core *cpu); +void m68k_op_suba_16_ix(m68ki_cpu_core *cpu); +void m68k_op_suba_16_aw(m68ki_cpu_core *cpu); +void m68k_op_suba_16_al(m68ki_cpu_core *cpu); +void m68k_op_suba_16_pcdi(m68ki_cpu_core *cpu); +void m68k_op_suba_16_pcix(m68ki_cpu_core *cpu); +void m68k_op_suba_16_i(m68ki_cpu_core *cpu); +void m68k_op_suba_32_d(m68ki_cpu_core *cpu); +void m68k_op_suba_32_a(m68ki_cpu_core *cpu); +void m68k_op_suba_32_ai(m68ki_cpu_core *cpu); +void m68k_op_suba_32_pi(m68ki_cpu_core *cpu); +void m68k_op_suba_32_pd(m68ki_cpu_core *cpu); +void m68k_op_suba_32_di(m68ki_cpu_core *cpu); +void m68k_op_suba_32_ix(m68ki_cpu_core *cpu); +void m68k_op_suba_32_aw(m68ki_cpu_core *cpu); +void m68k_op_suba_32_al(m68ki_cpu_core *cpu); +void m68k_op_suba_32_pcdi(m68ki_cpu_core *cpu); +void m68k_op_suba_32_pcix(m68ki_cpu_core *cpu); +void m68k_op_suba_32_i(m68ki_cpu_core *cpu); +void m68k_op_subi_8_d(m68ki_cpu_core *cpu); +void m68k_op_subi_8_ai(m68ki_cpu_core *cpu); +void m68k_op_subi_8_pi(m68ki_cpu_core *cpu); +void m68k_op_subi_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_subi_8_pd(m68ki_cpu_core *cpu); +void m68k_op_subi_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_subi_8_di(m68ki_cpu_core *cpu); +void m68k_op_subi_8_ix(m68ki_cpu_core *cpu); +void m68k_op_subi_8_aw(m68ki_cpu_core *cpu); +void m68k_op_subi_8_al(m68ki_cpu_core *cpu); +void m68k_op_subi_16_d(m68ki_cpu_core *cpu); +void m68k_op_subi_16_ai(m68ki_cpu_core *cpu); +void m68k_op_subi_16_pi(m68ki_cpu_core *cpu); +void m68k_op_subi_16_pd(m68ki_cpu_core *cpu); +void m68k_op_subi_16_di(m68ki_cpu_core *cpu); +void m68k_op_subi_16_ix(m68ki_cpu_core *cpu); +void m68k_op_subi_16_aw(m68ki_cpu_core *cpu); +void m68k_op_subi_16_al(m68ki_cpu_core *cpu); +void m68k_op_subi_32_d(m68ki_cpu_core *cpu); +void m68k_op_subi_32_ai(m68ki_cpu_core *cpu); +void m68k_op_subi_32_pi(m68ki_cpu_core *cpu); +void m68k_op_subi_32_pd(m68ki_cpu_core *cpu); +void m68k_op_subi_32_di(m68ki_cpu_core *cpu); +void m68k_op_subi_32_ix(m68ki_cpu_core *cpu); +void m68k_op_subi_32_aw(m68ki_cpu_core *cpu); +void m68k_op_subi_32_al(m68ki_cpu_core *cpu); +void m68k_op_subq_8_d(m68ki_cpu_core *cpu); +void m68k_op_subq_8_ai(m68ki_cpu_core *cpu); +void m68k_op_subq_8_pi(m68ki_cpu_core *cpu); +void m68k_op_subq_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_subq_8_pd(m68ki_cpu_core *cpu); +void m68k_op_subq_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_subq_8_di(m68ki_cpu_core *cpu); +void m68k_op_subq_8_ix(m68ki_cpu_core *cpu); +void m68k_op_subq_8_aw(m68ki_cpu_core *cpu); +void m68k_op_subq_8_al(m68ki_cpu_core *cpu); +void m68k_op_subq_16_d(m68ki_cpu_core *cpu); +void m68k_op_subq_16_a(m68ki_cpu_core *cpu); +void m68k_op_subq_16_ai(m68ki_cpu_core *cpu); +void m68k_op_subq_16_pi(m68ki_cpu_core *cpu); +void m68k_op_subq_16_pd(m68ki_cpu_core *cpu); +void m68k_op_subq_16_di(m68ki_cpu_core *cpu); +void m68k_op_subq_16_ix(m68ki_cpu_core *cpu); +void m68k_op_subq_16_aw(m68ki_cpu_core *cpu); +void m68k_op_subq_16_al(m68ki_cpu_core *cpu); +void m68k_op_subq_32_d(m68ki_cpu_core *cpu); +void m68k_op_subq_32_a(m68ki_cpu_core *cpu); +void m68k_op_subq_32_ai(m68ki_cpu_core *cpu); +void m68k_op_subq_32_pi(m68ki_cpu_core *cpu); +void m68k_op_subq_32_pd(m68ki_cpu_core *cpu); +void m68k_op_subq_32_di(m68ki_cpu_core *cpu); +void m68k_op_subq_32_ix(m68ki_cpu_core *cpu); +void m68k_op_subq_32_aw(m68ki_cpu_core *cpu); +void m68k_op_subq_32_al(m68ki_cpu_core *cpu); +void m68k_op_subx_8_rr(m68ki_cpu_core *cpu); +void m68k_op_subx_16_rr(m68ki_cpu_core *cpu); +void m68k_op_subx_32_rr(m68ki_cpu_core *cpu); +void m68k_op_subx_8_mm_ax7(m68ki_cpu_core *cpu); +void m68k_op_subx_8_mm_ay7(m68ki_cpu_core *cpu); +void m68k_op_subx_8_mm_axy7(m68ki_cpu_core *cpu); +void m68k_op_subx_8_mm(m68ki_cpu_core *cpu); +void m68k_op_subx_16_mm(m68ki_cpu_core *cpu); +void m68k_op_subx_32_mm(m68ki_cpu_core *cpu); +void m68k_op_swap_32(m68ki_cpu_core *cpu); +void m68k_op_tas_8_d(m68ki_cpu_core *cpu); +void m68k_op_tas_8_ai(m68ki_cpu_core *cpu); +void m68k_op_tas_8_pi(m68ki_cpu_core *cpu); +void m68k_op_tas_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_tas_8_pd(m68ki_cpu_core *cpu); +void m68k_op_tas_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_tas_8_di(m68ki_cpu_core *cpu); +void m68k_op_tas_8_ix(m68ki_cpu_core *cpu); +void m68k_op_tas_8_aw(m68ki_cpu_core *cpu); +void m68k_op_tas_8_al(m68ki_cpu_core *cpu); +void m68k_op_trap(m68ki_cpu_core *cpu); +void m68k_op_trapt(m68ki_cpu_core *cpu); +void m68k_op_trapt_16(m68ki_cpu_core *cpu); +void m68k_op_trapt_32(m68ki_cpu_core *cpu); +void m68k_op_trapf(m68ki_cpu_core *cpu); +void m68k_op_trapf_16(m68ki_cpu_core *cpu); +void m68k_op_trapf_32(m68ki_cpu_core *cpu); +void m68k_op_traphi(m68ki_cpu_core *cpu); +void m68k_op_trapls(m68ki_cpu_core *cpu); +void m68k_op_trapcc(m68ki_cpu_core *cpu); +void m68k_op_trapcs(m68ki_cpu_core *cpu); +void m68k_op_trapne(m68ki_cpu_core *cpu); +void m68k_op_trapeq(m68ki_cpu_core *cpu); +void m68k_op_trapvc(m68ki_cpu_core *cpu); +void m68k_op_trapvs(m68ki_cpu_core *cpu); +void m68k_op_trappl(m68ki_cpu_core *cpu); +void m68k_op_trapmi(m68ki_cpu_core *cpu); +void m68k_op_trapge(m68ki_cpu_core *cpu); +void m68k_op_traplt(m68ki_cpu_core *cpu); +void m68k_op_trapgt(m68ki_cpu_core *cpu); +void m68k_op_traple(m68ki_cpu_core *cpu); +void m68k_op_traphi_16(m68ki_cpu_core *cpu); +void m68k_op_trapls_16(m68ki_cpu_core *cpu); +void m68k_op_trapcc_16(m68ki_cpu_core *cpu); +void m68k_op_trapcs_16(m68ki_cpu_core *cpu); +void m68k_op_trapne_16(m68ki_cpu_core *cpu); +void m68k_op_trapeq_16(m68ki_cpu_core *cpu); +void m68k_op_trapvc_16(m68ki_cpu_core *cpu); +void m68k_op_trapvs_16(m68ki_cpu_core *cpu); +void m68k_op_trappl_16(m68ki_cpu_core *cpu); +void m68k_op_trapmi_16(m68ki_cpu_core *cpu); +void m68k_op_trapge_16(m68ki_cpu_core *cpu); +void m68k_op_traplt_16(m68ki_cpu_core *cpu); +void m68k_op_trapgt_16(m68ki_cpu_core *cpu); +void m68k_op_traple_16(m68ki_cpu_core *cpu); +void m68k_op_traphi_32(m68ki_cpu_core *cpu); +void m68k_op_trapls_32(m68ki_cpu_core *cpu); +void m68k_op_trapcc_32(m68ki_cpu_core *cpu); +void m68k_op_trapcs_32(m68ki_cpu_core *cpu); +void m68k_op_trapne_32(m68ki_cpu_core *cpu); +void m68k_op_trapeq_32(m68ki_cpu_core *cpu); +void m68k_op_trapvc_32(m68ki_cpu_core *cpu); +void m68k_op_trapvs_32(m68ki_cpu_core *cpu); +void m68k_op_trappl_32(m68ki_cpu_core *cpu); +void m68k_op_trapmi_32(m68ki_cpu_core *cpu); +void m68k_op_trapge_32(m68ki_cpu_core *cpu); +void m68k_op_traplt_32(m68ki_cpu_core *cpu); +void m68k_op_trapgt_32(m68ki_cpu_core *cpu); +void m68k_op_traple_32(m68ki_cpu_core *cpu); +void m68k_op_trapv(m68ki_cpu_core *cpu); +void m68k_op_tst_8_d(m68ki_cpu_core *cpu); +void m68k_op_tst_8_ai(m68ki_cpu_core *cpu); +void m68k_op_tst_8_pi(m68ki_cpu_core *cpu); +void m68k_op_tst_8_pi7(m68ki_cpu_core *cpu); +void m68k_op_tst_8_pd(m68ki_cpu_core *cpu); +void m68k_op_tst_8_pd7(m68ki_cpu_core *cpu); +void m68k_op_tst_8_di(m68ki_cpu_core *cpu); +void m68k_op_tst_8_ix(m68ki_cpu_core *cpu); +void m68k_op_tst_8_aw(m68ki_cpu_core *cpu); +void m68k_op_tst_8_al(m68ki_cpu_core *cpu); +void m68k_op_tst_8_pcdi(m68ki_cpu_core *cpu); +void m68k_op_tst_8_pcix(m68ki_cpu_core *cpu); +void m68k_op_tst_8_i(m68ki_cpu_core *cpu); +void m68k_op_tst_16_d(m68ki_cpu_core *cpu); +void m68k_op_tst_16_a(m68ki_cpu_core *cpu); +void m68k_op_tst_16_ai(m68ki_cpu_core *cpu); +void m68k_op_tst_16_pi(m68ki_cpu_core *cpu); +void m68k_op_tst_16_pd(m68ki_cpu_core *cpu); +void m68k_op_tst_16_di(m68ki_cpu_core *cpu); +void m68k_op_tst_16_ix(m68ki_cpu_core *cpu); +void m68k_op_tst_16_aw(m68ki_cpu_core *cpu); +void m68k_op_tst_16_al(m68ki_cpu_core *cpu); +void m68k_op_tst_16_pcdi(m68ki_cpu_core *cpu); +void m68k_op_tst_16_pcix(m68ki_cpu_core *cpu); +void m68k_op_tst_16_i(m68ki_cpu_core *cpu); +void m68k_op_tst_32_d(m68ki_cpu_core *cpu); +void m68k_op_tst_32_a(m68ki_cpu_core *cpu); +void m68k_op_tst_32_ai(m68ki_cpu_core *cpu); +void m68k_op_tst_32_pi(m68ki_cpu_core *cpu); +void m68k_op_tst_32_pd(m68ki_cpu_core *cpu); +void m68k_op_tst_32_di(m68ki_cpu_core *cpu); +void m68k_op_tst_32_ix(m68ki_cpu_core *cpu); +void m68k_op_tst_32_aw(m68ki_cpu_core *cpu); +void m68k_op_tst_32_al(m68ki_cpu_core *cpu); +void m68k_op_tst_32_pcdi(m68ki_cpu_core *cpu); +void m68k_op_tst_32_pcix(m68ki_cpu_core *cpu); +void m68k_op_tst_32_i(m68ki_cpu_core *cpu); +void m68k_op_unlk_32_a7(m68ki_cpu_core *cpu); +void m68k_op_unlk_32(m68ki_cpu_core *cpu); +void m68k_op_unpk_16_rr(m68ki_cpu_core *cpu); +void m68k_op_unpk_16_mm_ax7(m68ki_cpu_core *cpu); +void m68k_op_unpk_16_mm_ay7(m68ki_cpu_core *cpu); +void m68k_op_unpk_16_mm_axy7(m68ki_cpu_core *cpu); +void m68k_op_unpk_16_mm(m68ki_cpu_core *cpu); +/* Build the opcode handler table */ +void m68ki_build_opcode_table(); + +extern void (*m68ki_instruction_jump_table[0x10000])(m68ki_cpu_core *cpu); /* opcode handler jump table */ +extern unsigned char m68ki_cycles[][0x10000]; + + +/* ======================================================================== */ +/* ============================== END OF FILE ============================= */ +/* ======================================================================== */ + +#endif /* M68KOPS__HEADER */ + + diff --git a/plugins/ao/eng_ssf/sat_hw.c b/plugins/ao/eng_ssf/sat_hw.c new file mode 100644 index 00000000..fd324fdc --- /dev/null +++ b/plugins/ao/eng_ssf/sat_hw.c @@ -0,0 +1,180 @@ +/* + sat_hw.c - Saturn sound hardware glue/emulation/whatever + + supported: main RAM (512 KB) + SCSP + timers + MC68000 CPU + + Copyright (c) 2007, R. Belmont and Richard Bannister. + + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <stdio.h> + +#include "ao.h" +#include "scsp.h" +#include "sat_hw.h" +#include "m68k.h" +#include "m68kcpu.h" + +static void scsp_irq(m68ki_cpu_core *cpu, int irq) +{ + if (irq > 0) + { + m68k_set_irq(cpu, irq); + } +} + +#define MIXER_PAN_LEFT 1 +#define MIXER_PAN_RIGHT 2 +#define MIXER(level,pan) ((level & 0xff) | ((pan & 0x03) << 8)) +#define YM3012_VOL(LVol,LPan,RVol,RPan) (MIXER(LVol,LPan)|(MIXER(RVol,RPan) << 16)) + +#if 0 +static struct SCSPinterface scsp_interface =
+{
+ 1, + { sat_ram, }, + { YM3012_VOL(100, MIXER_PAN_LEFT, 100, MIXER_PAN_RIGHT) }, + { scsp_irq, }, +};
+#endif + +void sat_hw_init(m68ki_cpu_core *cpu) +{ +// m68k_init(); + m68k_set_cpu_type(cpu, M68K_CPU_TYPE_68000); + m68k_pulse_reset(cpu); + struct SCSPinterface scsp_interface; + scsp_interface.num = 1; + scsp_interface.region[0] = cpu->sat_ram; + scsp_interface.mixing_level[0] = YM3012_VOL(100, MIXER_PAN_LEFT, 100, MIXER_PAN_RIGHT); + scsp_interface.irq_callback[0] = scsp_irq; + scsp_interface.cpu = cpu; + + cpu->SCSP = SCSP_Start(&scsp_interface); +} + +void sat_hw_free(struct m68ki_cpu_core_s *cpu) { + SCSP_Exit (cpu->SCSP); +} + +/* M68k memory handlers */ + +unsigned int m68k_read_memory_8(m68ki_cpu_core *cpu, unsigned int address) +{ + if (address < (512*1024)) + return cpu->sat_ram[address^1]; + + if (address >= 0x100000 && address < 0x100c00) + { + int foo = SCSP_0_r(cpu->SCSP, (address - 0x100000)/2, 0); + + if (address & 1) + return foo & 0xff; + else + return foo>>8; + } + + printf("R8 @ %x\n", address); + return 0; +} + +unsigned int m68k_read_memory_16(m68ki_cpu_core *cpu, unsigned int address) +{ + if (address < (512*1024)) + { + return mem_readword_swap((unsigned short *)(cpu->sat_ram+address)); + } + + if (address >= 0x100000 && address < 0x100c00) + return SCSP_0_r(cpu->SCSP, (address-0x100000)/2, 0); + + printf("R16 @ %x\n", address); + return 0; +} + +unsigned int m68k_read_memory_32(m68ki_cpu_core *cpu, unsigned int address) +{ + if (address < 0x80000) + { + return cpu->sat_ram[address+2] | cpu->sat_ram[address+3]<<8 | cpu->sat_ram[address]<<16 | cpu->sat_ram[address+1]<<24; + } + + printf("R32 @ %x\n", address); + return 0; +} + +void m68k_write_memory_8(m68ki_cpu_core *cpu, unsigned int address, unsigned int data) +{ + if (address < 0x80000) + { + cpu->sat_ram[address^1] = data; + return; + } + + if (address >= 0x100000 && address < 0x100c00) + { + address -= 0x100000; + if (address & 1) + SCSP_0_w(cpu->SCSP, address>>1, data, 0xff00); + else + SCSP_0_w(cpu->SCSP, address>>1, data<<8, 0x00ff); + return; + } +} + +void m68k_write_memory_16(m68ki_cpu_core *cpu, unsigned int address, unsigned int data) +{ + if (address < 0x80000) + { + cpu->sat_ram[address+1] = (data>>8)&0xff; + cpu->sat_ram[address] = data&0xff; + return; + } + + if (address >= 0x100000 && address < 0x100c00) + { + SCSP_0_w(cpu->SCSP, (address-0x100000)>>1, data, 0x0000); + return; + } +} + +void m68k_write_memory_32(m68ki_cpu_core *cpu, unsigned int address, unsigned int data) +{ + if (address < 0x80000) + { + cpu->sat_ram[address+1] = (data>>24)&0xff; + cpu->sat_ram[address] = (data>>16)&0xff; + cpu->sat_ram[address+3] = (data>>8)&0xff; + cpu->sat_ram[address+2] = data&0xff; + return; + } + + if (address >= 0x100000 && address < 0x100c00) + { + address -= 0x100000; + SCSP_0_w(cpu->SCSP, address>>1, data>>16, 0x0000); + SCSP_0_w(cpu->SCSP, (address>>1)+1, data&0xffff, 0x0000); + return; + } +} diff --git a/plugins/ao/eng_ssf/sat_hw.h b/plugins/ao/eng_ssf/sat_hw.h new file mode 100644 index 00000000..fe0935c9 --- /dev/null +++ b/plugins/ao/eng_ssf/sat_hw.h @@ -0,0 +1,36 @@ +#ifndef _SAT_HW_H_ +#define _SAT_HW_H_ + +struct m68ki_cpu_core_s; + +void sat_hw_init(struct m68ki_cpu_core_s *cpu); +void sat_hw_free(struct m68ki_cpu_core_s *cpu); + +#if !LSB_FIRST +static unsigned short INLINE mem_readword_swap(unsigned short *addr) +{ + return ((*addr&0x00ff)<<8)|((*addr&0xff00)>>8); +} + +static void INLINE mem_writeword_swap(unsigned short *addr, unsigned short value) +{ + *addr = ((value&0x00ff)<<8)|((value&0xff00)>>8); +} +#else // big endian +static unsigned short INLINE mem_readword_swap(unsigned short *addr) +{ + unsigned long retval; + + retval = *addr; + + return retval; +} + +static void INLINE mem_writeword_swap(unsigned short *addr, unsigned short value) +{ + *addr = value; +} +#endif + + +#endif diff --git a/plugins/ao/eng_ssf/scsp.c b/plugins/ao/eng_ssf/scsp.c new file mode 100644 index 00000000..f3a3d9da --- /dev/null +++ b/plugins/ao/eng_ssf/scsp.c @@ -0,0 +1,1277 @@ +/* + Sega/Yamaha YMF292-F (SCSP = Saturn Custom Sound Processor) emulation + By ElSemi + MAME/M1 conversion and cleanup by R. Belmont + Additional code and bugfixes by kingshriek + + This chip has 32 voices. Each voice can play a sample or be part of + an FM construct. Unlike traditional Yamaha FM chips, the base waveform + for the FM still comes from the wavetable RAM. + + ChangeLog: + * November 25, 2003 (ES) Fixed buggy timers and envelope overflows. + (RB) Improved sample rates other than 44100, multiple + chips now works properly. + * December 02, 2003 (ES) Added DISDL register support, improves mix. + * April 28, 2004 (ES) Corrected envelope rates, added key-rate scaling, + added ringbuffer support. + * January 8, 2005 (RB) Added ability to specify region offset for RAM. + * January 26, 2007 (ES) Added on-board DSP capability + * December 16, 2007 (kingshriek) Many EG bug fixes, implemented effects mixer, + implemented FM. +*/ + +#include <math.h> +#include <string.h> +#include "ao.h" +#include "cpuintrf.h" +#include "scsp.h" +#include "scspdsp.h" +#include "sat_hw.h" + +#define ICLIP16(x) (x<-32768)?-32768:((x>32767)?32767:x) + +#define SHIFT 12 +#define FIX(v) ((UINT32) ((float) (1<<SHIFT)*(v))) + + +#define EG_SHIFT 16 +#define FM_DELAY 0 // delay in number of slots processed before samples are written to the FM ring buffer + +// include the LFO handling code +#include "scsplfo.c" + +/* + SCSP features 32 programmable slots + that can generate FM and PCM (from ROM/RAM) sound +*/ + +//SLOT PARAMETERS +#define KEYONEX(slot) ((slot->udata.data[0x0]>>0x0)&0x1000) +#define KEYONB(slot) ((slot->udata.data[0x0]>>0x0)&0x0800) +#define SBCTL(slot) ((slot->udata.data[0x0]>>0x9)&0x0003) +#define SSCTL(slot) ((slot->udata.data[0x0]>>0x7)&0x0003) +#define LPCTL(slot) ((slot->udata.data[0x0]>>0x5)&0x0003) +#define PCM8B(slot) ((slot->udata.data[0x0]>>0x0)&0x0010) + +#define SA(slot) (((slot->udata.data[0x0]&0xF)<<16)|(slot->udata.data[0x1])) + +#define LSA(slot) (slot->udata.data[0x2]) + +#define LEA(slot) (slot->udata.data[0x3]) + +#define D2R(slot) ((slot->udata.data[0x4]>>0xB)&0x001F) +#define D1R(slot) ((slot->udata.data[0x4]>>0x6)&0x001F) +#define EGHOLD(slot) ((slot->udata.data[0x4]>>0x0)&0x0020) +#define AR(slot) ((slot->udata.data[0x4]>>0x0)&0x001F) + +#define LPSLNK(slot) ((slot->udata.data[0x5]>>0x0)&0x4000) +#define KRS(slot) ((slot->udata.data[0x5]>>0xA)&0x000F) +#define DL(slot) ((slot->udata.data[0x5]>>0x5)&0x001F) +#define RR(slot) ((slot->udata.data[0x5]>>0x0)&0x001F) + +#define STWINH(slot) ((slot->udata.data[0x6]>>0x0)&0x0200) +#define SDIR(slot) ((slot->udata.data[0x6]>>0x0)&0x0100) +#define TL(slot) ((slot->udata.data[0x6]>>0x0)&0x00FF) + +#define MDL(slot) ((slot->udata.data[0x7]>>0xC)&0x000F) +#define MDXSL(slot) ((slot->udata.data[0x7]>>0x6)&0x003F) +#define MDYSL(slot) ((slot->udata.data[0x7]>>0x0)&0x003F) + +#define OCT(slot) ((slot->udata.data[0x8]>>0xB)&0x000F) +#define FNS(slot) ((slot->udata.data[0x8]>>0x0)&0x03FF) + +#define LFORE(slot) ((slot->udata.data[0x9]>>0x0)&0x8000) +#define LFOF(slot) ((slot->udata.data[0x9]>>0xA)&0x001F) +#define PLFOWS(slot) ((slot->udata.data[0x9]>>0x8)&0x0003) +#define PLFOS(slot) ((slot->udata.data[0x9]>>0x5)&0x0007) +#define ALFOWS(slot) ((slot->udata.data[0x9]>>0x3)&0x0003) +#define ALFOS(slot) ((slot->udata.data[0x9]>>0x0)&0x0007) + +#define ISEL(slot) ((slot->udata.data[0xA]>>0x3)&0x000F) +#define IMXL(slot) ((slot->udata.data[0xA]>>0x0)&0x0007) + +#define DISDL(slot) ((slot->udata.data[0xB]>>0xD)&0x0007) +#define DIPAN(slot) ((slot->udata.data[0xB]>>0x8)&0x001F) +#define EFSDL(slot) ((slot->udata.data[0xB]>>0x5)&0x0007) +#define EFPAN(slot) ((slot->udata.data[0xB]>>0x0)&0x001F) + +//Envelope times in ms +static const double ARTimes[64]={100000/*infinity*/,100000/*infinity*/,8100.0,6900.0,6000.0,4800.0,4000.0,3400.0,3000.0,2400.0,2000.0,1700.0,1500.0, + 1200.0,1000.0,860.0,760.0,600.0,500.0,430.0,380.0,300.0,250.0,220.0,190.0,150.0,130.0,110.0,95.0, + 76.0,63.0,55.0,47.0,38.0,31.0,27.0,24.0,19.0,15.0,13.0,12.0,9.4,7.9,6.8,6.0,4.7,3.8,3.4,3.0,2.4, + 2.0,1.8,1.6,1.3,1.1,0.93,0.85,0.65,0.53,0.44,0.40,0.35,0.0,0.0}; +static const double DRTimes[64]={100000/*infinity*/,100000/*infinity*/,118200.0,101300.0,88600.0,70900.0,59100.0,50700.0,44300.0,35500.0,29600.0,25300.0,22200.0,17700.0, + 14800.0,12700.0,11100.0,8900.0,7400.0,6300.0,5500.0,4400.0,3700.0,3200.0,2800.0,2200.0,1800.0,1600.0,1400.0,1100.0, + 920.0,790.0,690.0,550.0,460.0,390.0,340.0,270.0,230.0,200.0,170.0,140.0,110.0,98.0,85.0,68.0,57.0,49.0,43.0,34.0, + 28.0,25.0,22.0,18.0,14.0,12.0,11.0,8.5,7.1,6.1,5.4,4.3,3.6,3.1}; +static UINT32 FNS_Table[0x400]; +static INT32 EG_TABLE[0x400]; + +typedef enum {ATTACK,DECAY1,DECAY2,RELEASE} _STATE; +struct _EG +{ + int volume; // + _STATE state; + int step; + //step vals + int AR; //Attack + int D1R; //Decay1 + int D2R; //Decay2 + int RR; //Release + + int DL; //Decay level + UINT8 EGHOLD; + UINT8 LPLINK; +}; + +struct _SLOT +{ + union + { + UINT16 data[0x10]; //only 0x1a bytes used + UINT8 datab[0x20]; + } udata; + UINT8 active; //this slot is currently playing + UINT8 *base; //samples base address + UINT32 cur_addr; //current play address (24.8) + UINT32 nxt_addr; //next play address + UINT32 step; //pitch step (24.8) + UINT8 Backwards; //the wave is playing backwards + struct _EG EG; //Envelope + struct _LFO PLFO; //Phase LFO + struct _LFO ALFO; //Amplitude LFO + int slot; + signed short Prev; //Previous sample (for interpolation) +}; + +#define MEM4B(scsp) ((scsp->udata.data[0]>>0x0)&0x0200) +#define DAC18B(scsp) ((scsp->udata.data[0]>>0x0)&0x0100) +#define MVOL(scsp) ((scsp->udata.data[0]>>0x0)&0x000F) +#define RBL(scsp) ((scsp->udata.data[1]>>0x7)&0x0003) +#define RBP(scsp) ((scsp->udata.data[1]>>0x0)&0x003F) +#define MOFULL(scsp) ((scsp->udata.data[2]>>0x0)&0x1000) +#define MOEMPTY(scsp) ((scsp->udata.data[2]>>0x0)&0x0800) +#define MIOVF(scsp) ((scsp->udata.data[2]>>0x0)&0x0400) +#define MIFULL(scsp) ((scsp->udata.data[2]>>0x0)&0x0200) +#define MIEMPTY(scsp) ((scsp->udata.data[2]>>0x0)&0x0100) + +#define SCILV0(scsp) ((scsp->udata.data[0x24/2]>>0x0)&0xff) +#define SCILV1(scsp) ((scsp->udata.data[0x26/2]>>0x0)&0xff) +#define SCILV2(scsp) ((scsp->udata.data[0x28/2]>>0x0)&0xff) + +#define SCIEX0 0 +#define SCIEX1 1 +#define SCIEX2 2 +#define SCIMID 3 +#define SCIDMA 4 +#define SCIIRQ 5 +#define SCITMA 6 +#define SCITMB 7 + +#define USEDSP + +struct m68ki_cpu_core_s; + +struct _SCSP +{ + union + { + UINT16 data[0x30/2]; + UINT8 datab[0x30]; + } udata; + struct _SLOT Slots[32]; + signed short RINGBUF[64]; + unsigned char BUFPTR; +#if FM_DELAY + signed short DELAYBUF[FM_DELAY]; + unsigned char DELAYPTR; +#endif + unsigned char *SCSPRAM; + UINT32 SCSPRAM_LENGTH; + char Master; + void (*Int68kCB)(struct m68ki_cpu_core_s *cpu, int irq); + + INT32 *buffertmpl, *buffertmpr; + + UINT32 IrqTimA; + UINT32 IrqTimBC; + UINT32 IrqMidi; + + UINT8 MidiOutW,MidiOutR; + UINT8 MidiStack[16]; + UINT8 MidiW,MidiR; + + int LPANTABLE[0x10000]; + int RPANTABLE[0x10000]; + + int TimPris[3]; + int TimCnt[3]; + + // DMA stuff + UINT32 scsp_dmea; + UINT16 scsp_drga; + UINT16 scsp_dtlg; + + int ARTABLE[64], DRTABLE[64]; + + struct m68ki_cpu_core_s *cpu; + struct _SCSPDSP DSP; + + INT16 *bufferl; + INT16 *bufferr; + + int length; + + signed short *RBUFDST; //this points to where the sample will be stored in the RingBuf +}; + +static void dma_scsp(struct _SCSP *SCSP); /*SCSP DMA transfer function*/ +#define scsp_dgate scsp_regs[0x16/2] & 0x4000 +#define scsp_ddir scsp_regs[0x16/2] & 0x2000 +#define scsp_dexe scsp_regs[0x16/2] & 0x1000 +#define dma_transfer_end ((scsp_regs[0x24/2] & 0x10)>>4)|(((scsp_regs[0x26/2] & 0x10)>>4)<<1)|(((scsp_regs[0x28/2] & 0x10)>>4)<<2) + +static const float SDLT[8]={-1000000.0,-36.0,-30.0,-24.0,-18.0,-12.0,-6.0,0.0}; + +static unsigned char DecodeSCI(struct _SCSP *SCSP,unsigned char irq) +{ + unsigned char SCI=0; + unsigned char v; + v=(SCILV0((SCSP))&(1<<irq))?1:0; + SCI|=v; + v=(SCILV1((SCSP))&(1<<irq))?1:0; + SCI|=v<<1; + v=(SCILV2((SCSP))&(1<<irq))?1:0; + SCI|=v<<2; + return SCI; +} + +static void ResetInterrupts(struct _SCSP *SCSP) +{ + UINT32 reset = SCSP->udata.data[0x22/2]; + if (reset & 0x40) + SCSP->Int68kCB(SCSP->cpu, -SCSP->IrqTimA); + if (reset & 0x180) + SCSP->Int68kCB(SCSP->cpu, -SCSP->IrqTimBC); +} + +static void CheckPendingIRQ(struct _SCSP *SCSP) +{ + UINT32 pend=SCSP->udata.data[0x20/2]; + UINT32 en=SCSP->udata.data[0x1e/2]; + if(SCSP->MidiW!=SCSP->MidiR) + { + SCSP->Int68kCB(SCSP->cpu, SCSP->IrqMidi); + return; + } + if(!pend) + return; + if(pend&0x40) + if(en&0x40) + { + SCSP->Int68kCB(SCSP->cpu, SCSP->IrqTimA); + return; + } + if(pend&0x80) + if(en&0x80) + { + SCSP->Int68kCB(SCSP->cpu, SCSP->IrqTimBC); + return; + } + if(pend&0x100) + if(en&0x100) + { + SCSP->Int68kCB(SCSP->cpu, SCSP->IrqTimBC); + return; + } + + SCSP->Int68kCB(SCSP->cpu, 0); +} + +static int Get_AR(struct _SCSP *SCSP,int base,int R) +{ + int Rate=base+(R<<1); + if(Rate>63) Rate=63; + if(Rate<0) Rate=0; + return SCSP->ARTABLE[Rate]; +} + +static int Get_DR(struct _SCSP *SCSP,int base,int R) +{ + int Rate=base+(R<<1); + if(Rate>63) Rate=63; + if(Rate<0) Rate=0; + return SCSP->DRTABLE[Rate]; +} + +static int Get_RR(struct _SCSP *SCSP,int base,int R) +{ + int Rate=base+(R<<1); + if(Rate>63) Rate=63; + if(Rate<0) Rate=0; + return SCSP->DRTABLE[Rate]; +} + +static void Compute_EG(struct _SCSP *SCSP,struct _SLOT *slot) +{ + int octave=OCT(slot); + int rate; + if(octave&8) octave=octave-16; + if(KRS(slot)!=0xf) + rate=octave+2*KRS(slot)+((FNS(slot)>>9)&1); + else + rate=0; //rate=((FNS(slot)>>9)&1); + + slot->EG.volume=0x17F<<EG_SHIFT; + slot->EG.AR=Get_AR(SCSP,rate,AR(slot)); + slot->EG.D1R=Get_DR(SCSP,rate,D1R(slot)); + slot->EG.D2R=Get_DR(SCSP,rate,D2R(slot)); + slot->EG.RR=Get_RR(SCSP,rate,RR(slot)); + slot->EG.DL=0x1f-DL(slot); + slot->EG.EGHOLD=EGHOLD(slot); +} + +static void SCSP_StopSlot(struct _SLOT *slot,int keyoff); + +static int EG_Update(struct _SLOT *slot) +{ + switch(slot->EG.state) + { + case ATTACK: + slot->EG.volume+=slot->EG.AR; + if(slot->EG.volume>=(0x3ff<<EG_SHIFT)) + { + if (!LPSLNK(slot)) + { + slot->EG.state=DECAY1; + if(slot->EG.D1R>=(1024<<EG_SHIFT)) //Skip DECAY1, go directly to DECAY2 + slot->EG.state=DECAY2; + } + slot->EG.volume=0x3ff<<EG_SHIFT; + } + if(slot->EG.EGHOLD) + return 0x3ff<<(SHIFT-10); + break; + case DECAY1: + slot->EG.volume-=slot->EG.D1R; + if(slot->EG.volume<=0) + slot->EG.volume=0; + if(slot->EG.volume>>(EG_SHIFT+5)<=slot->EG.DL) + slot->EG.state=DECAY2; + break; + case DECAY2: + if(D2R(slot)==0) + return (slot->EG.volume>>EG_SHIFT)<<(SHIFT-10); + slot->EG.volume-=slot->EG.D2R; + if(slot->EG.volume<=0) + slot->EG.volume=0; + + break; + case RELEASE: + slot->EG.volume-=slot->EG.RR; + if(slot->EG.volume<=0) + { + slot->EG.volume=0; + SCSP_StopSlot(slot,0); + //slot->EG.volume=0x17F<<EG_SHIFT; + //slot->EG.state=ATTACK; + } + break; + default: + return 1<<SHIFT; + } + return (slot->EG.volume>>EG_SHIFT)<<(SHIFT-10); +} + +static UINT32 SCSP_Step(struct _SLOT *slot) +{ + int octave=OCT(slot); + UINT64 Fn; + + Fn=(FNS_Table[FNS(slot)]); //24.8 + if(octave&8) + Fn>>=(16-octave); + else + Fn<<=octave; + + return Fn/(44100); +} + + +static void Compute_LFO(struct _SLOT *slot) +{ + if(PLFOS(slot)!=0) + LFO_ComputeStep(&(slot->PLFO),LFOF(slot),PLFOWS(slot),PLFOS(slot),0); + if(ALFOS(slot)!=0) + LFO_ComputeStep(&(slot->ALFO),LFOF(slot),ALFOWS(slot),ALFOS(slot),1); +} + +static void SCSP_StartSlot(struct _SCSP *SCSP, struct _SLOT *slot) +{ + UINT32 start_offset; + slot->active=1; + slot->Backwards=0; + slot->cur_addr=0; slot->nxt_addr=1<<SHIFT; + start_offset = PCM8B(slot) ? SA(slot) : SA(slot) & 0x7FFFE; + slot->base=SCSP->SCSPRAM + start_offset; + slot->step=SCSP_Step(slot); + Compute_EG(SCSP,slot); + slot->EG.state=ATTACK; + slot->EG.volume=0x17F<<EG_SHIFT; + slot->Prev=0; + Compute_LFO(slot); + +// printf("StartSlot: SA %x PCM8B %x LPCTL %x ALFOS %x STWINH %x TL %x EFSDL %x\n", SA(slot), PCM8B(slot), LPCTL(slot), ALFOS(slot), STWINH(slot), TL(slot), EFSDL(slot)); +// printf(" AR %x D1R %x D2R %x RR %x DL %x KRS %x EGHOLD %x LPSLNK %x\n", AR(slot), D1R(slot), D2R(slot), RR(slot), DL(slot), KRS(slot), EGHOLD(slot), LPSLNK(slot)); +} + +static void SCSP_StopSlot(struct _SLOT *slot,int keyoff) +{ + if(keyoff /*&& slot->EG.state!=RELEASE*/) + { + slot->EG.state=RELEASE; + } + else + { + slot->active=0; + } + slot->udata.data[0]&=~0x800; +} + +#define log_base_2(n) (log((float) n)/log((float) 2)) + +static void SCSP_Init(struct _SCSP *SCSP, const struct SCSPinterface *intf) +{ + int i=0; + + SCSP->IrqTimA = SCSP->IrqTimBC = SCSP->IrqMidi = 0; + SCSP->MidiR=SCSP->MidiW=0; + SCSP->MidiOutR=SCSP->MidiOutW=0; + + // get SCSP RAM + { + memset(SCSP,0,sizeof(*SCSP)); + SCSP->cpu = intf->cpu; + + if (!i) + { + SCSP->Master=1; + } + else + { + SCSP->Master=0; + } + + if (intf->region) + { + SCSP->SCSPRAM = (unsigned char *)intf->region[0]; + SCSP->SCSPRAM_LENGTH = 512*1024; + SCSP->DSP.SCSPRAM = (UINT16 *)SCSP->SCSPRAM; + SCSP->DSP.SCSPRAM_LENGTH = (512*1024)/2; +// SCSP->SCSPRAM += intf->roffset; + } + } + + for(i=0;i<0x400;++i) + { + float fcent=(double) 1200.0*log_base_2((double)(((double) 1024.0+(double)i)/(double)1024.0)); + fcent=(double) 44100.0*pow(2.0,fcent/1200.0); + FNS_Table[i]=(float) (1<<SHIFT) *fcent; + } + + for(i=0;i<0x400;++i) + { + float envDB=((float)(3*(i-0x3ff)))/32.0; + float scale=(float)(1<<SHIFT); + EG_TABLE[i]=(INT32)(pow(10.0,envDB/20.0)*scale); + } + + for(i=0;i<0x10000;++i) + { + int iTL =(i>>0x0)&0xff; + int iPAN=(i>>0x8)&0x1f; + int iSDL=(i>>0xD)&0x07; + float TL=1.0; + float SegaDB=0; + float fSDL=1.0; + float PAN=1.0; + float LPAN,RPAN; + + if(iTL&0x01) SegaDB-=0.4; + if(iTL&0x02) SegaDB-=0.8; + if(iTL&0x04) SegaDB-=1.5; + if(iTL&0x08) SegaDB-=3; + if(iTL&0x10) SegaDB-=6; + if(iTL&0x20) SegaDB-=12; + if(iTL&0x40) SegaDB-=24; + if(iTL&0x80) SegaDB-=48; + + TL=pow(10.0,SegaDB/20.0); + + SegaDB=0; + if(iPAN&0x1) SegaDB-=3; + if(iPAN&0x2) SegaDB-=6; + if(iPAN&0x4) SegaDB-=12; + if(iPAN&0x8) SegaDB-=24; + + if((iPAN&0xf)==0xf) PAN=0.0; + else PAN=pow(10.0,SegaDB/20.0); + + if(iPAN<0x10) + { + LPAN=PAN; + RPAN=1.0; + } + else + { + RPAN=PAN; + LPAN=1.0; + } + + if(iSDL) + fSDL=pow(10.0,(SDLT[iSDL])/20.0); + else + fSDL=0.0; + + SCSP->LPANTABLE[i]=FIX((4.0*LPAN*TL*fSDL)); + SCSP->RPANTABLE[i]=FIX((4.0*RPAN*TL*fSDL)); + } + + SCSP->ARTABLE[0]=SCSP->DRTABLE[0]=0; //Infinite time + SCSP->ARTABLE[1]=SCSP->DRTABLE[1]=0; //Infinite time + for(i=2;i<64;++i) + { + double t,step,scale; + t=ARTimes[i]; //In ms + if(t!=0.0) + { + step=(1023*1000.0)/((float) 44100.0f*t); + scale=(double) (1<<EG_SHIFT); + SCSP->ARTABLE[i]=(int) (step*scale); + } + else + SCSP->ARTABLE[i]=1024<<EG_SHIFT; + + t=DRTimes[i]; //In ms + step=(1023*1000.0)/((float) 44100.0f*t); + scale=(double) (1<<EG_SHIFT); + SCSP->DRTABLE[i]=(int) (step*scale); + } + + // make sure all the slots are off + for(i=0;i<32;++i) + { + SCSP->Slots[i].slot=i; + SCSP->Slots[i].active=0; + SCSP->Slots[i].base=NULL; + } + + LFO_Init(); + SCSP->buffertmpl=(signed int*) malloc(44100*sizeof(signed int)); + SCSP->buffertmpr=(signed int*) malloc(44100*sizeof(signed int)); + memset(SCSP->buffertmpl,0,44100*sizeof(signed int)); + memset(SCSP->buffertmpr,0,44100*sizeof(signed int)); + + // no "pend" + SCSP[0].udata.data[0x20/2] = 0; + //SCSP[1].udata.data[0x20/2] = 0; + SCSP->TimCnt[0] = 0xffff; + SCSP->TimCnt[1] = 0xffff; + SCSP->TimCnt[2] = 0xffff; +} + +static void SCSP_UpdateSlotReg(struct _SCSP *SCSP,int s,int r) +{ + struct _SLOT *slot=SCSP->Slots+s; + int sl; + switch(r&0x3f) + { + case 0: + case 1: + if(KEYONEX(slot)) + { + for(sl=0;sl<32;++sl) + { + struct _SLOT *s2=SCSP->Slots+sl; + { + if(KEYONB(s2) && s2->EG.state==RELEASE/*&& !s2->active*/) + { + SCSP_StartSlot(SCSP, s2); + } + if(!KEYONB(s2) /*&& s2->active*/) + { + SCSP_StopSlot(s2,1); + } + } + } + slot->udata.data[0]&=~0x1000; + } + break; + case 0x10: + case 0x11: + slot->step=SCSP_Step(slot); + break; + case 0xA: + case 0xB: + slot->EG.RR=Get_RR(SCSP,0,RR(slot)); + slot->EG.DL=0x1f-DL(slot); + break; + case 0x12: + case 0x13: + Compute_LFO(slot); + break; + } +} + +static void SCSP_UpdateReg(struct _SCSP *SCSP, int reg) +{ + switch(reg&0x3f) + { + case 0x2: + case 0x3: + { + unsigned int v=RBL(SCSP); + SCSP->DSP.RBP=RBP(SCSP); + if(v==0) + SCSP->DSP.RBL=8*1024; + else if(v==1) + SCSP->DSP.RBL=16*1024; + if(v==2) + SCSP->DSP.RBL=32*1024; + if(v==3) + SCSP->DSP.RBL=64*1024; + } + break; + case 0x6: + case 0x7: + SCSP_MidiIn(SCSP, 0, SCSP->udata.data[0x6/2]&0xff, 0); + break; + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + break; + case 0x18: + case 0x19: + if(SCSP->Master) + { + SCSP->TimPris[0]=1<<((SCSP->udata.data[0x18/2]>>8)&0x7); + SCSP->TimCnt[0]=(SCSP->udata.data[0x18/2]&0xff)<<8; + } + break; + case 0x1a: + case 0x1b: + if(SCSP->Master) + { + SCSP->TimPris[1]=1<<((SCSP->udata.data[0x1A/2]>>8)&0x7); + SCSP->TimCnt[1]=(SCSP->udata.data[0x1A/2]&0xff)<<8; + } + break; + case 0x1C: + case 0x1D: + if(SCSP->Master) + { + SCSP->TimPris[2]=1<<((SCSP->udata.data[0x1C/2]>>8)&0x7); + SCSP->TimCnt[2]=(SCSP->udata.data[0x1C/2]&0xff)<<8; + } + break; + case 0x22: //SCIRE + case 0x23: + + if(SCSP->Master) + { + SCSP->udata.data[0x20/2]&=~SCSP->udata.data[0x22/2]; + ResetInterrupts(SCSP); + + // behavior from real hardware: if you SCIRE a timer that's expired, + // it'll immediately pop up again. ask Sakura Taisen on the Saturn... + if (SCSP->TimCnt[0] >= 0xff00) + { + SCSP->udata.data[0x20/2] |= 0x40; + } + if (SCSP->TimCnt[1] >= 0xff00) + { + SCSP->udata.data[0x20/2] |= 0x80; + } + if (SCSP->TimCnt[2] >= 0xff00) + { + SCSP->udata.data[0x20/2] |= 0x100; + } + } + break; + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + if(SCSP->Master) + { + SCSP->IrqTimA=DecodeSCI(SCSP,SCITMA); + SCSP->IrqTimBC=DecodeSCI(SCSP,SCITMB); + SCSP->IrqMidi=DecodeSCI(SCSP,SCIMID); + } + break; + } +} + +static void SCSP_UpdateSlotRegR(struct _SCSP *SCSP, int slot,int reg) +{ + +} + +static void SCSP_UpdateRegR(struct _SCSP *SCSP, int reg) +{ + switch(reg&0x3f) + { + case 4: + case 5: + { + unsigned short v=SCSP->udata.data[0x5/2]; + v&=0xff00; + v|=SCSP->MidiStack[SCSP->MidiR]; + SCSP->Int68kCB(SCSP->cpu, 0); // cancel the IRQ + if(SCSP->MidiR!=SCSP->MidiW) + { + ++SCSP->MidiR; + SCSP->MidiR&=15; + } + SCSP->udata.data[0x5/2]=v; + } + break; + case 8: + case 9: + { + unsigned char slot=SCSP->udata.data[0x8/2]>>11; + unsigned int CA=SCSP->Slots[slot&0x1f].cur_addr>>(SHIFT+12); + SCSP->udata.data[0x8/2]&=~(0x780); + SCSP->udata.data[0x8/2]|=CA<<7; + } + break; + } +} + +static void SCSP_w16(struct _SCSP *SCSP,unsigned int addr,unsigned short val) +{ + addr&=0xffff; + if(addr<0x400) + { + int slot=addr/0x20; + addr&=0x1f; + *((unsigned short *) (SCSP->Slots[slot].udata.datab+(addr))) = val; + SCSP_UpdateSlotReg(SCSP,slot,addr&0x1f); + } + else if(addr<0x600) + { + if (addr < 0x430) + { + *((unsigned short *) (SCSP->udata.datab+((addr&0x3f)))) = val; + SCSP_UpdateReg(SCSP, addr&0x3f); + } + } + else if(addr<0x700) + SCSP->RINGBUF[(addr-0x600)/2]=val; + else + { + //DSP + if(addr<0x780) //COEF + *((unsigned short *) (SCSP->DSP.COEF+(addr-0x700)/2))=val; + else if(addr<0x800) + *((unsigned short *) (SCSP->DSP.MADRS+(addr-0x780)/2))=val; + else if(addr<0xC00) + *((unsigned short *) (SCSP->DSP.MPRO+(addr-0x800)/2))=val; + + if(addr==0xBF0) + { +// printf("DSP start\n"); + SCSPDSP_Start(&SCSP->DSP); + } + } +} + +static unsigned short SCSP_r16(struct _SCSP *SCSP, unsigned int addr) +{ + unsigned short v=0; + addr&=0xffff; + if(addr<0x400) + { + int slot=addr/0x20; + addr&=0x1f; + SCSP_UpdateSlotRegR(SCSP, slot,addr&0x1f); + v=*((unsigned short *) (SCSP->Slots[slot].udata.datab+(addr))); + } + else if(addr<0x600) + { + if (addr < 0x430) + { + SCSP_UpdateRegR(SCSP, addr&0x3f); + v= *((unsigned short *) (SCSP->udata.datab+((addr&0x3f)))); + } + } + else if(addr<0x700) + v=SCSP->RINGBUF[(addr-0x600)/2]; + return v; +} + + +#define REVSIGN(v) ((~v)+1) + +void SCSP_TimersAddTicks(struct _SCSP *SCSP, int ticks) +{ + if(SCSP->TimCnt[0]<=0xff00) + { + SCSP->TimCnt[0] += ticks << (8-((SCSP->udata.data[0x18/2]>>8)&0x7)); + if (SCSP->TimCnt[0] > 0xFF00) + { + SCSP->TimCnt[0] = 0xFFFF; + SCSP->udata.data[0x20/2]|=0x40; + } + SCSP->udata.data[0x18/2]&=0xff00; + SCSP->udata.data[0x18/2]|=SCSP->TimCnt[0]>>8; + } + + if(SCSP->TimCnt[1]<=0xff00) + { + SCSP->TimCnt[1] += ticks << (8-((SCSP->udata.data[0x1a/2]>>8)&0x7)); + if (SCSP->TimCnt[1] > 0xFF00) + { + SCSP->TimCnt[1] = 0xFFFF; + SCSP->udata.data[0x20/2]|=0x80; + } + SCSP->udata.data[0x1a/2]&=0xff00; + SCSP->udata.data[0x1a/2]|=SCSP->TimCnt[1]>>8; + } + + if(SCSP->TimCnt[2]<=0xff00) + { + SCSP->TimCnt[2] += ticks << (8-((SCSP->udata.data[0x1c/2]>>8)&0x7)); + if (SCSP->TimCnt[2] > 0xFF00) + { + SCSP->TimCnt[2] = 0xFFFF; + SCSP->udata.data[0x20/2]|=0x100; + } + SCSP->udata.data[0x1c/2]&=0xff00; + SCSP->udata.data[0x1c/2]|=SCSP->TimCnt[2]>>8; + } +} + +INLINE INT32 SCSP_UpdateSlot(struct _SCSP *SCSP, struct _SLOT *slot) +{ + INT32 sample; + int step=slot->step; + UINT32 addr1,addr2,addr_select; // current and next sample addresses + UINT32 *addr[2] = {&addr1, &addr2}; // used for linear interpolation + UINT32 *slot_addr[2] = {&(slot->cur_addr), &(slot->nxt_addr)}; // + + if(SSCTL(slot)!=0) //no FM or noise yet + return 0; + + if(PLFOS(slot)!=0) + { + step=step*PLFO_Step(&(slot->PLFO)); + step>>=SHIFT; + } + + if(PCM8B(slot)) + { + addr1=slot->cur_addr>>SHIFT; + addr2=slot->nxt_addr>>SHIFT; + } + else + { + addr1=(slot->cur_addr>>(SHIFT-1))&0x7fffe; + addr2=(slot->nxt_addr>>(SHIFT-1))&0x7fffe; + } + + if(MDL(slot)!=0 || MDXSL(slot)!=0 || MDYSL(slot)!=0) + { + INT32 smp=(SCSP->RINGBUF[(SCSP->BUFPTR+MDXSL(slot))&63]+SCSP->RINGBUF[(SCSP->BUFPTR+MDYSL(slot))&63])/2; + + smp<<=0xA; // associate cycle with 1024 + smp>>=0x1A-MDL(slot); // ex. for MDL=0xF, sample range corresponds to +/- 64 pi (32=2^5 cycles) so shift by 11 (16-5 == 0x1A-0xF) + if(!PCM8B(slot)) smp<<=1; + + addr1+=smp; addr2+=smp; + } + + if(PCM8B(slot)) //8 bit signed + { + INT8 *p1=(signed char *) (SCSP->SCSPRAM+(((SA(slot)+addr1)^1)&0x7FFFF)); + INT8 *p2=(signed char *) (SCSP->SCSPRAM+(((SA(slot)+addr2)^1)&0x7FFFF)); + //sample=(p[0])<<8; + INT32 s; + INT32 fpart=slot->cur_addr&((1<<SHIFT)-1); + s=(int) (p1[0]<<8)*((1<<SHIFT)-fpart)+(int) (p2[0]<<8)*fpart; + sample=(s>>SHIFT); + } + else //16 bit signed (endianness?) + { + INT16 *p1=(signed short *) (SCSP->SCSPRAM+((SA(slot)+addr1)&0x7FFFE)); + INT16 *p2=(signed short *) (SCSP->SCSPRAM+((SA(slot)+addr2)&0x7FFFE)); + //sample=LE16(p[0]); + INT32 s; + INT32 fpart=slot->cur_addr&((1<<SHIFT)-1); + s=(int) LE16(p1[0])*((1<<SHIFT)-fpart)+(int) LE16(p2[0])*fpart; + sample=(s>>SHIFT); + } + + if(SBCTL(slot)&0x1) + sample ^= 0x7FFF; + if(SBCTL(slot)&0x2) + sample = (INT16)(sample^0x8000); + + if(slot->Backwards) + slot->cur_addr-=step; + else + slot->cur_addr+=step; + slot->nxt_addr=slot->cur_addr+(1<<SHIFT); + + addr1=slot->cur_addr>>SHIFT; + addr2=slot->nxt_addr>>SHIFT; + + if(addr1>=LSA(slot) && !(slot->Backwards)) + { + if(LPSLNK(slot) && slot->EG.state==ATTACK) + slot->EG.state = DECAY1; + } + + for (addr_select=0;addr_select<2;addr_select++) + { + INT32 rem_addr; + switch(LPCTL(slot)) + { + case 0: //no loop + if(*addr[addr_select]>=LSA(slot) && *addr[addr_select]>=LEA(slot)) + { + //slot->active=0; + SCSP_StopSlot(slot,0); + } + break; + case 1: //normal loop + if(*addr[addr_select]>=LEA(slot)) + { + rem_addr = *slot_addr[addr_select] - (LEA(slot)<<SHIFT); + *slot_addr[addr_select]=(LSA(slot)<<SHIFT) + rem_addr; + } + break; + case 2: //reverse loop + if((*addr[addr_select]>=LSA(slot)) && !(slot->Backwards)) + { + rem_addr = *slot_addr[addr_select] - (LSA(slot)<<SHIFT); + *slot_addr[addr_select]=(LEA(slot)<<SHIFT) - rem_addr; + slot->Backwards=1; + } + else if((*addr[addr_select]<LSA(slot) || (*slot_addr[addr_select]&0x80000000)) && slot->Backwards) + { + rem_addr = (LSA(slot)<<SHIFT) - *slot_addr[addr_select]; + *slot_addr[addr_select]=(LEA(slot)<<SHIFT) - rem_addr; + } + break; + case 3: //ping-pong + if(*addr[addr_select]>=LEA(slot)) //reached end, reverse till start + { + rem_addr = *slot_addr[addr_select] - (LEA(slot)<<SHIFT); + *slot_addr[addr_select]=(LEA(slot)<<SHIFT) - rem_addr; + slot->Backwards=1; + } + else if((*addr[addr_select]<LSA(slot) || (*slot_addr[addr_select]&0x80000000)) && slot->Backwards)//reached start or negative + { + rem_addr = (LSA(slot)<<SHIFT) - *slot_addr[addr_select]; + *slot_addr[addr_select]=(LSA(slot)<<SHIFT) + rem_addr; + slot->Backwards=0; + } + break; + } + } + + if(ALFOS(slot)!=0) + { + sample=sample*ALFO_Step(&(slot->ALFO)); + sample>>=SHIFT; + } + + if(slot->EG.state==ATTACK) + sample=(sample*EG_Update(slot))>>SHIFT; + else + sample=(sample*EG_TABLE[EG_Update(slot)>>(SHIFT-10)])>>SHIFT; + + if(!STWINH(slot)) + { + unsigned short Enc=((TL(slot))<<0x0)|(0x7<<0xd); + *SCSP->RBUFDST=(sample*SCSP->LPANTABLE[Enc])>>(SHIFT+1); + } + + return sample; +} + +static void SCSP_DoMasterSamples(struct _SCSP *SCSP, int nsamples) +{ + INT16 *bufr,*bufl; + int sl, s, i; + + bufr=SCSP->bufferr; + bufl=SCSP->bufferl; + + for(s=0;s<nsamples;++s) + { + INT32 smpl, smpr; + + smpl = smpr = 0; + + for(sl=0;sl<32;++sl) + { +#if FM_DELAY + SCSP->RBUFDST=SCSP->DELAYBUF+SCSP->DELAYPTR; +#else + SCSP->RBUFDST=SCSP->RINGBUF+SCSP->BUFPTR; +#endif + if(SCSP->Slots[sl].active) + { + struct _SLOT *slot=SCSP->Slots+sl; + unsigned short Enc; + signed int sample; + + sample=SCSP_UpdateSlot(SCSP, slot); + + Enc=((TL(slot))<<0x0)|((IMXL(slot))<<0xd); + SCSPDSP_SetSample(&SCSP->DSP,(sample*SCSP->LPANTABLE[Enc])>>(SHIFT-2),ISEL(slot),IMXL(slot)); + Enc=((TL(slot))<<0x0)|((DIPAN(slot))<<0x8)|((DISDL(slot))<<0xd); + { + smpl+=(sample*SCSP->LPANTABLE[Enc])>>SHIFT; + smpr+=(sample*SCSP->RPANTABLE[Enc])>>SHIFT; + } + } + +#if FM_DELAY + SCSP->RINGBUF[(SCSP->BUFPTR+64-(FM_DELAY-1))&63] = SCSP->DELAYBUF[(SCSP->DELAYPTR+FM_DELAY-(FM_DELAY-1))%FM_DELAY]; +#endif + ++SCSP->BUFPTR; + SCSP->BUFPTR&=63; +#if FM_DELAY + ++SCSP->DELAYPTR; + if(SCSP->DELAYPTR>FM_DELAY-1) SCSP->DELAYPTR=0; +#endif + } + + SCSPDSP_Step(&SCSP->DSP); + + for(i=0;i<16;++i) + { + struct _SLOT *slot=SCSP->Slots+i; + if(EFSDL(slot)) + { + unsigned short Enc=((EFPAN(slot))<<0x8)|((EFSDL(slot))<<0xd); + smpl+=(SCSP->DSP.EFREG[i]*SCSP->LPANTABLE[Enc])>>SHIFT; + smpr+=(SCSP->DSP.EFREG[i]*SCSP->RPANTABLE[Enc])>>SHIFT; + } + } + + *bufl++ = ICLIP16(smpl>>2); + *bufr++ = ICLIP16(smpr>>2); + + SCSP_TimersAddTicks(SCSP, 1); + CheckPendingIRQ(SCSP); + } + +} + +static void dma_scsp(struct _SCSP *SCSP) +{ + static UINT16 tmp_dma[3], *scsp_regs; + + scsp_regs = (UINT16 *)SCSP->udata.datab; + + printf("SCSP: DMA transfer START\n" + "DMEA: %04x DRGA: %04x DTLG: %04x\n" + "DGATE: %d DDIR: %d\n",SCSP->scsp_dmea,SCSP->scsp_drga,SCSP->scsp_dtlg,scsp_dgate ? 1 : 0,scsp_ddir ? 1 : 0); + + /* Copy the dma values in a temp storage for resuming later * + * (DMA *can't* overwrite his parameters). */ + if(!(scsp_ddir)) + { + tmp_dma[0] = scsp_regs[0x12/2]; + tmp_dma[1] = scsp_regs[0x14/2]; + tmp_dma[2] = scsp_regs[0x16/2]; + } + + if(scsp_ddir) + { + for(;SCSP->scsp_dtlg > 0;SCSP->scsp_dtlg-=2) + { +// program_write_word(SCSP->scsp_dmea, program_read_word(0x100000|SCSP->scsp_drga)); + SCSP->scsp_dmea+=2; + SCSP->scsp_drga+=2; + } + } + else + { + for(;SCSP->scsp_dtlg > 0;SCSP->scsp_dtlg-=2) + { +// program_write_word(0x100000|SCSP->scsp_drga,program_read_word(SCSP->scsp_dmea)); + SCSP->scsp_dmea+=2; + SCSP->scsp_drga+=2; + } + } + + /*Resume the values*/ + if(!(scsp_ddir)) + { + scsp_regs[0x12/2] = tmp_dma[0]; + scsp_regs[0x14/2] = tmp_dma[1]; + scsp_regs[0x16/2] = tmp_dma[2]; + } + + /*Job done,request a dma end irq*/ +// if(scsp_regs[0x1e/2] & 0x10) +// cpunum_set_input_line(2,dma_transfer_end,HOLD_LINE); +} + +int SCSP_IRQCB(void *param) +{ + CheckPendingIRQ(param); + return -1; +} + +void SCSP_Update(void *param, INT16 **inputs, INT16 **buf, int samples) +{ + struct _SCSP *SCSP = param; + SCSP->bufferl = buf[0]; + SCSP->bufferr = buf[1]; + SCSP->length = samples; + SCSP_DoMasterSamples(SCSP, samples); +} + +void *SCSP_Start(const void *config) +{ + const struct SCSPinterface *intf; + + struct _SCSP *SCSP; + + SCSP = malloc(sizeof(*SCSP)); + memset(SCSP, 0, sizeof(*SCSP)); + + intf = config; + + // init the emulation + SCSP_Init(SCSP, intf); + + // set up the IRQ callbacks + { + SCSP->Int68kCB = intf->irq_callback[0]; + +// SCSP->stream = stream_create(0, 2, 44100, SCSP, SCSP_Update); + } + + return SCSP; +} + +void SCSP_Exit (void *param) { + if (param) { + struct _SCSP *SCSP = param; + if (SCSP->buffertmpl) { + free (SCSP->buffertmpl); + } + if (SCSP->buffertmpr) { + free (SCSP->buffertmpr); + } + free (param); + } +} + + +void SCSP_set_ram_base(struct _SCSP *SCSP, int which, void *base) +{ + if (SCSP) + { + SCSP->SCSPRAM = base; + SCSP->DSP.SCSPRAM = base; + } +} + + +READ16_HANDLER( SCSP_0_r ) +{ + return SCSP_r16(param, offset*2); +} + +WRITE16_HANDLER( SCSP_0_w ) +{ + struct _SCSP *SCSP = param; + UINT16 tmp, *scsp_regs; + + tmp = SCSP_r16(SCSP, offset*2); + COMBINE_DATA(&tmp); + SCSP_w16(SCSP,offset*2, tmp); + + scsp_regs = (UINT16 *)SCSP->udata.datab; + + switch(offset*2) + { + // check DMA + case 0x412: + /*DMEA [15:1]*/ + /*Sound memory address*/ + SCSP->scsp_dmea = (((scsp_regs[0x14/2] & 0xf000)>>12)*0x10000) | (scsp_regs[0x12/2] & 0xfffe); + break; + case 0x414: + /*DMEA [19:16]*/ + SCSP->scsp_dmea = (((scsp_regs[0x14/2] & 0xf000)>>12)*0x10000) | (scsp_regs[0x12/2] & 0xfffe); + /*DRGA [11:1]*/ + /*Register memory address*/ + SCSP->scsp_drga = scsp_regs[0x14/2] & 0x0ffe; + break; + case 0x416: + /*DGATE[14]*/ + /*DDIR[13]*/ + /*if 0 sound_mem -> reg*/ + /*if 1 sound_mem <- reg*/ + /*DEXE[12]*/ + /*starting bit*/ + /*DTLG[11:1]*/ + /*size of transfer*/ + SCSP->scsp_dtlg = scsp_regs[0x16/2] & 0x0ffe; + if(scsp_dexe) + { + dma_scsp(SCSP); + scsp_regs[0x16/2]^=0x1000;//disable starting bit + } + break; + //check main cpu IRQ + case 0x42a: +#if 0 + extern UINT32* stv_scu; + + if(stv_scu && !(stv_scu[40] & 0x40) /*&& scsp_regs[0x42c/2] & 0x20*/)/*Main CPU allow sound irq*/ + { + cpunum_set_input_line_and_vector(0, 9, HOLD_LINE , 0x46); + logerror("SCSP: Main CPU interrupt\n"); + } +#endif + break; + case 0x42c: + break; + case 0x42e: + break; + } +} + +WRITE16_HANDLER( SCSP_MidiIn ) +{ + struct _SCSP *SCSP = param; + SCSP->MidiStack[SCSP->MidiW++]=data; + SCSP->MidiW &= 15; +} + +READ16_HANDLER( SCSP_MidiOutR ) +{ + struct _SCSP *SCSP = param; + unsigned char val; + + val=SCSP->MidiStack[SCSP->MidiR++]; + SCSP->MidiR&=7; + return val; +} + diff --git a/plugins/ao/eng_ssf/scsp.h b/plugins/ao/eng_ssf/scsp.h new file mode 100644 index 00000000..2f2a8e01 --- /dev/null +++ b/plugins/ao/eng_ssf/scsp.h @@ -0,0 +1,47 @@ +/* + + SCSP (YMF292-F) header +*/ + +#ifndef _SCSP_H_ +#define _SCSP_H_ + +#define MAX_SCSP (2) + +#define COMBINE_DATA(varptr) (*(varptr) = (*(varptr) & mem_mask) | (data & ~mem_mask)) + +// convert AO types +typedef int8 data8_t; +typedef int16 data16_t; +typedef int32 data32_t; +typedef int offs_t; +struct m68ki_cpu_core_s; + +struct SCSPinterface +{ + int num; + void *region[MAX_SCSP]; + int mixing_level[MAX_SCSP]; /* volume */
+ void (*irq_callback[MAX_SCSP])(struct m68ki_cpu_core_s *cpu, int state); /* irq callback */ + struct m68ki_cpu_core_s *cpu; +}; + +void *SCSP_Start(const void *config); +void SCSP_Exit (void *param); + +void SCSP_Update(void *param, INT16 **inputs, INT16 **buf, int samples); + +#define READ16_HANDLER(name) data16_t name(void *param, offs_t offset, data16_t mem_mask) +#define WRITE16_HANDLER(name) void name(void *param, offs_t offset, data16_t data, data16_t mem_mask) + +// SCSP register access +READ16_HANDLER( SCSP_0_r ); +WRITE16_HANDLER( SCSP_0_w ); +READ16_HANDLER( SCSP_1_r ); +WRITE16_HANDLER( SCSP_1_w ); + +// MIDI I/O access (used for comms on Model 2/3) +WRITE16_HANDLER( SCSP_MidiIn ); +READ16_HANDLER( SCSP_MidiOutR ); + +#endif diff --git a/plugins/ao/eng_ssf/scspdsp.c b/plugins/ao/eng_ssf/scspdsp.c new file mode 100644 index 00000000..8c08dd72 --- /dev/null +++ b/plugins/ao/eng_ssf/scspdsp.c @@ -0,0 +1,349 @@ +#include <assert.h> +#include <math.h> +#include "ao.h" +#include "cpuintrf.h" +#include "scsp.h" +#include "scspdsp.h" + +static UINT16 PACK(INT32 val) +{ + UINT32 temp; + int sign,exponent,k; + + sign = (val >> 23) & 0x1; + temp = (val ^ (val << 1)) & 0xFFFFFF; + exponent = 0; + for (k=0; k<12; k++) + { + if (temp & 0x800000) + break; + temp <<= 1; + exponent += 1; + } + if (exponent < 12) + val = (val << exponent) & 0x3FFFFF; + else + val <<= 11; + val >>= 11; + val |= sign << 15; + val |= exponent << 11; + + return (UINT16)val; +} + +static INT32 UNPACK(UINT16 val) +{ + int sign,exponent,mantissa; + INT32 uval; + + sign = (val >> 15) & 0x1; + exponent = (val >> 11) & 0xF; + mantissa = val & 0x7FF; + uval = mantissa << 11; + if (exponent > 11) + exponent = 11; + else + uval |= (sign ^ 1) << 22; + uval |= sign << 23; + uval <<= 8; + uval >>= 8; + uval >>= exponent; + + return uval; +} + +void SCSPDSP_Init(struct _SCSPDSP *DSP) +{ + memset(DSP,0,sizeof(struct _SCSPDSP)); + DSP->RBL=0x8000; + DSP->Stopped=1; +} + +void SCSPDSP_Step(struct _SCSPDSP *DSP) +{ + INT32 ACC=0; //26 bit + INT32 SHIFTED=0; //24 bit + INT32 X=0; //24 bit + INT32 Y=0; //13 bit + INT32 B=0; //26 bit + INT32 INPUTS=0; //24 bit + INT32 MEMVAL=0; + INT32 FRC_REG=0; //13 bit + INT32 Y_REG=0; //24 bit + UINT32 ADDR=0; + UINT32 ADRS_REG=0; //13 bit + int step; + + if(DSP->Stopped) + return; + + memset(DSP->EFREG,0,2*16); +#if 0 + int dump=0; + FILE *f=NULL; + if(dump) + f=fopen("dsp.txt","wt"); +#endif + for(step=0;step</*128*/DSP->LastStep;++step) + { + UINT16 *IPtr=DSP->MPRO+step*4; + +// if(IPtr[0]==0 && IPtr[1]==0 && IPtr[2]==0 && IPtr[3]==0) +// break; + + UINT32 TRA=(IPtr[0]>>8)&0x7F; + UINT32 TWT=(IPtr[0]>>7)&0x01; + UINT32 TWA=(IPtr[0]>>0)&0x7F; + + UINT32 XSEL=(IPtr[1]>>15)&0x01; + UINT32 YSEL=(IPtr[1]>>13)&0x03; + UINT32 IRA=(IPtr[1]>>6)&0x3F; + UINT32 IWT=(IPtr[1]>>5)&0x01; + UINT32 IWA=(IPtr[1]>>0)&0x1F; + + UINT32 TABLE=(IPtr[2]>>15)&0x01; + UINT32 MWT=(IPtr[2]>>14)&0x01; + UINT32 MRD=(IPtr[2]>>13)&0x01; + UINT32 EWT=(IPtr[2]>>12)&0x01; + UINT32 EWA=(IPtr[2]>>8)&0x0F; + UINT32 ADRL=(IPtr[2]>>7)&0x01; + UINT32 FRCL=(IPtr[2]>>6)&0x01; + UINT32 SHIFT=(IPtr[2]>>4)&0x03; + UINT32 YRL=(IPtr[2]>>3)&0x01; + UINT32 NEGB=(IPtr[2]>>2)&0x01; + UINT32 ZERO=(IPtr[2]>>1)&0x01; + UINT32 BSEL=(IPtr[2]>>0)&0x01; + + UINT32 NOFL=(IPtr[3]>>15)&1; //???? + UINT32 COEF=(IPtr[3]>>9)&0x3f; + + UINT32 MASA=(IPtr[3]>>2)&0x1f; //??? + UINT32 ADREB=(IPtr[3]>>1)&0x1; + UINT32 NXADR=(IPtr[3]>>0)&0x1; + + INT64 v; + + //operations are done at 24 bit precision +#if 0 + if(MASA) + int a=1; + if(NOFL) + int a=1; + +// int dump=0; + + if(f) + { +#define DUMP(v) fprintf(f," " #v ": %04X",v); + + fprintf(f,"%d: ",step); + DUMP(ACC); + DUMP(SHIFTED); + DUMP(X); + DUMP(Y); + DUMP(B); + DUMP(INPUTS); + DUMP(MEMVAL); + DUMP(FRC_REG); + DUMP(Y_REG); + DUMP(ADDR); + DUMP(ADRS_REG); + fprintf(f,"\n"); + } +#endif + //INPUTS RW + assert(IRA<0x32); + if(IRA<=0x1f) + INPUTS=DSP->MEMS[IRA]; + else if(IRA<=0x2F) + INPUTS=DSP->MIXS[IRA-0x20]<<4; //MIXS is 20 bit + else if(IRA<=0x31) + INPUTS=0; + + INPUTS<<=8; + INPUTS>>=8; + //if(INPUTS&0x00800000) + // INPUTS|=0xFF000000; + + if(IWT) + { + DSP->MEMS[IWA]=MEMVAL; //MEMVAL was selected in previous MRD + if(IRA==IWA) + INPUTS=MEMVAL; + } + + //Operand sel + //B + if(!ZERO) + { + if(BSEL) + B=ACC; + else + { + B=DSP->TEMP[(TRA+DSP->DEC)&0x7F]; + B<<=8; + B>>=8; + //if(B&0x00800000) + // B|=0xFF000000; //Sign extend + } + if(NEGB) + B=0-B; + } + else + B=0; + + //X + if(XSEL) + X=INPUTS; + else + { + X=DSP->TEMP[(TRA+DSP->DEC)&0x7F]; + X<<=8; + X>>=8; + //if(X&0x00800000) + // X|=0xFF000000; + } + + //Y + if(YSEL==0) + Y=FRC_REG; + else if(YSEL==1) + Y=DSP->COEF[COEF]>>3; //COEF is 16 bits + else if(YSEL==2) + Y=(Y_REG>>11)&0x1FFF; + else if(YSEL==3) + Y=(Y_REG>>4)&0x0FFF; + + if(YRL) + Y_REG=INPUTS; + + //Shifter + if(SHIFT==0) + { + SHIFTED=ACC; + if(SHIFTED>0x007FFFFF) + SHIFTED=0x007FFFFF; + if(SHIFTED<(-0x00800000)) + SHIFTED=-0x00800000; + } + else if(SHIFT==1) + { + SHIFTED=ACC*2; + if(SHIFTED>0x007FFFFF) + SHIFTED=0x007FFFFF; + if(SHIFTED<(-0x00800000)) + SHIFTED=-0x00800000; + } + else if(SHIFT==2) + { + SHIFTED=ACC*2; + SHIFTED<<=8; + SHIFTED>>=8; + //SHIFTED&=0x00FFFFFF; + //if(SHIFTED&0x00800000) + // SHIFTED|=0xFF000000; + } + else if(SHIFT==3) + { + SHIFTED=ACC; + SHIFTED<<=8; + SHIFTED>>=8; + //SHIFTED&=0x00FFFFFF; + //if(SHIFTED&0x00800000) + // SHIFTED|=0xFF000000; + } + + //ACCUM + Y<<=19; + Y>>=19; + //if(Y&0x1000) + // Y|=0xFFFFF000; + + v=(((INT64) X*(INT64) Y)>>12); + ACC=(int) v+B; + + if(TWT) + DSP->TEMP[(TWA+DSP->DEC)&0x7F]=SHIFTED; + + if(FRCL) + { + if(SHIFT==3) + FRC_REG=SHIFTED&0x0FFF; + else + FRC_REG=(SHIFTED>>11)&0x1FFF; + } + + if(MRD || MWT) + //if(0) + { + ADDR=DSP->MADRS[MASA]; + if(!TABLE) + ADDR+=DSP->DEC; + if(ADREB) + ADDR+=ADRS_REG&0x0FFF; + if(NXADR) + ADDR++; + if(!TABLE) + ADDR&=DSP->RBL-1; + else + ADDR&=0xFFFF; + //ADDR<<=1; + //ADDR+=DSP->RBP<<13; + //MEMVAL=DSP->SCSPRAM[ADDR>>1]; + ADDR+=DSP->RBP<<12; + if(MRD && (step&1)) //memory only allowed on odd? DoA inserts NOPs on even + { + if(NOFL) + MEMVAL=DSP->SCSPRAM[ADDR]<<8; + else + MEMVAL=UNPACK(DSP->SCSPRAM[ADDR]); + } + if(MWT && (step&1)) + { + if(NOFL) + DSP->SCSPRAM[ADDR]=SHIFTED>>8; + else + DSP->SCSPRAM[ADDR]=PACK(SHIFTED); + } + } + + if(ADRL) + { + if(SHIFT==3) + ADRS_REG=(SHIFTED>>12)&0xFFF; + else + ADRS_REG=(INPUTS>>16); + } + + if(EWT) + DSP->EFREG[EWA]+=SHIFTED>>8; + + } + --DSP->DEC; + memset(DSP->MIXS,0,4*16); +// if(f) +// fclose(f); +} + +void SCSPDSP_SetSample(struct _SCSPDSP *DSP,INT32 sample,int SEL,int MXL) +{ + //DSP->MIXS[SEL]+=sample<<(MXL+1)/*7*/; + DSP->MIXS[SEL]+=sample; +// if(MXL) +// int a=1; +} + +void SCSPDSP_Start(struct _SCSPDSP *DSP) +{ + int i; + DSP->Stopped=0; + for(i=127;i>=0;--i) + { + UINT16 *IPtr=DSP->MPRO+i*4; + + if(IPtr[0]!=0 || IPtr[1]!=0 || IPtr[2]!=0 || IPtr[3]!=0) + break; + } + DSP->LastStep=i+1; + +} diff --git a/plugins/ao/eng_ssf/scspdsp.h b/plugins/ao/eng_ssf/scspdsp.h new file mode 100644 index 00000000..481f93af --- /dev/null +++ b/plugins/ao/eng_ssf/scspdsp.h @@ -0,0 +1,37 @@ +#ifndef SCSPDSP_H +#define SCSPDSP_H + +//the DSP Context +struct _SCSPDSP +{ +//Config + UINT16 *SCSPRAM; + UINT32 SCSPRAM_LENGTH; + UINT32 RBP; //Ring buf pointer + UINT32 RBL; //Delay ram (Ring buffer) size in words + +//context + + INT16 COEF[64]; //16 bit signed + UINT16 MADRS[32]; //offsets (in words), 16 bit + UINT16 MPRO[128*4]; //128 steps 64 bit + INT32 TEMP[128]; //TEMP regs,24 bit signed + INT32 MEMS[32]; //MEMS regs,24 bit signed + UINT32 DEC; + +//input + INT32 MIXS[16]; //MIXS, 24 bit signed + INT16 EXTS[2]; //External inputs (CDDA) 16 bit signed + +//output + INT16 EFREG[16]; //EFREG, 16 bit signed + + int Stopped; + int LastStep; +}; + +void SCSPDSP_Init(struct _SCSPDSP *DSP); +void SCSPDSP_SetSample(struct _SCSPDSP *DSP, INT32 sample, INT32 SEL, INT32 MXL); +void SCSPDSP_Step(struct _SCSPDSP *DSP); +void SCSPDSP_Start(struct _SCSPDSP *DSP); +#endif diff --git a/plugins/ao/eng_ssf/scsplfo.c b/plugins/ao/eng_ssf/scsplfo.c new file mode 100644 index 00000000..c25e3c8d --- /dev/null +++ b/plugins/ao/eng_ssf/scsplfo.c @@ -0,0 +1,157 @@ +/* + SCSP LFO handling + + Part of the SCSP (YMF292-F) emulator package. + (not compiled directly, #included from scsp.c) + + By ElSemi + MAME/M1 conversion and cleanup by R. Belmont +*/ + +#define LFO_SHIFT 8 + +struct _LFO +{ + unsigned short phase; + UINT32 phase_step; + int *table; + int *scale; +}; + +#define LFIX(v) ((unsigned int) ((float) (1<<LFO_SHIFT)*(v))) + +//Convert DB to multiply amplitude +#define DB(v) LFIX(pow(10.0,v/20.0)) + +//Convert cents to step increment +#define CENTS(v) LFIX(pow(2.0,v/1200.0)) + +static int PLFO_TRI[256],PLFO_SQR[256],PLFO_SAW[256],PLFO_NOI[256]; +static int ALFO_TRI[256],ALFO_SQR[256],ALFO_SAW[256],ALFO_NOI[256]; +static float LFOFreq[32]={0.17,0.19,0.23,0.27,0.34,0.39,0.45,0.55,0.68,0.78,0.92,1.10,1.39,1.60,1.87,2.27, + 2.87,3.31,3.92,4.79,6.15,7.18,8.60,10.8,14.4,17.2,21.5,28.7,43.1,57.4,86.1,172.3}; +static float ASCALE[8]={0.0,0.4,0.8,1.5,3.0,6.0,12.0,24.0}; +static float PSCALE[8]={0.0,7.0,13.5,27.0,55.0,112.0,230.0,494}; +static int PSCALES[8][256]; +static int ASCALES[8][256]; + +void LFO_Init(void) +{ + int i,s; + for(i=0;i<256;++i) + { + int a,p; +// float TL; + //Saw + a=255-i; + if(i<128) + p=i; + else + p=i-256; + ALFO_SAW[i]=a; + PLFO_SAW[i]=p; + + //Square + if(i<128) + { + a=255; + p=127; + } + else + { + a=0; + p=-128; + } + ALFO_SQR[i]=a; + PLFO_SQR[i]=p; + + //Tri + if(i<128) + a=255-(i*2); + else + a=(i*2)-256; + if(i<64) + p=i*2; + else if(i<128) + p=255-i*2; + else if(i<192) + p=256-i*2; + else + p=i*2-511; + ALFO_TRI[i]=a; + PLFO_TRI[i]=p; + + //noise + //a=lfo_noise[i]; + a=rand()&0xff; + p=128-a; + ALFO_NOI[i]=a; + PLFO_NOI[i]=p; + } + + for(s=0;s<8;++s) + { + float limit=PSCALE[s]; + for(i=-128;i<128;++i) + { + PSCALES[s][i+128]=CENTS(((limit*(float) i)/128.0)); + } + limit=-ASCALE[s]; + for(i=0;i<256;++i) + { + ASCALES[s][i]=DB(((limit*(float) i)/256.0)); + } + } +} + +signed int INLINE PLFO_Step(struct _LFO *LFO) +{ + int p; + LFO->phase+=LFO->phase_step; +#if LFO_SHIFT!=8 + LFO->phase&=(1<<(LFO_SHIFT+8))-1; +#endif + p=LFO->table[LFO->phase>>LFO_SHIFT]; + p=LFO->scale[p+128]; + return p<<(SHIFT-LFO_SHIFT); +} + +signed int INLINE ALFO_Step(struct _LFO *LFO) +{ + int p; + LFO->phase+=LFO->phase_step; +#if LFO_SHIFT!=8 + LFO->phase&=(1<<(LFO_SHIFT+8))-1; +#endif + p=LFO->table[LFO->phase>>LFO_SHIFT]; + p=LFO->scale[p]; + return p<<(SHIFT-LFO_SHIFT); +} + +void LFO_ComputeStep(struct _LFO *LFO,UINT32 LFOF,UINT32 LFOWS,UINT32 LFOS,int ALFO) +{ + float step=(float) LFOFreq[LFOF]*256.0/(float)44100.0; + LFO->phase_step=(unsigned int) ((float) (1<<LFO_SHIFT)*step); + if(ALFO) + { + switch(LFOWS) + { + case 0: LFO->table=ALFO_SAW; break; + case 1: LFO->table=ALFO_SQR; break; + case 2: LFO->table=ALFO_TRI; break; + case 3: LFO->table=ALFO_NOI; break; + } + LFO->scale=ASCALES[LFOS]; + } + else + { + switch(LFOWS) + { + case 0: LFO->table=PLFO_SAW; break; + case 1: LFO->table=PLFO_SQR; break; + case 2: LFO->table=PLFO_TRI; break; + case 3: LFO->table=PLFO_NOI; break; + } + LFO->scale=PSCALES[LFOS]; + } +} diff --git a/plugins/ao/license.txt b/plugins/ao/license.txt new file mode 100644 index 00000000..b700befa --- /dev/null +++ b/plugins/ao/license.txt @@ -0,0 +1,236 @@ +Here is a list of the licenses each file in this package are under, and their text. + +The upshot is this: if you create anything from this SDK and include any MAME licensed components +(which are an integral part of each engine supplied) you must distribute the source code to your +derivative program. + + +===================================================================================== + +BSD license: + +Copyright (c) 2007-2009, R. Belmont and Richard Bannister. + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +===================================================================================== + +MAME license: + +Copyright (c) 1997-2008, Nicola Salmoria and the MAME team +All rights reserved. + +Redistribution and use of this code or any derivative works are permitted provided that the following conditions are met: + + * Redistributions may not be sold, nor may they be used in a commercial product or activity. + * Redistributions that are modified from the original source must include the complete source code, including the source code for all components used by a binary built from the modified sources. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. + * Redistributions must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +===================================================================================== + +GPL license: + +Too long to include here. + +See eng_psf/peops/License.txt or eng_psf/peops2/License.txt for the complete text. + +While legally combining GPL with BSD and MAME licensed software is unclear, Pete Bernert +will probably be OK with anything you do as long as you distribute the source for your +AOSDK based creations. + +===================================================================================== + +ZLIB license: + +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.2, October 3rd, 2004 + + Copyright (C) 1995-2004 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly jloup@gzip.org + Mark Adler madler@alumni.caltech.edu + +*/ + +===================================================================================== + +List of files and their licenses: + +ao.h BSD +corlett.c BSD +corlett.h BSD +cpuintrf.h BSD +dsnd.c BSD +eng_protos.h BSD +main.c BSD +Makefile BSD +mem.h BSD +osd_cpu.h MAME +oss.c BSD +oss.h BSD + +eng_dsf: + +aica.c MAME +aica.h MAME +aicadsp.c MAME +aicadsp.h MAME +aicalfo.c MAME +arm7.c MAME +arm7.h MAME +arm7i.c MAME +arm7i.h MAME +arm7memil.c MAME +eng_dsf.c BSD +dc_hw.c BSD +dc_hw.h BSD + +eng_qsf: + +eng_qsf.c BSD +kabuki.c MAME +qsound.c MAME +qsound.h MAME +z80.c MAME +z80dasm.c MAME +z80dasm.h MAME +z80.h MAME + +eng_ssf: + +eng_ssf.c BSD +m68kconf.h MAME +m68kcpu.c MAME +m68kcpu.h MAME +m68k.h MAME +m68k_in.c MAME +m68kmake.c MAME +m68kmame.h MAME +m68kopac.c MAME +m68kopdm.c MAME +m68kopnz.c MAME +m68kops.c MAME +m68kops.h MAME +sat_hw.c BSD +sat_hw.h BSD +scsp.c MAME +scspdsp.c MAME +scspdsp.h MAME +scsp.h MAME +scsplfo.c MAME + +eng_psf: + +eng_psf2.c BSD +eng_psf.c BSD +eng_spu.c BSD +psx_hw.c BSD +psx.c MAME +psx.h MAME +cpuintrf.h MAME +mamemem.h MAME + +eng_psf/peops: + +adsr.c GPL +adsr.h GPL +dma.c GPL +dma.h GPL +externals.h GPL +gauss_i.h GPL +registers.c GPL +registers.h GPL +regs.h GPL +reverb.c GPL +spu.c GPL +spu.h GPL +stdafx.h GPL + + +eng_psf/peops2: + +adsr.c GPL +adsr.h GPL +dma.c GPL +dma.h GPL +externals.h GPL +gauss_i.h GPL +psemuxa.h GPL +registers.c GPL +registers.h GPL +regs.h GPL +reverb.c GPL +reverb.h GPL +spu.c GPL +spu.h GPL +stdafx.h GPL +xa.c GPL + + + +zlib: + +adler32.c ZLIB +compress.c ZLIB +crc32.c ZLIB +crc32.h ZLIB +crypt.h ZLIB +deflate.c ZLIB +deflate.h ZLIB +gzio.c ZLIB +infback.c ZLIB +inffast.c ZLIB +inffast.h ZLIB +inffixed.h ZLIB +inflate.c ZLIB +inflate.h ZLIB +inftrees.c ZLIB +inftrees.h ZLIB +ioapi.c ZLIB +ioapi.h ZLIB +trees.c ZLIB +trees.h ZLIB +uncompr.c ZLIB +unzip.c ZLIB +unzip.h ZLIB +zconf.h ZLIB +zlib.h ZLIB +zutil.c ZLIB +zutil.h ZLIB + diff --git a/plugins/ao/main.c b/plugins/ao/main.c new file mode 100644 index 00000000..073347d8 --- /dev/null +++ b/plugins/ao/main.c @@ -0,0 +1,261 @@ +/* + Audio Overload SDK - main driver. for demonstration only, not user friendly! + + Copyright (c) 2007-2009 R. Belmont and Richard Bannister. + + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "ao.h" +#include "eng_protos.h" + +#define trace(...) { fprintf(stderr, __VA_ARGS__); } +//#define trace(fmt,...) + +/* file types */ +static uint32 type; + +static struct +{ + uint32 sig; + char *name; + void * (*start)(const char *path, uint8 *, uint32); // returns handle + int32 (*gen)(void *handle, int16 *, uint32); + int32 (*stop)(void *handle); + int32 (*command)(void *handle, int32, int32); + uint32 rate; + int32 (*fillinfo)(void *handle, ao_display_info *); +} types[] = { + { 0x50534641, "Capcom QSound (.qsf)", qsf_start, qsf_gen, qsf_stop, qsf_command, 60, qsf_fill_info }, + { 0x50534611, "Sega Saturn (.ssf)", ssf_start, ssf_gen, ssf_stop, ssf_command, 60, ssf_fill_info }, + { 0x50534601, "Sony PlayStation (.psf)", psf_start, psf_gen, psf_stop, psf_command, 60, psf_fill_info }, + { 0x53505500, "Sony PlayStation (.spu)", spu_start, spu_gen, spu_stop, spu_command, 60, spu_fill_info }, + { 0x50534602, "Sony PlayStation 2 (.psf2)", psf2_start, psf2_gen, psf2_stop, psf2_command, 60, psf2_fill_info }, + { 0x50534612, "Sega Dreamcast (.dsf)", dsf_start, dsf_gen, dsf_stop, dsf_command, 60, dsf_fill_info }, + + { 0xffffffff, "", NULL, NULL, NULL, NULL, 0, NULL } +}; + +/* ao_get_lib: called to load secondary files */ +int ao_get_lib(char *filename, uint8 **buffer, uint64 *length) +{ + uint8 *filebuf; + uint32 size; + FILE *auxfile; + + auxfile = fopen(filename, "rb"); + if (!auxfile) + { + printf("Unable to find auxiliary file %s\n", filename); + return AO_FAIL; + } + + fseek(auxfile, 0, SEEK_END); + size = ftell(auxfile); + fseek(auxfile, 0, SEEK_SET); + + filebuf = malloc(size); + + if (!filebuf) + { + fclose(auxfile); + printf("ERROR: could not allocate %d bytes of memory\n", size); + return AO_FAIL; + } + + fread(filebuf, size, 1, auxfile); + fclose(auxfile); + + *buffer = filebuf; + *length = (uint64)size; + + return AO_SUCCESS; +} + +#if 0 +static void do_frame(uint32 size, int16 *buffer) +{ + (*types[type].gen)(buffer, size); +} +#endif + +int main(int argv, char *argc[]) +{ + FILE *file; + uint8 *buffer; + uint32 size, filesig; + + printf("AOSDK test program v1.0 by R. Belmont [AOSDK release 1.4.8]\nCopyright (c) 2007-2009 R. Belmont and Richard Bannister - please read license.txt for license details\n\n"); + + // check if an argument was given + if (argv < 2) + { + printf("Error: must specify a filename!\n"); + return -1; + } + + file = fopen(argc[1], "rb"); + + if (!file) + { + printf("ERROR: could not open file %s\n", argc[1]); + return -1; + } + + // get the length of the file by seeking to the end then reading the current position + fseek(file, 0, SEEK_END); + size = ftell(file); + // reset the pointer + fseek(file, 0, SEEK_SET); + + buffer = malloc(size); + + if (!buffer) + { + fclose(file); + printf("ERROR: could not allocate %d bytes of memory\n", size); + return -1; + } + + // read the file + fread(buffer, size, 1, file); + fclose(file); + + // now try to identify the file + type = 0; + filesig = buffer[0]<<24 | buffer[1]<<16 | buffer[2]<<8 | buffer[3]; + while (types[type].sig != 0xffffffff) + { + if (filesig == types[type].sig) + { + break; + } + else + { + type++; + } + } + + // now did we identify it above or just fall through? + if (types[type].sig != 0xffffffff) + { + printf("File identified as %s\n", types[type].name); + } + else + { + printf("ERROR: File is unknown, signature bytes are %02x %02x %02x %02x\n", buffer[0], buffer[1], buffer[2], buffer[3]); + free(buffer); + return -1; + } + + void *handle = (*types[type].start)(argc[1], buffer, size); + + if (!handle) + { + free(buffer); + printf("ERROR: Engine rejected file!\n"); + return -1; + } + +#if 0 + m1sdr_Init(44100); + m1sdr_SetCallback(do_frame); + m1sdr_PlayStart(); + + printf("\n\nPlaying. Press CTRL-C to stop.\n"); + + while (1) + { + m1sdr_TimeCheck(); + } +#endif + free(buffer); + + return 1; +} + +// stub for MAME stuff +int change_pc(int foo) +{ + return 0; +} + +int +ao_identify (char *buffer) { + uint32 filesig; + uint32 type = 0; + + filesig = buffer[0]<<24 | buffer[1]<<16 | buffer[2]<<8 | buffer[3]; + while (types[type].sig != 0xffffffff) + { + if (filesig == types[type].sig) + { + break; + } + else + { + type++; + } + } + + // now did we identify it above or just fall through? + if (types[type].sig != 0xffffffff) + { + trace ("psf: File identified as %s\n", types[type].name); + } + else + { + trace ("psf: File is unknown, signature bytes are %02x %02x %02x %02x\n", buffer[0], buffer[1], buffer[2], buffer[3]); + return -1; + } + return type; +} + +void * +ao_start (uint32 type, const char *path, uint8 *buffer, uint32 size) { + printf ("ao_start %d %p %d\n", type, buffer, size); + return (*types[type].start)(path, buffer, size); +} + +int +ao_stop (uint32 type, void *handle) { + return (*types[type].stop)(handle); +} + +int +ao_get_info (uint32 type, void *handle, ao_display_info *info) { + return (*types[type].fillinfo)(handle, info); +} + +int +ao_decode (uint32 type, void *handle, int16 *buffer, uint32 size) { + (*types[type].gen)(handle, buffer, size); + return size; +} + +int +ao_command (uint32 type, void *handle, int32 command, int32 param) { + return (*types[type].command)(handle, command, param); +} diff --git a/plugins/ao/mem.h b/plugins/ao/mem.h new file mode 100644 index 00000000..ba40f331 --- /dev/null +++ b/plugins/ao/mem.h @@ -0,0 +1,23 @@ +// +// Audio Overload +// Emulated music player +// +// (C) 2000-2008 Richard F. Bannister +// + +// mem.h + +// defined in eng_qsf.c +uint8 memory_read(void *userdata, uint16 addr); +uint8 memory_readop(void *userdata, uint16 addr); +uint8 memory_readport(void *userdata, uint16 addr); +void memory_write(void *userdata, uint16 addr, uint8 byte); +void memory_writeport(void *userdata, uint16 addr, uint8 byte); + +uint8 dc_read8(uint32 addr); +uint16 dc_read16(uint32 addr); +uint32 dc_read32(uint32 addr); +void dc_write8(uint32 addr, uint8 byte); +void dc_write16(uint32 addr, uint16 word); +void dc_write32(uint32 addr, uint32 dword); + diff --git a/plugins/ao/osd_cpu.h b/plugins/ao/osd_cpu.h new file mode 100644 index 00000000..da74a0d4 --- /dev/null +++ b/plugins/ao/osd_cpu.h @@ -0,0 +1,70 @@ +/******************************************************************************* +* * +* Define size independent data types and operations. * +* * +* The following types must be supported by all platforms: * +* * +* UINT8 - Unsigned 8-bit Integer INT8 - Signed 8-bit integer * +* UINT16 - Unsigned 16-bit Integer INT16 - Signed 16-bit integer * +* UINT32 - Unsigned 32-bit Integer INT32 - Signed 32-bit integer * +* UINT64 - Unsigned 64-bit Integer INT64 - Signed 64-bit integer * +* * +* * +* The macro names for the artithmatic operations are composed as follows: * +* * +* XXX_R_A_B, where XXX - 3 letter operation code (ADD, SUB, etc.) * +* R - The type of the result * +* A - The type of operand 1 * +* B - The type of operand 2 (if binary operation) * +* * +* Each type is one of: U8,8,U16,16,U32,32,U64,64 * +* * +*******************************************************************************/ + + +#ifndef OSD_CPU_H +#define OSD_CPU_H + +#include "ao.h" + +/* Combine two 32-bit integers into a 64-bit integer */ +#define COMBINE_64_32_32(A,B) ((((UINT64)(A))<<32) | (UINT32)(B)) +#define COMBINE_U64_U32_U32(A,B) COMBINE_64_32_32(A,B) + +/* Return upper 32 bits of a 64-bit integer */ +#define HI32_32_64(A) (((UINT64)(A)) >> 32) +#define HI32_U32_U64(A) HI32_32_64(A) + +/* Return lower 32 bits of a 64-bit integer */ +#define LO32_32_64(A) ((A) & 0xffffffff) +#define LO32_U32_U64(A) LO32_32_64(A) + +#define DIV_64_64_32(A,B) ((A)/(B)) +#define DIV_U64_U64_U32(A,B) ((A)/(UINT32)(B)) + +#define MOD_32_64_32(A,B) ((A)%(B)) +#define MOD_U32_U64_U32(A,B) ((A)%(UINT32)(B)) + +#define MUL_64_32_32(A,B) ((A)*(INT64)(B)) +#define MUL_U64_U32_U32(A,B) ((A)*(UINT64)(UINT32)(B)) + + +/****************************************************************************** + * Union of UINT8, UINT16 and UINT32 in native endianess of the target + * This is used to access bytes and words in a machine independent manner. + * The upper bytes h2 and h3 normally contain zero (16 bit CPU cores) + * thus PAIR.d can be used to pass arguments to the memory system + * which expects 'int' really. + ******************************************************************************/ +typedef union { +#if LSB_FIRST + struct { UINT8 l,h,h2,h3; } b; + struct { UINT16 l,h; } w; +#else + struct { UINT8 h3,h2,h,l; } b; + struct { UINT16 h,l; } w; +#endif + UINT32 d; +} PAIR; + +#endif /* defined OSD_CPU_H */ diff --git a/plugins/ao/plugin.c b/plugins/ao/plugin.c new file mode 100644 index 00000000..5f6a12bf --- /dev/null +++ b/plugins/ao/plugin.c @@ -0,0 +1,338 @@ +/* + DeaDBeeF - ultimate music player for GNU/Linux systems with X11 + Copyright (C) 2009-2010 Alexey Yakovenko <waker@users.sourceforge.net> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#include <stdlib.h> +#include <string.h> +#include "../../deadbeef.h" +#include "ao.h" +#include "eng_protos.h" + +#define min(x,y) ((x)<(y)?(x):(y)) +#define max(x,y) ((x)>(y)?(x):(y)) + +#define trace(...) { fprintf(stderr, __VA_ARGS__); } +//#define trace(fmt,...) + +DB_functions_t *deadbeef; +static DB_decoder_t plugin; + +static const char * exts[] = { "psf", "psf2", "spu", "ssf", "minidsf", "qsf", "dsf", "miniqsf", NULL }; +static const char *filetypes[] = { "PSF", "PSF2", "SPU", "SSF", "QSF", "DSF", NULL }; + +typedef struct { + DB_fileinfo_t info; + int currentsample; + uint32 type; + void *decoder; + char *filebuffer; + size_t filesize; + char buffer[735*4]; // psf2 decoder only works with 735 samples buffer + int remaining; + int skipsamples; + float duration; +} aoplug_info_t; + +static DB_fileinfo_t * +aoplug_open (void) { + DB_fileinfo_t *_info = malloc (sizeof (aoplug_info_t)); + aoplug_info_t *info = (aoplug_info_t *)_info; + memset (info, 0, sizeof (aoplug_info_t)); + return _info; +} + +static int +aoplug_init (DB_fileinfo_t *_info, DB_playItem_t *it) { + aoplug_info_t *info = (aoplug_info_t *)_info; + + _info->bps = 16; + _info->channels = 2; + _info->samplerate = 44100; + _info->readpos = 0; + _info->plugin = &plugin; + info->duration = deadbeef->pl_get_item_duration (it); + + DB_FILE *file = deadbeef->fopen (it->fname); + if (!file) { + trace ("psf: failed to fopen %s\n", it->fname); + return -1; + } + + info->filesize = deadbeef->fgetlength (file); + info->filebuffer = malloc (info->filesize); + if (!info->filebuffer) { + fprintf(stderr, "psf: could not allocate %d bytes of memory\n", (int)info->filesize); + deadbeef->fclose (file); + return -1; + } + + if (deadbeef->fread(info->filebuffer, 1, info->filesize, file) != info->filesize) { + fprintf(stderr, "psf: file read error: %s\n", it->fname); + deadbeef->fclose (file); + return -1; + } + deadbeef->fclose (file); + + info->type = ao_identify (info->filebuffer); + if (info->type < 0) { + fprintf (stderr, "psf: ao_identify failed\n"); + return -1; + } + + info->decoder = ao_start (info->type, it->fname, (uint8 *)info->filebuffer, info->filesize); + if (!info->decoder) { + fprintf (stderr, "psf: ao_start failed\n"); + return -1; + } + + return 0; +} + +static void +aoplug_free (DB_fileinfo_t *_info) { + aoplug_info_t *info = (aoplug_info_t *)_info; + if (info) { + if (info->filebuffer) { + ao_stop (info->type, info->decoder); + free (info->filebuffer); + info->filebuffer = NULL; + } + free (info); + } +} + +static int +aoplug_read_int16 (DB_fileinfo_t *_info, char *bytes, int size) { + aoplug_info_t *info = (aoplug_info_t *)_info; +// printf ("aoplug_read_int16 %d samples, curr %d, end %d\n", size/4, info->currentsample, (int)(info->duration * _info->samplerate)); + + if (info->currentsample >= info->duration * _info->samplerate) { + return 0; + } + + int initsize = size; + + while (size > 0) { + if (info->remaining > 0) { + if (info->skipsamples > 0) { + int n = min (info->skipsamples, info->remaining); + if (info->remaining > n) { + memmove (info->buffer, info->buffer+n*4, (info->remaining - n)*4); + } + info->remaining -= n; + info->skipsamples -= n; + continue; + } + int n = size / 4; + n = min (info->remaining, n); + memcpy (bytes, info->buffer, n * 4); + if (info->remaining > n) { + memmove (info->buffer, info->buffer+n*4, (info->remaining - n)*4); + } + info->remaining -= n; + bytes += n*4; + size -= n*4; + } + if (!info->remaining) { + ao_decode (info->type, info->decoder, (int16_t *)info->buffer, 735); + info->remaining = 735; + } + } + info->currentsample += (initsize-size) / (_info->channels * _info->bps/8); + return initsize-size; +} + +static int +aoplug_seek_sample (DB_fileinfo_t *_info, int sample) { + aoplug_info_t *info = (aoplug_info_t *)_info; + if (sample > info->currentsample) { + info->skipsamples = sample-info->currentsample; + } + else { + // restart song + ao_command (info->type, info->decoder, COMMAND_RESTART, 0); + info->skipsamples = sample; + } + info->currentsample = sample; + _info->readpos = (float)sample / _info->samplerate; + return 0; +} + +static int +aoplug_seek (DB_fileinfo_t *_info, float time) { + return aoplug_seek_sample (_info, time * _info->samplerate); +} + +static DB_playItem_t * +aoplug_insert (DB_playItem_t *after, const char *fname) { + DB_FILE *fp = deadbeef->fopen (fname); + if (!fp) { + trace ("psf: failed to fopen %s\n", fname); + return NULL; + } + + size_t size = deadbeef->fgetlength (fp); + char *buffer = malloc (size); + if (!buffer) { + deadbeef->fclose (fp); + fprintf(stderr, "psf: could not allocate %d bytes of memory\n", (int)size); + return NULL; + } + + if (deadbeef->fread(buffer, 1, size, fp) != size) { + deadbeef->fclose (fp); + fprintf(stderr, "psf: file read error: %s\n", fname); + return NULL; + } + + deadbeef->fclose (fp); + + int type = ao_identify (buffer); + if (type < 0) { + free (buffer); + return NULL; + } + + void *dec = ao_start (type, fname, (uint8*)buffer, size); + if (!dec) { + free (buffer); + return NULL; + } + ao_display_info info; + int have_info = 0; + if (ao_get_info (type, dec, &info) == AO_SUCCESS) { + have_info = 1; + } + + ao_stop (type, dec); + dec = NULL; + + free (buffer); + + DB_playItem_t *it = deadbeef->pl_item_alloc (); + it->decoder_id = deadbeef->plug_get_decoder_id (plugin.plugin.id); + it->fname = strdup (fname); + const char *ext = fname + strlen (fname); + while (*ext != '.' && ext > fname) { + ext--; + } + if (*ext == '.') { + ext++; + if (!strcasecmp (ext, "psf")) { + it->filetype = filetypes[0]; + } + else if (!strcasecmp (ext, "psf2")) { + it->filetype = filetypes[1]; + } + else if (!strcasecmp (ext, "spu")) { + it->filetype = filetypes[2]; + } + else if (!strcasecmp (ext, "ssf")) { + it->filetype = filetypes[3]; + } + else if (!strcasecmp (ext, "dsf") || !strcasecmp (ext, "minidsf")) { + it->filetype = filetypes[5]; + } + else if (!strcasecmp (ext, "qsf") || !strcasecmp (ext, "miniqsf")) { + it->filetype = filetypes[4]; + } + } + else { + it->filetype = filetypes[0]; + } + + float duration = 120; + + if (have_info) { + int i; + for (i = 1; i < 9; i++) { + if (!strncasecmp (info.title[i], "Length: ", 8)) { + int min, sec; + if (sscanf (info.info[i], "%d:%d", &min, &sec) == 2) { + duration = min * 60 + sec; + } + } + else if (!strncasecmp (info.title[i], "Name: ", 6) || !strncasecmp (info.title[i], "Song: ", 6)) { + deadbeef->pl_add_meta (it, "title", info.info[i]); + } + else if (!strncasecmp (info.title[i], "Game: ", 6)) { + deadbeef->pl_add_meta (it, "album", info.info[i]); + } + else if (!strncasecmp (info.title[i], "Artist: ", 8)) { + deadbeef->pl_add_meta (it, "artist", info.info[i]); + } + else if (!strncasecmp (info.title[i], "Copyright: ", 11)) { + deadbeef->pl_add_meta (it, "copyright", info.info[i]); + } + else if (!strncasecmp (info.title[i], "Year: ", 6)) { + deadbeef->pl_add_meta (it, "date", info.info[i]); + } + else if (!strncasecmp (info.title[i], "Year: ", 6)) { + deadbeef->pl_add_meta (it, "date", info.info[i]); + } + char s[1024]; + snprintf (s, sizeof (s), "%s%s", info.title[i], info.info[i]); + deadbeef->pl_append_meta (it, "comment", s); + } + } + deadbeef->pl_set_item_duration (it, duration); + deadbeef->pl_add_meta (it, "title", NULL); + after = deadbeef->pl_insert_item (after, it); + deadbeef->pl_item_unref (it); + return after; +} + +static int +aoplug_start (void) { + return 0; +} + +static int +aoplug_stop (void) { + return 0; +} + +static DB_decoder_t plugin = { + DB_PLUGIN_SET_API_VERSION + .plugin.version_major = 0, + .plugin.version_minor = 1, + .plugin.type = DB_PLUGIN_DECODER, + .plugin.id = "psf", + .plugin.name = "Audio Overload plugin", + .plugin.descr = "psf, psf2, spu, ssf, minidsf player based on Audio Overload library", + .plugin.author = "Alexey Yakovenko", + .plugin.email = "waker@users.sourceforge.net", + .plugin.website = "http://deadbeef.sf.net", + .plugin.start = aoplug_start, + .plugin.stop = aoplug_stop, + .open = aoplug_open, + .init = aoplug_init, + .free = aoplug_free, + .read_int16 = aoplug_read_int16, + .seek = aoplug_seek, + .seek_sample = aoplug_seek_sample, + .insert = aoplug_insert, + .exts = exts, + .filetypes = filetypes +}; + +DB_plugin_t * +ao_load (DB_functions_t *api) { + deadbeef = api; + return DB_PLUGIN (&plugin); +} + diff --git a/plugins/ao/readme.txt b/plugins/ao/readme.txt new file mode 100644 index 00000000..26fcbcb1 --- /dev/null +++ b/plugins/ao/readme.txt @@ -0,0 +1,81 @@ +Audio Overload SDK - Development Release 1.4.8 February 15, 2009 + +Copyright (c) 2007-2009 R. Belmont and Richard Bannister. +All rights reserved. +========================================================= + +Please refer to license.txt for the specific licensing details of this software. + +This SDK opens up some of the music file format engines developed for the Audio Overload project. +You may use this code to play the formats on systems we don't support or inside of applications +other than AO. + +Configurables in the makefile: + +- Uncomment the line that defines LONG_IS_64BIT for compilation on 64-bit Linux, *BSD, and other operating +systems using the AMD64 recommended ABI (not 64-bit Windows). + +- Change LSB_FIRST=1 to =0 for big-endian platforms. + +New in Release 1.4.8 +- Guard against invalid data sometimes created by makessf.py (fixes crashing Pebble Beach ST-V rips) + + +Entry points of an AO engine are as follows: + +int32 XXX_start(uint8 *, uint32) + +This function attempts to recognize and load a file of a specific type. It is assumed external code has +already checked the file's signature in cases where that's possible. The first parameter is a pointer to +the entire file in memory, and the second is the length of the file. The return value is AO_SUCCESS if +the engine properly loaded the file and AO_FAIL if it didn't. + + +int32 XXX_gen(int16 *, uint32) + +This function actually plays the song and generates signed 16-bit stereo samples at 44100 Hz. The first +parameter is a pointer to a buffer in which to place the samples (stereo interleaved), and the second is +the number of stereo samples to generate (so the output buffer size must be (number of samples) * 2 * 2 +bytes in length). + + +int32 XXX_stop(void) + +This function ceases playback and cleans up the engine. You must call _start again after this to play more +music. + + +int32 XXX_command(int32, int32) + +For some engines, this allows you to send commands while a song is playing. The first parameter is the +command (these are defined in ao.h), the second is the parameter. These commands are as follows: + +COMMAND_PREV (parameter ignored) - for file formats which have more than one song in a file (NSF), this +moves back one song. + +COMMAND_NEXT (parameter ignored) - for file formats which have more than one song in a file (NSF), this +moves forward one song. + +COMMAND_RESTART (parameter ignored) - Restarts the current song from the beginning. Not supported by +all engines. + +COMMAND_HAS_PREV (parameter ignored) - for file formats which have more than one song in a file (NSF), +this checks if moving backwards from the current song is a valid operation. (Returns AO_FAIL if not) + +COMMAND_HAS_NEXT (parameter ignored) - for file formats which have more than one song in a file (NSF), +this checks if moving forward from the current song is a valid operation. (Returns AO_FAIL if not) + +COMMAND_GET_MIN (parameter ignored) - for file formats which have more than one song in a file (NSF), +this returns the lowest valid song number. + +COMMAND_GET_MAX (parameter ignored) - for file formats which have more than one song in a file (NSF), +this returns the highest valid song number. + +COMAND_JUMP - for file formats which have more than one song in a file (NSF), this command jumps directly +to a specific song number, which is passed in as the parameter. + + +int32 XXX_fillinfo(ao_display_info *) + +This function fills out the ao_display_info struct (see ao.h for details) with information about the currently +playing song. The information provided varies by engine. diff --git a/plugins/dca/dcaplug.c b/plugins/dca/dcaplug.c index fca8569f..3aea033c 100644 --- a/plugins/dca/dcaplug.c +++ b/plugins/dca/dcaplug.c @@ -33,18 +33,23 @@ #define s16_BE(s16,channels) do {} while (0) #define s32_LE(s32,channels) s32_swap (s32, channels) #define s32_BE(s32,channels) do {} while (0) +#define u32_LE(u32) ((((u32)&0xff000000)>>24)|(((u32)&0x00ff0000)>>8)|(((u32)&0x0000ff00)<<8)|(((u32)&0x000000ff)<<24)) +#define u16_LE(u16) ((((u16)&0xff00)>>8)|(((u16)&0x00ff)<<8)) #else #define s16_LE(s16,channels) do {} while (0) #define s16_BE(s16,channels) s16_swap (s16, channels) #define s32_LE(s32,channels) do {} while (0) #define s32_BE(s32,channels) s32_swap (s32, channels) +#define u32_LE(u32) (u32) +#define u16_LE(u16) (u16) #endif #define min(x,y) ((x)<(y)?(x):(y)) #define max(x,y) ((x)>(y)?(x):(y)) -#define trace(...) { fprintf (stderr, __VA_ARGS__); } -//#define trace(fmt,...) +//#define trace(...) { fprintf (stderr, __VA_ARGS__); } +#define trace(fmt,...) + static const char * exts[] = { "wav", NULL }; static const char *filetypes[] = { "DTS WAV", NULL }; @@ -266,6 +271,7 @@ dts_open_wav (DB_FILE *fp, wavfmt_t *fmt, int *totalsamples) { if (deadbeef->fread (&size, 1, sizeof (size), fp) != sizeof (size)) { return -1; } + size = u32_LE(size); char type[4]; if (deadbeef->fread (type, 1, sizeof (type), fp) != sizeof (type)) { @@ -291,10 +297,18 @@ dts_open_wav (DB_FILE *fp, wavfmt_t *fmt, int *totalsamples) { if (deadbeef->fread (&fmtsize, 1, sizeof (fmtsize), fp) != sizeof (fmtsize)) { return -1; } + fmtsize = u32_LE(fmtsize); if (deadbeef->fread (fmt, 1, sizeof (wavfmt_t), fp) != sizeof (wavfmt_t)) { return -1; } + fmt->wFormatTag = u16_LE (fmt->wFormatTag); + fmt->nChannels = u16_LE (fmt->nChannels); + fmt->nSamplesPerSec = u32_LE (fmt->nSamplesPerSec); + fmt->nAvgBytesPerSec = u32_LE (fmt->nAvgBytesPerSec); + fmt->nBlockAlign = u16_LE (fmt->nBlockAlign); + fmt->wBitsPerSample = u16_LE (fmt->wBitsPerSample); + fmt->cbSize = u16_LE (fmt->cbSize); if (fmt->wFormatTag != 0x0001 || fmt->wBitsPerSample != 16) { return -1; @@ -317,6 +331,7 @@ dts_open_wav (DB_FILE *fp, wavfmt_t *fmt, int *totalsamples) { if (deadbeef->fread (&datasize, 1, sizeof (datasize), fp) != sizeof (datasize)) { return -1; } + datasize = u32_LE (datasize); *totalsamples = datasize / ((fmt->wBitsPerSample >> 3) * fmt->nChannels); diff --git a/plugins/faad2/Makefile.am b/plugins/faad2/Makefile.am deleted file mode 100644 index 963e4c7d..00000000 --- a/plugins/faad2/Makefile.am +++ /dev/null @@ -1,9 +0,0 @@ -if HAVE_FAAD -faad2dir = $(libdir)/$(PACKAGE) -pkglib_LTLIBRARIES = faad2.la -faad2_la_SOURCES = faad2.c -faad2_la_LDFLAGS = -module - -faad2_la_LIBADD = $(LDADD) $(FAAD2_LIBS) -AM_CFLAGS = $(CFLAGS) -std=c99 -endif diff --git a/plugins/faad2/faad2.c b/plugins/faad2/faad2.c deleted file mode 100644 index 9b30667a..00000000 --- a/plugins/faad2/faad2.c +++ /dev/null @@ -1,270 +0,0 @@ -/* - DeaDBeeF - ultimate music player for GNU/Linux systems with X11 - Copyright (C) 2009-2010 Alexey Yakovenko <waker@users.sourceforge.net> - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include <string.h> -#include <stdio.h> -#include <neaacdec.h> -#include <mp4ff.h> -#include <stdlib.h> -#include "../../deadbeef.h" - -#define min(x,y) ((x)<(y)?(x):(y)) -#define max(x,y) ((x)>(y)?(x):(y)) - -#define trace(...) { fprintf(stderr, __VA_ARGS__); } -//#define trace(fmt,...) - -static DB_decoder_t plugin; -static DB_functions_t *deadbeef; - -static int -aac_init (DB_playItem_t *it) { - return 0; -} - -static void -aac_free (void) { -} - -static int -aac_read_int16 (char *bytes, int size) { - return 0; -} - -static int -aac_seek_sample (int sample) { - return 0; -} - -static int -aac_seek (float t) { - return aac_seek_sample (t * plugin.info.samplerate); -} - -static uint32_t -aac_fs_read (void *user_data, void *buffer, uint32_t length) { - trace ("aac_fs_read\n"); - DB_FILE *fp = (DB_FILE *)user_data; - return deadbeef->fread (buffer, 1, length, fp); -} - -static uint32_t -aac_fs_seek (void *user_data, uint64_t position) { - trace ("aac_fs_seek\n"); - DB_FILE *fp = (DB_FILE *)user_data; - return deadbeef->fseek (fp, position, SEEK_SET); -} - -/* - * These routines are derived from MPlayer. - */ - -/// \param srate (out) sample rate -/// \param num (out) number of audio frames in this ADTS frame -/// \return size of the ADTS frame in bytes -/// aac_parse_frames needs a buffer at least 8 bytes long -static int -aac_parse_frame(uint8_t *buf, int *srate, int *num) -{ - int i = 0, sr, fl = 0; - static int srates[] = {96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 0, 0, 0}; - - if((buf[i] != 0xFF) || ((buf[i+1] & 0xF6) != 0xF0)) - return 0; - - /* We currently have no use for the id below. - id = (buf[i+1] >> 3) & 0x01; //id=1 mpeg2, 0: mpeg4 - */ - sr = (buf[i+2] >> 2) & 0x0F; - if(sr > 11) - return 0; - *srate = srates[sr]; - - fl = ((buf[i+3] & 0x03) << 11) | (buf[i+4] << 3) | ((buf[i+5] >> 5) & 0x07); - *num = (buf[i+6] & 0x02) + 1; - - return fl; -} - -static int -parse_aac_stream(DB_FILE *stream) -{ - int cnt = 0, len, srate, num; - int8_t c; - off_t init, probed; - static uint8_t buf[8]; - - init = probed = deadbeef->ftell(stream); - while(probed-init <= 32768 && cnt < 8) - { - c = 0; - while(probed-init <= 32768 && c != 0xFF) - { - if (deadbeef->fread (&c, 1, 1, stream) != 1) { - return 1; - } - if(c < 0) - return 0; - probed = deadbeef->ftell(stream); - } - buf[0] = 0xFF; - if(deadbeef->fread(&(buf[1]), 1, 7, stream) < 7) - return 0; - - len = aac_parse_frame(buf, &srate, &num); - if(len > 0) - { - cnt++; - deadbeef->fseek(stream, len - 8, SEEK_CUR); - } - probed = deadbeef->ftell(stream); - } - - if(cnt < 8) - return 0; - - return 1; -} - -static DB_playItem_t * -aac_insert (DB_playItem_t *after, const char *fname) { - return NULL; // to avoid crashes - trace ("adding %s\n", fname); - DB_FILE *fp = deadbeef->fopen (fname); - if (!fp) { - trace ("not found\n"); - return NULL; - } - if (fp->vfs->streaming) { - trace ("no streaming aac yet (%s)\n", fname); - deadbeef->fclose (fp); - return NULL; - } - - // try mp4 - - mp4ff_callback_t cb = { - .read = aac_fs_read, - .write = NULL, - .seek = aac_fs_seek, - .truncate = NULL, - .user_data = fp - }; - - float duration = -1; - const char *ftype = NULL; - mp4ff_t *mp4 = mp4ff_open_read (&cb); - if (!mp4) { - trace ("not an mp4 file\n"); - deadbeef->fclose (fp); - return NULL; - } - int ntracks = mp4ff_total_tracks (mp4); - trace ("ntracks=%d\n", ntracks); - int i = -1; - for (i = 0; i < ntracks; i++) { - unsigned char* buff = 0; - unsigned int buff_size = 0; - mp4AudioSpecificConfig mp4ASC; - mp4ff_get_decoder_config(mp4, i, &buff, &buff_size); - if(buff){ - int rc = AudioSpecificConfig(buff, buff_size, &mp4ASC); - free(buff); - if(rc < 0) - continue; - break; - } - } - if (i != ntracks) - { - trace ("mp4 track: %d\n", i); - int samplerate = mp4ff_get_sample_rate (mp4, i); - duration = mp4ff_get_track_duration (mp4, i) / (float)samplerate; - ftype = "mp4"; - } - else { - trace ("mp4 track not found\n"); - } - - mp4ff_close (mp4); - - if (duration < 0) { - trace ("trying raw aac\n"); - // not an mp4, try raw aac - deadbeef->rewind (fp); - if (parse_aac_stream (fp)) { - trace ("not aac stream either\n"); - deadbeef->fclose (fp); - return NULL; - } - else { - trace ("yes, it's aac indeed\n"); - ftype = "aac"; - } - } - - DB_playItem_t *it = deadbeef->pl_item_alloc (); - it->decoder = &plugin; - it->fname = strdup (fname); - it->filetype = ftype; - deadbeef->pl_set_item_duration (it, duration); - - // read tags - if (ftype == "aac") { - int apeerr = deadbeef->junk_read_ape (it, fp); - int v2err = deadbeef->junk_read_id3v2 (it, fp); - int v1err = deadbeef->junk_read_id3v1 (it, fp); - } - deadbeef->pl_add_meta (it, "title", NULL); - - deadbeef->fclose (fp); - - return deadbeef->pl_insert_item (after, it); -} - -static const char * exts[] = { "aac", "mp4", "m4a", NULL }; -static const char *filetypes[] = { "aac", "mp4", NULL }; - -// define plugin interface -static DB_decoder_t plugin = { - DB_PLUGIN_SET_API_VERSION - .plugin.version_major = 0, - .plugin.version_minor = 1, - .plugin.type = DB_PLUGIN_DECODER, - .plugin.name = "faad2 AAC decoder", - .plugin.descr = "aac/mp4 player", - .plugin.author = "Alexey Yakovenko", - .plugin.email = "waker@users.sourceforge.net", - .plugin.website = "http://deadbeef.sf.net", - .init = aac_init, - .free = aac_free, - .read_int16 = aac_read_int16, - .seek = aac_seek, - .seek_sample = aac_seek_sample, - .insert = aac_insert, - .exts = exts, - .id = "aac", - .filetypes = filetypes -}; - -DB_plugin_t * -faad2_load (DB_functions_t *api) { - deadbeef = api; - return DB_PLUGIN (&plugin); -} diff --git a/plugins/ffmpeg/ffmpeg.c b/plugins/ffmpeg/ffmpeg.c index 62c60bf8..eb99ff9b 100644 --- a/plugins/ffmpeg/ffmpeg.c +++ b/plugins/ffmpeg/ffmpeg.c @@ -55,20 +55,20 @@ static DB_decoder_t plugin; static DB_functions_t *deadbeef; -static const char * exts[] = { "m4a", "aac", "mp4", "mp+", "mpp", "wma", "shn", "aa3", "oma", "ac3", "vqf", NULL }; +static const char * exts[] = { "m4a", "mp+", "mpp", "wma", "shn", "aa3", "oma", "ac3", "vqf", NULL }; enum { - FT_AAC = 0, - FT_M4A = 1, - FT_WMA = 2, - FT_SHORTEN = 3, - FT_ATRAC3 = 4, - FT_VQF = 5, - FT_TTA = 6, - FT_UNKNOWN = 7 +// FT_AAC = 0, + FT_M4A = 0, + FT_WMA = 1, + FT_SHORTEN = 2, + FT_ATRAC3 = 3, + FT_VQF = 4, + FT_TTA = 5, + FT_UNKNOWN = 6 }; -static const char *filetypes[] = { "AAC", "M4A", "WMA", "Shorten", "atrac3", "VQF", "TTA", "FFMPEG", NULL }; +static const char *filetypes[] = { "M4A", "WMA", "Shorten", "atrac3", "VQF", "TTA", "FFMPEG (unknown)", NULL }; #define FF_PROTOCOL_NAME "deadbeef" @@ -519,12 +519,12 @@ ffmpeg_insert (DB_playItem_t *after, const char *fname) { if (!strcasecmp (ext, "m4a")) { filetype = filetypes[FT_M4A]; } - if (!strcasecmp (ext, "aac")) { - filetype = filetypes[FT_AAC]; - } - else if (!strcasecmp (ext, "mp4")) { - filetype = filetypes[FT_M4A]; - } +// if (!strcasecmp (ext, "aac")) { +// filetype = filetypes[FT_AAC]; +// } +// else if (!strcasecmp (ext, "mp4")) { +// filetype = filetypes[FT_M4A]; +// } else if (!strcasecmp (ext, "wma")) { filetype = filetypes[FT_WMA]; } @@ -609,7 +609,7 @@ ffmpeg_vfs_read(URLContext *h, unsigned char *buf, int size) } static int -ffmpeg_vfs_write(URLContext *h, unsigned char *buf, int size) +ffmpeg_vfs_write(URLContext *h, const unsigned char *buf, int size) { return -1; } diff --git a/plugins/gtkui/callbacks.c b/plugins/gtkui/callbacks.c index 81183a66..fabeae76 100644 --- a/plugins/gtkui/callbacks.c +++ b/plugins/gtkui/callbacks.c @@ -108,6 +108,7 @@ set_file_filter (GtkWidget *dlg, const char *name) { gtk_file_filter_set_name (flt, _("Other files (*)")); gtk_file_filter_add_pattern (flt, "*"); gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dlg), flt); + return flt; } void @@ -434,9 +435,10 @@ seekbar_draw (GtkWidget *widget) { if (trk) { deadbeef->pl_item_unref (trk); } - clearlooks_rounded_rectangle (cr, 2+ax, widget->allocation.height/2-4+ay, aw-4, 8, 4, 0xff); // empty seekbar, just a frame + clearlooks_rounded_rectangle (cr, 2+ax, widget->allocation.height/2-4+ay, aw-4, 8, 4, 0xff); cairo_set_source_rgb (cr, clr_selection.red/65535.f, clr_selection.green/65535.f, clr_selection.blue/65535.f ); + cairo_set_line_width (cr, 2); cairo_stroke (cr); cairo_destroy (cr); return; diff --git a/plugins/gtkui/ddbvolumebar.c b/plugins/gtkui/ddbvolumebar.c index a9191cff..1efa2881 100644 --- a/plugins/gtkui/ddbvolumebar.c +++ b/plugins/gtkui/ddbvolumebar.c @@ -155,31 +155,11 @@ ddb_volumebar_init(DdbVolumeBar *volumebar) { } -#define DRAW_DEBUG 0 - void volumebar_draw (GtkWidget *widget) { if (!widget) { return; } -#if DRAW_DEBUG - gdk_draw_rectangle (widget->window, widget->style->bg_gc[0], TRUE, 0, 0, widget->allocation.width, widget->allocation.height); - GdkGC **gc[] = { - widget->style->fg_gc, - widget->style->bg_gc, - widget->style->light_gc, - widget->style->dark_gc, - widget->style->mid_gc, - widget->style->text_gc, - widget->style->base_gc, - widget->style->text_aa_gc - }; - for (int i = 0; i < 8; i++) { - for (int state = 0; state < 5; state++) { - gdk_draw_rectangle (widget->window, gc[i][state], TRUE, i * 8, state * 5, 8, 5); - } - } -#else GdkDrawable *volumebar_backbuf = GDK_DRAWABLE (widget->window); float range = -deadbeef->volume_get_min_db (); int n = widget->allocation.width / 4; @@ -207,9 +187,17 @@ volumebar_draw (GtkWidget *widget) { gdk_draw_rectangle (volumebar_backbuf, back_gc, TRUE, _x + widget->allocation.x, _y + widget->allocation.y, _w, _h); } } + if (DDB_VOLUMEBAR (widget)->show_dbs) { + draw_begin ((uintptr_t)widget->window); + draw_init_font (widget->style); + char s[100]; + int db = deadbeef->volume_get_db (); + snprintf (s, sizeof (s), "%s%ddB", db < 0 ? "" : "+", db); + draw_text (widget->allocation.x, widget->allocation.y, widget->allocation.width, 0, s); + draw_end (); + } g_object_unref (back_gc); g_object_unref (front_gc); -#endif } gboolean @@ -243,16 +231,19 @@ gboolean on_volumebar_button_press_event (GtkWidget *widget, GdkEventButton *event) { - float range = -deadbeef->volume_get_min_db (); - float volume = (event->x - widget->allocation.x)/ widget->allocation.width * range - range; - if (volume < -range) { - volume = -range; - } - if (volume > 0) { - volume = 0; + if (event->button == 1) { + float range = -deadbeef->volume_get_min_db (); + float volume = (event->x - widget->allocation.x)/ widget->allocation.width * range - range; + if (volume < -range) { + volume = -range; + } + if (volume > 0) { + volume = 0; + } + deadbeef->volume_set_db (volume); + DDB_VOLUMEBAR (widget)->show_dbs = 1; + gtk_widget_queue_draw (widget); } - deadbeef->volume_set_db (volume); - gtk_widget_queue_draw (widget); return FALSE; } @@ -261,6 +252,10 @@ gboolean on_volumebar_button_release_event (GtkWidget *widget, GdkEventButton *event) { + if (event->button == 1) { + DDB_VOLUMEBAR (widget)->show_dbs = 0; + gtk_widget_queue_draw (widget); + } return FALSE; } diff --git a/plugins/gtkui/ddbvolumebar.h b/plugins/gtkui/ddbvolumebar.h index 192f1545..530e556e 100644 --- a/plugins/gtkui/ddbvolumebar.h +++ b/plugins/gtkui/ddbvolumebar.h @@ -38,6 +38,7 @@ typedef void * DdbVolumeBarColIter; struct _DdbVolumeBar { GtkWidget parent; + int show_dbs; }; struct _DdbVolumeBarClass { diff --git a/plugins/gtkui/gtkui.c b/plugins/gtkui/gtkui.c index 8a5acecd..c743983d 100644 --- a/plugins/gtkui/gtkui.c +++ b/plugins/gtkui/gtkui.c @@ -153,7 +153,7 @@ update_songinfo (gpointer ctx) { const char *mode; char temp[20]; if (c->channels <= 2) { - c->channels == 1 ? _("Mono") : _("Stereo"); + mode = c->channels == 1 ? _("Mono") : _("Stereo"); } else { snprintf (temp, sizeof (temp), "%dch Multichannel", c->channels); @@ -218,6 +218,15 @@ update_songinfo (gpointer ctx) { return FALSE; } +void +set_tray_tooltip (const char *text) { +#if (GTK_MINOR_VERSION < 16) + gtk_status_icon_set_tooltip (trayicon, text); +#else + gtk_status_icon_set_tooltip_text (trayicon, text); +#endif +} + gboolean on_trayicon_scroll_event (GtkWidget *widget, GdkEventScroll *event, @@ -234,11 +243,23 @@ on_trayicon_scroll_event (GtkWidget *widget, if (vol > 0) { vol = 0; } - else if (vol < -60) { - vol = -60; + else if (vol < deadbeef->volume_get_min_db ()) { + vol = deadbeef->volume_get_min_db (); } deadbeef->volume_set_db (vol); volumebar_redraw (); + +#if 0 + char str[100]; + if (deadbeef->conf_get_int ("gtkui.show_gain_in_db", 1)) { + snprintf (str, sizeof (str), "Gain: %s%d dB", vol == 0 ? "+" : "", (int)vol); + } + else { + snprintf (str, sizeof (str), "Gain: %d%%", (int)(deadbeef->volume_get_amp () * 100)); + } + set_tray_tooltip (str); +#endif + return FALSE; } @@ -365,15 +386,6 @@ gtkui_on_songchanged (DB_event_trackchange_t *ev, uintptr_t data) { return 0; } -void -set_tray_tooltip (const char *text) { -#if (GTK_MINOR_VERSION < 16) - gtk_status_icon_set_tooltip (trayicon, text); -#else - gtk_status_icon_set_tooltip_text (trayicon, text); -#endif -} - static void current_track_changed (DB_playItem_t *it) { char str[600]; @@ -1006,6 +1018,7 @@ gtkui_load (DB_functions_t *api) { static const char settings_dlg[] = "property \"Ask confirmation to delete files from disk\" checkbox gtkui.delete_files_ask 1;\n" "property \"Status icon volume control sensitivity\" entry gtkui.tray_volume_sensitivity 1;\n" +// "property \"Show volume in dB (percentage otherwise)\" entry gtkui.show_gain_in_db 1\n" "property \"Custom status icon\" entry gtkui.custom_tray_icon \"" TRAY_ICON "\" ;\n" "property \"Run gtk_init with --sync (debug mode)\" checkbox gtkui.sync 0;\n" ; diff --git a/plugins/gtkui/trkproperties.c b/plugins/gtkui/trkproperties.c index cea21d6f..55561889 100644 --- a/plugins/gtkui/trkproperties.c +++ b/plugins/gtkui/trkproperties.c @@ -178,6 +178,8 @@ trkproperties_fill_metadata (void) { gtk_list_store_set (propstore, &iter, 0, _("Tag Type(s)"), 1, temp, -1); gtk_list_store_append (propstore, &iter); gtk_list_store_set (propstore, &iter, 0, _("Embedded Cuesheet"), 1, (deadbeef->pl_get_item_flags (track) & DDB_HAS_EMBEDDED_CUESHEET) ? _("Yes") : _("No"), -1); + gtk_list_store_append (propstore, &iter); + gtk_list_store_set (propstore, &iter, 0, _("Codec"), 1, track->decoder_id, -1); gtk_list_store_append (propstore, &iter); snprintf (temp, sizeof (temp), "%0.2f dB", track->replaygain_album_gain); diff --git a/plugins/mms/Makefile.am b/plugins/mms/Makefile.am new file mode 100644 index 00000000..c6a06fdb --- /dev/null +++ b/plugins/mms/Makefile.am @@ -0,0 +1,9 @@ +if HAVE_MMS +mmsdir = $(libdir)/$(PACKAGE) +pkglib_LTLIBRARIES = mms.la +mms_la_SOURCES = mms.c +mms_la_LDFLAGS = -module + +mms_la_LIBADD = $(LDADD) $(LIBMMS_LIBS) +AM_CFLAGS = $(CFLAGS) -std=c99 +endif diff --git a/plugins/mms/mms.c b/plugins/mms/mms.c new file mode 100644 index 00000000..617b16f2 --- /dev/null +++ b/plugins/mms/mms.c @@ -0,0 +1,138 @@ +/* + DeaDBeeF - ultimate music player for GNU/Linux systems with X11 + Copyright (C) 2009-2010 Alexey Yakovenko <waker@users.sourceforge.net> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#include "deadbeef.h" +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> +#include <string.h> +#include <libmms/mmsx.h> + +static DB_functions_t *deadbeef; +typedef struct { + DB_vfs_t *vfs; + mmsx_t *stream; + const mms_io_t *io; +} MMS_FILE; + +static DB_vfs_t plugin; + +const uint32_t mms_bandwidths[]={14400,19200,28800,33600,34430,57600, + 115200,262200,393216,524300,1544000,10485800}; + + +const char * mms_bandwidth_strs[]={"14.4 Kbps (Modem)", "19.2 Kbps (Modem)", + "28.8 Kbps (Modem)", "33.6 Kbps (Modem)", + "34.4 Kbps (Modem)", "57.6 Kbps (Modem)", + "115.2 Kbps (ISDN)", "262.2 Kbps (Cable/DSL)", + "393.2 Kbps (Cable/DSL)","524.3 Kbps (Cable/DSL)", + "1.5 Mbps (T1)", "10.5 Mbps (LAN)", NULL}; + + + +static DB_FILE * +mms_open (const char *fname) { + MMS_FILE *fp = malloc (sizeof (MMS_FILE)); + fp->io = mms_get_default_io_impl(); + fp->stream = mmsx_connect ((mms_io_t *)fp->io, fp, fname, 1544000); + if (!fp->stream) { + free (fp); + return NULL; + } + fp->vfs = &plugin; + return (DB_FILE*)fp; +} + +static void +mms_close (DB_FILE *stream) { + assert (stream); + mmsx_close (((MMS_FILE *)stream)->stream); + free (stream); +} + +static size_t +mms_read (void *ptr, size_t size, size_t nmemb, DB_FILE *stream) { + assert (stream); + assert (ptr); + MMS_FILE *fp = (MMS_FILE *)stream; + int res = mmsx_read ((mms_io_t *)fp->io, fp->stream, ptr, size * nmemb); + return res; +} + +static int +mms_seek (DB_FILE *stream, int64_t offset, int whence) { + assert (stream); + MMS_FILE *fp = (MMS_FILE *)stream; + return mmsx_seek ((mms_io_t *)fp->io, fp->stream, offset, whence); +} + +static int64_t +mms_tell (DB_FILE *stream) { + assert (stream); + return mmsx_get_current_pos (((MMS_FILE *)stream)->stream); +} + +static void +mms_rewind (DB_FILE *stream) { + assert (stream); + // FIXME + return; +} + +static int64_t +mms_getlength (DB_FILE *stream) { + assert (stream); + MMS_FILE *f = (MMS_FILE *)stream; + return mmsx_get_length (f->stream); +} + +const char * +mms_get_content_type (DB_FILE *stream) { + return "audio/wma"; +} + +static const char *scheme_names[] = { "mms://", "mmsh://", NULL }; + +static DB_vfs_t plugin = { + DB_PLUGIN_SET_API_VERSION + .plugin.version_major = 0, + .plugin.version_minor = 1, + .plugin.type = DB_PLUGIN_VFS, + .plugin.name = "mms vfs", + .plugin.descr = "MMS streaming plugin based on libmms", + .plugin.author = "Alexey Yakovenko", + .plugin.email = "waker@users.sourceforge.net", + .plugin.website = "http://deadbeef.sf.net", + .open = mms_open, + .close = mms_close, + .read = mms_read, + .seek = mms_seek, + .tell = mms_tell, + .rewind = mms_rewind, + .getlength = mms_getlength, + .get_content_type = mms_get_content_type, + .scheme_names = scheme_names, + .streaming = 1 +}; + +DB_plugin_t * +mms_load (DB_functions_t *api) { + deadbeef = api; + return DB_PLUGIN (&plugin); +} + diff --git a/plugins/musepack/mpc/minimax.h b/plugins/musepack/mpc/minimax.h new file mode 100644 index 00000000..11926265 --- /dev/null +++ b/plugins/musepack/mpc/minimax.h @@ -0,0 +1,57 @@ +/* + * Musepack audio compression + * Copyright (C) 1999-2004 Buschmann/Klemm/Piecha/Wolf + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#pragma once + +# define clip(x,min,max) ( (x) < (min) ? (min) : (x) > (max) ? (max) : (x) ) + +#ifdef __cplusplus + +# define maxi(A,B) ( (A) >? (B) ) +# define mini(A,B) ( (A) <? (B) ) +# define maxd(A,B) ( (A) >? (B) ) +# define mind(A,B) ( (A) <? (B) ) +# define maxf(A,B) ( (A) >? (B) ) +# define minf(A,B) ( (A) <? (B) ) + +#else + +# define maxi(A,B) ( (A) > (B) ? (A) : (B) ) +# define mini(A,B) ( (A) < (B) ? (A) : (B) ) +# define maxd(A,B) ( (A) > (B) ? (A) : (B) ) +# define mind(A,B) ( (A) < (B) ? (A) : (B) ) +# define maxf(A,B) ( (A) > (B) ? (A) : (B) ) +# define minf(A,B) ( (A) < (B) ? (A) : (B) ) + +#endif + +#ifdef __GNUC__ + +# define absi(A) abs (A) +# define absf(A) fabsf (A) +# define absd(A) fabs (A) + +#else + +# define absi(A) ( (A) >= 0 ? (A) : -(A) ) +# define absf(A) ( (A) >= 0.f ? (A) : -(A) ) +# define absd(A) ( (A) >= 0. ? (A) : -(A) ) + +#endif + diff --git a/plugins/musepack/mpc/mpc_types.h b/plugins/musepack/mpc/mpc_types.h new file mode 100644 index 00000000..bd51f06a --- /dev/null +++ b/plugins/musepack/mpc/mpc_types.h @@ -0,0 +1,138 @@ +/* + Copyright (c) 2005-2009, The Musepack Development Team + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of the The Musepack Development Team nor the + names of its contributors may be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef _MPC_TYPES_H_ +#define _MPC_TYPES_H_ +#ifdef WIN32 +#pragma once +#endif + +#include <stdlib.h> +#include <memory.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _MSC_VER +typedef __int8 mpc_int8_t; +typedef unsigned __int8 mpc_uint8_t; +typedef __int16 mpc_int16_t; +typedef unsigned __int16 mpc_uint16_t; +typedef __int32 mpc_int32_t; +typedef unsigned __int32 mpc_uint32_t; +typedef __int64 mpc_int64_t; +typedef unsigned __int64 mpc_uint64_t; +#define mpc_inline __inline +#else +#include <stdint.h> +typedef int8_t mpc_int8_t; +typedef uint8_t mpc_uint8_t; +typedef int16_t mpc_int16_t; +typedef uint16_t mpc_uint16_t; +typedef int32_t mpc_int32_t; +typedef uint32_t mpc_uint32_t; +typedef int64_t mpc_int64_t; +typedef uint64_t mpc_uint64_t; +#define mpc_inline inline +#endif + +typedef int mpc_int_t; +typedef unsigned int mpc_uint_t; +typedef size_t mpc_size_t; +typedef mpc_uint8_t mpc_bool_t; + +// #define LONG_SEEK_TABLE +#ifdef LONG_SEEK_TABLE // define as needed (mpc_uint32_t supports files up to 512 MB) +typedef mpc_uint64_t mpc_seek_t; +#else +typedef mpc_uint32_t mpc_seek_t; +#endif + +# define mpc_int64_min -9223372036854775808ll +# define mpc_int64_max 9223372036854775807ll + +typedef struct mpc_quantizer { + mpc_int16_t L [36]; + mpc_int16_t R [36]; +} mpc_quantizer; + +/// Libmpcdec error codes +typedef enum mpc_status { + MPC_STATUS_OK = 0, + MPC_STATUS_FILE = -1, + MPC_STATUS_SV7BETA = -2, + MPC_STATUS_CBR = -3, + MPC_STATUS_IS = -4, + MPC_STATUS_BLOCKSIZE = -5, + MPC_STATUS_INVALIDSV = -6 +} mpc_status; + + +#define MPC_FIXED_POINT_SHIFT 16 + +#ifdef MPC_FIXED_POINT +# define MPC_FIXED_POINT_FRACTPART 14 +# define MPC_FIXED_POINT_SCALE_SHIFT (MPC_FIXED_POINT_SHIFT + MPC_FIXED_POINT_FRACTPART) +# define MPC_FIXED_POINT_SCALE (1 << (MPC_FIXED_POINT_SCALE_SHIFT - 1)) +typedef mpc_int32_t MPC_SAMPLE_FORMAT; +#else +typedef float MPC_SAMPLE_FORMAT; +#endif + +enum { + MPC_FALSE = 0, + MPC_TRUE = !MPC_FALSE +}; + +//// 'Cdecl' forces the use of standard C/C++ calling convention /////// +#if defined _WIN32 +# define mpc_cdecl __cdecl +#elif defined __ZTC__ +# define mpc_cdecl _cdecl +#elif defined __TURBOC__ +# define mpc_cdecl cdecl +#else +# define mpc_cdecl +#endif + +#ifdef __GNUC__ +# define MPC_API __attribute__ ((visibility("default"))) +#else +# define MPC_API +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/plugins/musepack/mpcdec.h b/plugins/musepack/mpc/mpcdec.h index c7235951..c7235951 100644 --- a/plugins/musepack/mpcdec.h +++ b/plugins/musepack/mpc/mpcdec.h diff --git a/plugins/musepack/reader.h b/plugins/musepack/mpc/reader.h index 1a93e067..1a93e067 100644 --- a/plugins/musepack/reader.h +++ b/plugins/musepack/mpc/reader.h diff --git a/plugins/musepack/streaminfo.h b/plugins/musepack/mpc/streaminfo.h index a0a9470b..a0a9470b 100644 --- a/plugins/musepack/streaminfo.h +++ b/plugins/musepack/mpc/streaminfo.h diff --git a/plugins/musepack/musepack.c b/plugins/musepack/musepack.c index 44e364f4..595eb571 100644 --- a/plugins/musepack/musepack.c +++ b/plugins/musepack/musepack.c @@ -20,7 +20,7 @@ #include <assert.h> #include <limits.h> #include <unistd.h> -#include "mpcdec.h" +#include "mpc/mpcdec.h" #ifdef HAVE_CONFIG_H # include <config.h> #endif diff --git a/plugins/shn/AUTHORS b/plugins/shn/AUTHORS new file mode 100644 index 00000000..cf097345 --- /dev/null +++ b/plugins/shn/AUTHORS @@ -0,0 +1,2 @@ +original xmms-shn plugin: Jason Jordan <shnutils@freeshell.org> +deadbeef port: Alexey Yakovenko <waker@users.sourceforge.net> diff --git a/plugins/shn/LICENSE.shorten b/plugins/shn/LICENSE.shorten new file mode 100644 index 00000000..d5066c7a --- /dev/null +++ b/plugins/shn/LICENSE.shorten @@ -0,0 +1,20 @@ +SHORTEN SOFTWARE LICENSE + +This software is being provided to you, the LICENSEE, by Tony Robinson +and SoftSound under the following license. By obtaining, using and/or +copying this software, you agree that you have read, understood, and +will comply with these terms and conditions: + +This software may not be sold or incorporated into any product which is +sold without prior permission from SoftSound. When no charge is made, +this software may be copied and distributed freely. + +Permission is granted to use this software for decoding and +non-commercial encoding (e.g. private or research use). Please email +shorten@softsound.com for commercial encoding terms. + +DISCLAIMER + +This software carries no warranty, expressed or implied. The user +assumes all risks, known or unknown, direct or indirect, which involve +this software in any way. diff --git a/plugins/shn/Makefile.am b/plugins/shn/Makefile.am new file mode 100644 index 00000000..44671140 --- /dev/null +++ b/plugins/shn/Makefile.am @@ -0,0 +1,10 @@ +if HAVE_SHN +shndir = $(libdir)/$(PACKAGE) +pkglib_LTLIBRARIES = shn.la +shn_la_SOURCES = array.c config.h convert.c misc.c output.c seek.c shn.c shn.h shorten.c shorten.h sulawalaw.c vario.c wave.c + +shn_la_LDFLAGS = -module + +shn_la_LIBADD = $(LDADD) +AM_CFLAGS = $(CFLAGS) -std=c99 +endif diff --git a/plugins/shn/README b/plugins/shn/README new file mode 100644 index 00000000..942d8ace --- /dev/null +++ b/plugins/shn/README @@ -0,0 +1,355 @@ +xmms-shn version 2.4.x + + +-------- +Overview +-------- + +xmms-shn provides playback support for shorten (.shn) files in XMMS. Real-time +seeking support is provided for .shn files that have accompanying seek tables +generated by shorten 3.x. Otherwise, seeking is not supported. + +See the "Shorten 3.x overview" section below for more information about this new +seek-enabled version of shorten. + + +------- +License +------- + +xmms-shn is dual-licensed. The code taken from the sources of 'shorten' remains +under the shorten license (see doc/LICENSE.shorten), while the rest of the code +is GPL (see COPYING). + + +------------ +Availability +------------ + +The latest version of this plugin can always be found at the sites below: + + http://www.etree.org/shnutils/ + http://shnutils.freeshell.org/ + +Please see the ChangeLog file for changes to this plugin since its creation. + + +------------ +Dependencies +------------ + +As of version 2.0, xmms-shn no longer depends on an external shorten executable +to work, since the core shorten algorithm has been incorporated directly into +xmms-shn. + +You should have XMMS 1.0.0 or newer, and GTK & GLIB 1.2.2 or newer. The +configure script will usually find these if you installed them from source. +However, if you installed any of the above via .rpm's, then you may need to tell +the configure script where to find them. To see what options are available, +type: + +% ./configure --help + +The applicable options are the following: + + --with-xmms-prefix=PFX Prefix where XMMS is installed (optional) + --with-xmms-exec-prefix=PFX Exec prefix where XMMS is installed (optional) + --with-glib-prefix=PFX Prefix where GLIB is installed (optional) + --with-glib-exec-prefix=PFX Exec prefix where GLIB is installed (optional) + --disable-glibtest Do not try to compile and run a test GLIB program + --with-gtk-prefix=PFX Prefix where GTK is installed (optional) + --with-gtk-exec-prefix=PFX Exec prefix where GTK is installed (optional) + --disable-gtktest Do not try to compile and run a test GTK program + + +----------------------------------- +Building and installing this plugin +----------------------------------- + +For instructions on how to build and install this plugin, please consult the +INSTALL file. It is usually as simple as the following: + +% ./configure +% make +% su -c "make install" +Password: (give your root password here) +% + + +--------------------- +Configuration options +--------------------- + +This section details the options that can be found in the plugin's configuration +window in XMMS, under Preferences -> Audio I/O Plugins -> SHN Player 2.4.x -> +Configure. + + +Error Display tab: +================== + + Error display options: + ---------------------- + + This option determines where any error messages go - to a popup window, + to standard error, or to the bit bucket. Pretty self-explanatory. + + +Seek Tables tab: +================ + + Alternate seek table file locations: + ------------------------------------ + + These options allow you to specify alternate directores to search for .skt + (seek table) files. These directories will be searched after all other attempts + to locate a seek table for a given file have failed. + + The "Relative seek table path" option allows you to specify a subdirectory + relative to the base directory of a given file, where seek tables may reside. + This is useful if you create seek table files for a group of .shn files, and + store them in a commonly-named subdirectory of that group. + + The "Absolute seek table path" option allows you to specify an absolute directory + where seek tables may reside. This is useful if you create seek table files for + multiple groups of .shn files and store them in the same directory. + + When searching for seek tables belonging to a file (e.g. '/mnt/shn/filename.shn'), + xmms-shn will do the following, in this order, until it either finds a seek table + or runs out of places to check for one: + + 1. look for a seek table appended to '/mnt/shn/filename.shn' (whether at the end, + or hidden behind an ID3v1 tag) + + 2. look for a seek table in '/mnt/shn/filename.skt' + + 3. look for a seek table in '/mnt/shn/relative_dir/filename.skt', where + 'relative_dir' is the directory specified in the "Relative seek table path" + option + + 4. look for a seek table in '/absolute_dir/filename.skt', where 'absolute_dir' + is the directory specified in the "Absolute seek table path" option + + +Miscellaneous tab: +================== + + Miscellaneous options: + ---------------------- + + The "Swap audio bytes on output" option is useful in situations where every file + you play back is static. This is known to help on the following platforms: + + + Sun Ultra 10 and Ultra 30 both running Solaris 8 + + SGI Octane/Irix 6.5 + + + The "Display debug info to stderr" option specifies whether to display debugging + messages to stderr. This is potentially useful for remote debugging, and also + just to see what's going on. Debug lines are always shown with a prefix of + "xmms-shn [debug]:". + + Note that if "Display debug info to stderr" is enabled, and the error display + option is set to /dev/null, then all non-debug messages that normally would be + suppressed are displayed to stderr with a prefix of "xmms-shn [error]:". + + The "Load text files in file information box" option specifies whether text files + found in the same or parent directory as the given file should be loaded into the + file information box. Each file found will be loaded in a separate tab. The tabs + will be labeled "Text file n", where n starts at 1 and increases with each new + text file. + + The "Text file extensions" option lets you specify a comma-separated list of case- + sensitive file extensions that xmms-shn will recognize as text files. The default + list is "txt,nfo". This option is only useful if "Load text files in file + information box" is enabled. + + Note: + + Text file support is useful for quickly determining information about the given + file and/or the show it belongs to, assuming such information is contained within + the text files. + + Text file location assumes some combination of the following two directory + structures: all text files and .shn files in the same directory, or text files + in a directory with all .shn files in subdirectories one level deep. This + pretty much covers all directory structures seen on live music servers and file- + sharing programs. + + +-------------------- +File information box +-------------------- + +This section describes the output shown in the file information window, which +can be viewed by choosing 'File Inf.' from the 'Misc. Opt' button in the +playlist editor, or selecting 'View File Info' from XMMS's main popup menu. + +Properties tab: +=============== + + Filename: Shows the full path to the .shn file being examined. + + Length: Shows the length of the WAVE data in the file, in m:ss.nnn format. + If the WAVE data is CD-quality (see below for definition), then the length is + shown in m:ss.ff format, where ff is a number from 00 to 74 that best + approximates the number of frames (2352-byte blocks) remaining after m:ss. + + Note on rounding: If the WAVE data is CD-quality, then its length is + rounded to the nearest frame. Otherwise, it is rounded + to the nearest millisecond. + + Seekable: Shows whether a seek table was found for the given file. + + Seek table revision: Shows the revision number of the seek tables, if + present. Note that it is possible for this field to contain a numeric value, + even when the file is not seekable - for example, xmms-shn might detect that + certain seek tables are unsupported or buggy, and disable seeking in those + files. + + Compression ratio: Shows the compression ratio for the given file. This is + simply the file's actual size divided by its total size, as calculated from + the chunk size contained in the WAVE header. Note that if the given file is + truncated (or has junk appended to it), then the compression ratio will be + skewed accordingly. + + CD-quality properties: + ---------------------- + + CD-quality: Shows whether the given file is CD-quality. A file is considered + to be CD-quality if its header indicates 2 channels, 16 bits/sample, 44100 + samples/second, and 176400 average bytes/second. + + Cut on a sector boundary: If the given file is CD-quality, then this shows + whether the length of its WAVE data is a multiple of 2352 bytes (1/75 of a + second). Otherwise, "n/a" is displayed. + + Sector misalignemt: If the file is CD-quality, then the sector misalignment + is simply the remainder when the data size is divided by 2352; i.e. it is the + number of bytes by which the audio data exceeds the previous sector boundary. + + Long enough to be burned: If the given file is CD-quality, then this shows + whether the length of its WAVE data is long enough to be burned (705600 bytes, + or 3 seconds in length). Otherwise, "n/a" is displayed. + + WAVE properties: + ---------------- + + Non-canonical header: Shows whether the WAVE header is canonical. A header + is considered canonical if it is 44 bytes long (this is the smallest possible + size that a WAVE header can be). + + Extra RIFF chunks: Shows whether there are any extra RIFF chunks following + the data chunk in the WAVE stream. + + Possible problems: + ------------------ + + File contains ID3v2 tag: Shows whether the file contains an ID3v2 tag, and + if so, how many bytes it occupies. This is not a problem for xmms-shn (it + was able to read the file after all), but could pose a problem for programs + that are not able to process files with ID3v2 tags. + + +Details tab: +============ + + This tab primarily shows the raw information taken from the WAVE header of the + given file. Each entry is self-explanatory. + + +Text file n tab(s): +=================== + + These tabs, if any, show the contents of all text files found in the same + directory or parent directory as the given file. The associated file name for + each tab is contained in the frame surrounding the text, and the full path to + the file being displayed is shown just above the text. You can control which + files are considered to be text files with the "Text file extensions" option in + the configuration window. Make sure to select the "Load text files in file + information box" option if you want to see these tabs. + + +-------------------- +Shorten 3.x overview +-------------------- + +Wayne Stielau has extended shorten 2.3 to support the creation of seek tables. +Seek tables are simply descriptions of the internal state of the shorten +algorithm at specific points in the decompression. This allows a modified +shorten decoder to restore the decoder state of the shorten algorithm for a +point at (or very close to) the desired seek point. You can get the latest +version at any of the URLs below: + + http://www.etree.org/shnutils/shorten/ + http://shnutils.freeshell.org/shorten/ + +Seek tables may be appended to the .shn itself, or stored in a separate file +(usually with a suffix of '.skt'). xmms-shn supports both of these options. + +The current implementation creates a seek table entry once every 25600 samples. +For 'CD-quality' WAVE data (44100 samples/sec), this provides a granularity of 1 +seek table entry per 25600/44100 ~= 0.58 seconds, more than what is needed by +either XMMS or WinAmp. + +At 80 bytes per seek table entry, you can expect the seek table to add about +0.1% to the size of the existing shortened file, for 'CD-quality' WAVE data. +So the seek table generated for 1 GB of already-shortened 'CD-quality' WAVE data +will fit on a floppy! Quite a deal, if you ask me. :-) + +Best of all, shorten 3.x is fully backward compatible with version 2.3, meaning +that any files created by shorten 3.x can be processed by version 2.3 with no +problems. + +The command line options for dealing with seek tables in shorten 3.x are: + + -e erase seek table appended to input file * + -i inquire as to whether a seek table is appended to input file * + -k append seek table information to existing shorten file + -s generate seek table information in separate file [input file].skt + -S[name] generate seek table information in separate file given by [name] + -v 3 format version number (2: no seek info; 3: default) * + + * only available in versions 3.2 and up + +By default, any file shortened with version 3.x will automatically have seek +tables appended to it. In later versions (3.2 and up), you can disable this +with the -v2 switch. + +** NOTE ON SEEKING IN FILES ENCODED WITH NON-DEFAULT OPTIONS ** + +Seek tables are unable to support all types of SHN files due to limitations in +their original design. The only files they can fully support are ones encoded +with the following values: + + -c = 1 or 2 (number of channels, default is 1) + -p in the range [0 .. 3] (maximum LPC predictor order, default is 0) + -m in the range [0 .. 4] (number of block for mean estimation, default is 4) + +If xmms-shn detects a file encoded with parameters that fall outside of these +ranges, then seeking is automatically disabled for that file. + + +---------- +Known bugs +---------- + +I test this plugin aggressively until I can no longer make it crash. That does +not mean that there are no bugs. If you can crash it, I want to hear about it - +please report it to me at the address below. The xmms-shn webpage (see the +Availability section above) will always contain an up-to-date list of reported +bugs, so be sure to check that page before you send me a bug report. + +Also, feel free to send me any questions, comments, feature requests, patches... +I always enjoy getting feedback. + +Enjoy! + +Jason Jordan <shnutils@freeshell.org> + + +================== +Document revision: +================== + +$Id: README,v 1.27 2007/03/29 00:08:05 jason Exp $ diff --git a/plugins/shn/array.c b/plugins/shn/array.c new file mode 100644 index 00000000..0adf8549 --- /dev/null +++ b/plugins/shn/array.c @@ -0,0 +1,41 @@ +/****************************************************************************** +* * +* Copyright (C) 1992-1995 Tony Robinson * +* * +* See the file doc/LICENSE.shorten for conditions on distribution and usage * +* * +******************************************************************************/ + +/* + * $Id: array.c,v 1.7 2003/08/26 05:34:04 jason Exp $ + */ + +#include <stdio.h> +#include <stdlib.h> +#include "shorten.h" +#include "shn.h" + +void *pmalloc(ulong size, shn_file *this_shn) { + void *ptr; + + ptr = malloc(size); + + if(ptr == NULL) + shn_error_fatal(this_shn,"Call to malloc(%ld) failed in pmalloc() -\nyour system may be low on memory", size); + + return(ptr); +} + +slong **long2d(ulong n0, ulong n1, shn_file *this_shn) { + slong **array0 = NULL; + + if((array0 = (slong**) pmalloc((ulong) (n0 * sizeof(slong*) + + n0 * n1 * sizeof(slong)),this_shn)) != NULL ) { + slong *array1 = (slong*) (array0 + n0); + int i; + + for(i = 0; i < n0; i++) + array0[i] = array1 + i * n1; + } + return(array0); +} diff --git a/plugins/shn/bitshift.h b/plugins/shn/bitshift.h new file mode 100644 index 00000000..ad491f92 --- /dev/null +++ b/plugins/shn/bitshift.h @@ -0,0 +1,33 @@ +char ulaw_maxshift[256] = {12,8,7,9,7,8,7,10,7,8,7,9,7,8,7,11,6,7,6,8,6,7,6,9,6,7,6,8,6,7,6,10,5,6,5,7,5,6,5,8,5,6,5,7,5,6,5,9,5,4,6,4,5,4,7,4,5,4,6,4,5,4,8,4,3,5,3,4,3,6,3,4,3,5,3,4,3,7,3,4,2,3,2,5,2,3,2,4,2,3,2,6,2,3,2,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,0,7,8,7,9,7,8,7,10,7,8,7,9,7,8,7,11,6,7,6,8,6,7,6,9,6,7,6,8,6,7,6,10,5,6,5,7,5,6,5,8,5,6,5,7,5,6,5,9,5,4,6,4,5,4,7,4,5,4,6,4,5,4,8,4,3,5,3,4,3,6,3,4,3,5,3,4,3,7,3,4,2,3,2,5,2,3,2,4,2,3,2,6,2,3,2,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,12}; + +/*schar ulaw_inward[13][256] = { +{4294967169,4294967170,4294967171,4294967172,4294967173,4294967174,4294967175,4294967176,4294967177,4294967178,4294967179,4294967180,4294967181,4294967182,4294967183,4294967184,4294967185,4294967186,4294967187,4294967188,4294967189,4294967190,4294967191,4294967192,4294967193,4294967194,4294967195,4294967196,4294967197,4294967198,4294967199,4294967200,4294967201,4294967202,4294967203,4294967204,4294967205,4294967206,4294967207,4294967208,4294967209,4294967210,4294967211,4294967212,4294967213,4294967214,4294967215,4294967216,4294967217,4294967218,4294967219,4294967220,4294967221,4294967222,4294967223,4294967224,4294967225,4294967226,4294967227,4294967228,4294967229,4294967230,4294967231,4294967232,4294967233,4294967234,4294967235,4294967236,4294967237,4294967238,4294967239,4294967240,4294967241,4294967242,4294967243,4294967244,4294967245,4294967246,4294967247,4294967248,4294967249,4294967250,4294967251,4294967252,4294967253,4294967254,4294967255,4294967256,4294967257,4294967258,4294967259,4294967260,4294967261,4294967262,4294967263,4294967264,4294967265,4294967266,4294967267,4294967268,4294967269,4294967270,4294967271,4294967272,4294967273,4294967274,4294967275,4294967276,4294967277,4294967278,4294967279,4294967280,4294967281,4294967282,4294967283,4294967284,4294967285,4294967286,4294967287,4294967288,4294967289,4294967290,4294967291,4294967292,4294967293,4294967294,4294967295,4294967168,127,126,125,124,123,122,121,120,119,118,117,116,115,114,113,112,111,110,109,108,107,106,105,104,103,102,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0}, +{4294967177,4294967178,4294967179,4294967180,4294967181,4294967182,4294967183,4294967184,4294967185,4294967186,4294967187,4294967188,4294967189,4294967190,4294967191,4294967192,4294967193,4294967194,4294967195,4294967196,4294967197,4294967198,4294967199,4294967200,4294967201,4294967202,4294967203,4294967204,4294967205,4294967206,4294967207,4294967208,4294967209,4294967210,4294967211,4294967212,4294967213,4294967214,4294967215,4294967216,4294967217,4294967218,4294967219,4294967220,4294967221,4294967222,4294967223,4294967224,4294967225,4294967226,4294967227,4294967228,4294967229,4294967230,4294967231,4294967232,4294967233,4294967234,4294967235,4294967236,4294967237,4294967238,4294967239,4294967240,4294967241,4294967242,4294967243,4294967244,4294967245,4294967246,4294967247,4294967248,4294967249,4294967250,4294967251,4294967252,4294967253,4294967254,4294967255,4294967256,4294967257,4294967258,4294967259,4294967260,4294967261,4294967262,4294967263,4294967264,4294967265,4294967266,4294967267,4294967268,4294967269,4294967270,4294967271,4294967272,4294967273,4294967274,4294967275,4294967276,4294967277,4294967278,4294967279,4294967280,4294967281,4294967282,4294967283,4294967284,4294967285,4294967286,4294967287,4294967288,4294967168,4294967289,4294967169,4294967290,4294967170,4294967291,4294967171,4294967292,4294967172,4294967293,4294967173,4294967294,4294967174,4294967295,4294967175,4294967176,119,118,117,116,115,114,113,112,111,110,109,108,107,106,105,104,103,102,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,127,7,126,6,125,5,124,4,123,3,122,2,121,1,120,0}, +{4294967189,4294967190,4294967191,4294967192,4294967193,4294967194,4294967195,4294967196,4294967197,4294967198,4294967199,4294967200,4294967201,4294967202,4294967203,4294967204,4294967205,4294967206,4294967207,4294967208,4294967209,4294967210,4294967211,4294967212,4294967213,4294967214,4294967215,4294967216,4294967217,4294967218,4294967219,4294967220,4294967221,4294967222,4294967223,4294967224,4294967225,4294967226,4294967227,4294967228,4294967229,4294967230,4294967231,4294967232,4294967233,4294967234,4294967235,4294967236,4294967237,4294967238,4294967239,4294967240,4294967241,4294967242,4294967243,4294967244,4294967245,4294967246,4294967247,4294967248,4294967249,4294967250,4294967251,4294967252,4294967253,4294967254,4294967255,4294967256,4294967257,4294967258,4294967259,4294967260,4294967261,4294967262,4294967263,4294967264,4294967265,4294967266,4294967267,4294967268,4294967269,4294967270,4294967271,4294967272,4294967273,4294967274,4294967275,4294967276,4294967277,4294967278,4294967279,4294967280,4294967281,4294967282,4294967283,4294967284,4294967168,4294967285,4294967169,4294967286,4294967170,4294967287,4294967171,4294967288,4294967172,4294967289,4294967173,4294967290,4294967174,4294967291,4294967175,4294967292,4294967176,4294967177,4294967178,4294967293,4294967179,4294967180,4294967181,4294967294,4294967182,4294967183,4294967184,4294967295,4294967185,4294967186,4294967187,4294967188,107,106,105,104,103,102,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,127,11,126,10,125,9,124,8,123,7,122,6,121,5,120,4,119,118,117,3,116,115,114,2,113,112,111,1,110,109,108,0}, +{4294967203,4294967204,4294967205,4294967206,4294967207,4294967208,4294967209,4294967210,4294967211,4294967212,4294967213,4294967214,4294967215,4294967216,4294967217,4294967218,4294967219,4294967220,4294967221,4294967222,4294967223,4294967224,4294967225,4294967226,4294967227,4294967228,4294967229,4294967230,4294967231,4294967232,4294967233,4294967234,4294967235,4294967236,4294967237,4294967238,4294967239,4294967240,4294967241,4294967242,4294967243,4294967244,4294967245,4294967246,4294967247,4294967248,4294967249,4294967250,4294967251,4294967252,4294967253,4294967254,4294967255,4294967256,4294967257,4294967258,4294967259,4294967260,4294967261,4294967262,4294967263,4294967264,4294967265,4294967266,4294967267,4294967268,4294967269,4294967270,4294967271,4294967272,4294967273,4294967274,4294967275,4294967276,4294967277,4294967278,4294967279,4294967280,4294967281,4294967282,4294967168,4294967283,4294967169,4294967284,4294967170,4294967285,4294967171,4294967286,4294967172,4294967287,4294967173,4294967288,4294967174,4294967289,4294967175,4294967290,4294967176,4294967177,4294967178,4294967291,4294967179,4294967180,4294967181,4294967292,4294967182,4294967183,4294967184,4294967293,4294967185,4294967186,4294967187,4294967294,4294967188,4294967189,4294967190,4294967191,4294967192,4294967193,4294967194,4294967295,4294967195,4294967196,4294967197,4294967198,4294967199,4294967200,4294967201,4294967202,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,127,13,126,12,125,11,124,10,123,9,122,8,121,7,120,6,119,118,117,5,116,115,114,4,113,112,111,3,110,109,108,2,107,106,105,104,103,102,101,1,100,99,98,97,96,95,94,0}, +{4294967218,4294967219,4294967220,4294967221,4294967222,4294967223,4294967224,4294967225,4294967226,4294967227,4294967228,4294967229,4294967230,4294967231,4294967232,4294967233,4294967234,4294967235,4294967236,4294967237,4294967238,4294967239,4294967240,4294967241,4294967242,4294967243,4294967244,4294967245,4294967246,4294967247,4294967248,4294967249,4294967250,4294967251,4294967252,4294967253,4294967254,4294967255,4294967256,4294967257,4294967258,4294967259,4294967260,4294967261,4294967262,4294967263,4294967264,4294967265,4294967266,4294967267,4294967268,4294967269,4294967270,4294967271,4294967272,4294967273,4294967274,4294967275,4294967276,4294967277,4294967278,4294967279,4294967280,4294967281,4294967168,4294967282,4294967169,4294967283,4294967170,4294967284,4294967171,4294967285,4294967172,4294967286,4294967173,4294967287,4294967174,4294967288,4294967175,4294967289,4294967176,4294967177,4294967178,4294967290,4294967179,4294967180,4294967181,4294967291,4294967182,4294967183,4294967184,4294967292,4294967185,4294967186,4294967187,4294967293,4294967188,4294967189,4294967190,4294967191,4294967192,4294967193,4294967194,4294967294,4294967195,4294967196,4294967197,4294967198,4294967199,4294967200,4294967201,4294967295,4294967202,4294967203,4294967204,4294967205,4294967206,4294967207,4294967208,4294967209,4294967210,4294967211,4294967212,4294967213,4294967214,4294967215,4294967216,4294967217,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,127,14,126,13,125,12,124,11,123,10,122,9,121,8,120,7,119,118,117,6,116,115,114,5,113,112,111,4,110,109,108,3,107,106,105,104,103,102,101,2,100,99,98,97,96,95,94,1,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,0}, +{4294967233,4294967234,4294967235,4294967236,4294967237,4294967238,4294967239,4294967240,4294967241,4294967242,4294967243,4294967244,4294967245,4294967246,4294967247,4294967248,4294967249,4294967250,4294967251,4294967252,4294967253,4294967254,4294967255,4294967256,4294967257,4294967258,4294967259,4294967260,4294967261,4294967262,4294967263,4294967264,4294967265,4294967266,4294967267,4294967268,4294967269,4294967270,4294967271,4294967272,4294967273,4294967274,4294967275,4294967276,4294967277,4294967278,4294967279,4294967280,4294967281,4294967168,4294967282,4294967169,4294967283,4294967170,4294967284,4294967171,4294967285,4294967172,4294967286,4294967173,4294967287,4294967174,4294967288,4294967175,4294967176,4294967289,4294967177,4294967178,4294967179,4294967290,4294967180,4294967181,4294967182,4294967291,4294967183,4294967184,4294967185,4294967292,4294967186,4294967187,4294967188,4294967189,4294967190,4294967293,4294967191,4294967192,4294967193,4294967194,4294967195,4294967196,4294967197,4294967294,4294967198,4294967199,4294967200,4294967201,4294967202,4294967203,4294967204,4294967205,4294967206,4294967207,4294967208,4294967295,4294967209,4294967210,4294967211,4294967212,4294967213,4294967214,4294967215,4294967216,4294967217,4294967218,4294967219,4294967220,4294967221,4294967222,4294967223,4294967224,4294967225,4294967226,4294967227,4294967228,4294967229,4294967230,4294967231,4294967232,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,127,14,126,13,125,12,124,11,123,10,122,9,121,8,120,119,7,118,117,116,6,115,114,113,5,112,111,110,4,109,108,107,106,105,3,104,103,102,101,100,99,98,2,97,96,95,94,93,92,91,90,89,88,87,1,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,0}, +{4294967249,4294967250,4294967251,4294967252,4294967253,4294967254,4294967255,4294967256,4294967257,4294967258,4294967259,4294967260,4294967261,4294967262,4294967263,4294967264,4294967265,4294967266,4294967267,4294967268,4294967269,4294967270,4294967271,4294967272,4294967273,4294967274,4294967275,4294967276,4294967277,4294967278,4294967279,4294967280,4294967168,4294967281,4294967169,4294967282,4294967170,4294967283,4294967171,4294967284,4294967172,4294967285,4294967173,4294967286,4294967174,4294967287,4294967175,4294967288,4294967176,4294967177,4294967289,4294967178,4294967179,4294967180,4294967290,4294967181,4294967182,4294967183,4294967291,4294967184,4294967185,4294967186,4294967292,4294967187,4294967188,4294967189,4294967190,4294967191,4294967192,4294967293,4294967193,4294967194,4294967195,4294967196,4294967197,4294967198,4294967199,4294967294,4294967200,4294967201,4294967202,4294967203,4294967204,4294967205,4294967206,4294967207,4294967208,4294967209,4294967210,4294967211,4294967212,4294967295,4294967213,4294967214,4294967215,4294967216,4294967217,4294967218,4294967219,4294967220,4294967221,4294967222,4294967223,4294967224,4294967225,4294967226,4294967227,4294967228,4294967229,4294967230,4294967231,4294967232,4294967233,4294967234,4294967235,4294967236,4294967237,4294967238,4294967239,4294967240,4294967241,4294967242,4294967243,4294967244,4294967245,4294967246,4294967247,4294967248,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,127,15,126,14,125,13,124,12,123,11,122,10,121,9,120,8,119,118,7,117,116,115,6,114,113,112,5,111,110,109,4,108,107,106,105,104,103,3,102,101,100,99,98,97,96,2,95,94,93,92,91,90,89,88,87,86,85,84,83,1,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,0}, +{4294967265,4294967266,4294967267,4294967268,4294967269,4294967270,4294967271,4294967272,4294967273,4294967274,4294967275,4294967276,4294967277,4294967278,4294967279,4294967280,4294967168,4294967281,4294967169,4294967282,4294967170,4294967283,4294967171,4294967284,4294967172,4294967285,4294967173,4294967286,4294967174,4294967287,4294967175,4294967288,4294967176,4294967177,4294967178,4294967289,4294967179,4294967180,4294967181,4294967290,4294967182,4294967183,4294967184,4294967291,4294967185,4294967186,4294967187,4294967292,4294967188,4294967189,4294967190,4294967191,4294967192,4294967193,4294967293,4294967194,4294967195,4294967196,4294967197,4294967198,4294967199,4294967200,4294967294,4294967201,4294967202,4294967203,4294967204,4294967205,4294967206,4294967207,4294967208,4294967209,4294967210,4294967211,4294967212,4294967213,4294967214,4294967295,4294967215,4294967216,4294967217,4294967218,4294967219,4294967220,4294967221,4294967222,4294967223,4294967224,4294967225,4294967226,4294967227,4294967228,4294967229,4294967230,4294967231,4294967232,4294967233,4294967234,4294967235,4294967236,4294967237,4294967238,4294967239,4294967240,4294967241,4294967242,4294967243,4294967244,4294967245,4294967246,4294967247,4294967248,4294967249,4294967250,4294967251,4294967252,4294967253,4294967254,4294967255,4294967256,4294967257,4294967258,4294967259,4294967260,4294967261,4294967262,4294967263,4294967264,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,127,15,126,14,125,13,124,12,123,11,122,10,121,9,120,8,119,118,117,7,116,115,114,6,113,112,111,5,110,109,108,4,107,106,105,104,103,102,3,101,100,99,98,97,96,95,2,94,93,92,91,90,89,88,87,86,85,84,83,82,81,1,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,0}, +{4294967280,4294967281,4294967168,4294967282,4294967169,4294967283,4294967170,4294967284,4294967171,4294967285,4294967172,4294967286,4294967173,4294967287,4294967174,4294967288,4294967175,4294967176,4294967177,4294967289,4294967178,4294967179,4294967180,4294967290,4294967181,4294967182,4294967183,4294967291,4294967184,4294967185,4294967186,4294967292,4294967187,4294967188,4294967189,4294967190,4294967191,4294967192,4294967193,4294967293,4294967194,4294967195,4294967196,4294967197,4294967198,4294967199,4294967200,4294967294,4294967201,4294967202,4294967203,4294967204,4294967205,4294967206,4294967207,4294967208,4294967209,4294967210,4294967211,4294967212,4294967213,4294967214,4294967295,4294967215,4294967216,4294967217,4294967218,4294967219,4294967220,4294967221,4294967222,4294967223,4294967224,4294967225,4294967226,4294967227,4294967228,4294967229,4294967230,4294967231,4294967232,4294967233,4294967234,4294967235,4294967236,4294967237,4294967238,4294967239,4294967240,4294967241,4294967242,4294967243,4294967244,4294967245,4294967246,4294967247,4294967248,4294967249,4294967250,4294967251,4294967252,4294967253,4294967254,4294967255,4294967256,4294967257,4294967258,4294967259,4294967260,4294967261,4294967262,4294967263,4294967264,4294967265,4294967266,4294967267,4294967268,4294967269,4294967270,4294967271,4294967272,4294967273,4294967274,4294967275,4294967276,4294967277,4294967278,4294967279,127,15,126,14,125,13,124,12,123,11,122,10,121,9,120,8,119,118,117,7,116,115,114,6,113,112,111,5,110,109,108,4,107,106,105,104,103,102,101,3,100,99,98,97,96,95,94,2,93,92,91,90,89,88,87,86,85,84,83,82,81,80,1,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,0}, +{4294967288,4294967168,4294967169,4294967289,4294967170,4294967171,4294967172,4294967290,4294967173,4294967174,4294967175,4294967291,4294967176,4294967177,4294967178,4294967292,4294967179,4294967180,4294967181,4294967182,4294967183,4294967184,4294967185,4294967293,4294967186,4294967187,4294967188,4294967189,4294967190,4294967191,4294967192,4294967294,4294967193,4294967194,4294967195,4294967196,4294967197,4294967198,4294967199,4294967200,4294967201,4294967202,4294967203,4294967204,4294967205,4294967206,4294967207,4294967295,4294967208,4294967209,4294967210,4294967211,4294967212,4294967213,4294967214,4294967215,4294967216,4294967217,4294967218,4294967219,4294967220,4294967221,4294967222,4294967223,4294967224,4294967225,4294967226,4294967227,4294967228,4294967229,4294967230,4294967231,4294967232,4294967233,4294967234,4294967235,4294967236,4294967237,4294967238,4294967239,4294967240,4294967241,4294967242,4294967243,4294967244,4294967245,4294967246,4294967247,4294967248,4294967249,4294967250,4294967251,4294967252,4294967253,4294967254,4294967255,4294967256,4294967257,4294967258,4294967259,4294967260,4294967261,4294967262,4294967263,4294967264,4294967265,4294967266,4294967267,4294967268,4294967269,4294967270,4294967271,4294967272,4294967273,4294967274,4294967275,4294967276,4294967277,4294967278,4294967279,4294967280,4294967281,4294967282,4294967283,4294967284,4294967285,4294967286,4294967287,127,126,125,7,124,123,122,6,121,120,119,5,118,117,116,4,115,114,113,112,111,110,109,3,108,107,106,105,104,103,102,2,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,1,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,0}, +{4294967292,4294967168,4294967169,4294967170,4294967171,4294967172,4294967173,4294967293,4294967174,4294967175,4294967176,4294967177,4294967178,4294967179,4294967180,4294967294,4294967181,4294967182,4294967183,4294967184,4294967185,4294967186,4294967187,4294967188,4294967189,4294967190,4294967191,4294967192,4294967193,4294967194,4294967195,4294967295,4294967196,4294967197,4294967198,4294967199,4294967200,4294967201,4294967202,4294967203,4294967204,4294967205,4294967206,4294967207,4294967208,4294967209,4294967210,4294967211,4294967212,4294967213,4294967214,4294967215,4294967216,4294967217,4294967218,4294967219,4294967220,4294967221,4294967222,4294967223,4294967224,4294967225,4294967226,4294967227,4294967228,4294967229,4294967230,4294967231,4294967232,4294967233,4294967234,4294967235,4294967236,4294967237,4294967238,4294967239,4294967240,4294967241,4294967242,4294967243,4294967244,4294967245,4294967246,4294967247,4294967248,4294967249,4294967250,4294967251,4294967252,4294967253,4294967254,4294967255,4294967256,4294967257,4294967258,4294967259,4294967260,4294967261,4294967262,4294967263,4294967264,4294967265,4294967266,4294967267,4294967268,4294967269,4294967270,4294967271,4294967272,4294967273,4294967274,4294967275,4294967276,4294967277,4294967278,4294967279,4294967280,4294967281,4294967282,4294967283,4294967284,4294967285,4294967286,4294967287,4294967288,4294967289,4294967290,4294967291,127,126,125,124,123,122,121,3,120,119,118,117,116,115,114,2,113,112,111,110,109,108,107,106,105,104,103,102,101,100,99,1,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,0}, +{4294967294,4294967168,4294967169,4294967170,4294967171,4294967172,4294967173,4294967174,4294967175,4294967176,4294967177,4294967178,4294967179,4294967180,4294967181,4294967295,4294967182,4294967183,4294967184,4294967185,4294967186,4294967187,4294967188,4294967189,4294967190,4294967191,4294967192,4294967193,4294967194,4294967195,4294967196,4294967197,4294967198,4294967199,4294967200,4294967201,4294967202,4294967203,4294967204,4294967205,4294967206,4294967207,4294967208,4294967209,4294967210,4294967211,4294967212,4294967213,4294967214,4294967215,4294967216,4294967217,4294967218,4294967219,4294967220,4294967221,4294967222,4294967223,4294967224,4294967225,4294967226,4294967227,4294967228,4294967229,4294967230,4294967231,4294967232,4294967233,4294967234,4294967235,4294967236,4294967237,4294967238,4294967239,4294967240,4294967241,4294967242,4294967243,4294967244,4294967245,4294967246,4294967247,4294967248,4294967249,4294967250,4294967251,4294967252,4294967253,4294967254,4294967255,4294967256,4294967257,4294967258,4294967259,4294967260,4294967261,4294967262,4294967263,4294967264,4294967265,4294967266,4294967267,4294967268,4294967269,4294967270,4294967271,4294967272,4294967273,4294967274,4294967275,4294967276,4294967277,4294967278,4294967279,4294967280,4294967281,4294967282,4294967283,4294967284,4294967285,4294967286,4294967287,4294967288,4294967289,4294967290,4294967291,4294967292,4294967293,127,126,125,124,123,122,121,120,119,118,117,116,115,114,113,1,112,111,110,109,108,107,106,105,104,103,102,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,0}, +{4294967295,4294967168,4294967169,4294967170,4294967171,4294967172,4294967173,4294967174,4294967175,4294967176,4294967177,4294967178,4294967179,4294967180,4294967181,4294967182,4294967183,4294967184,4294967185,4294967186,4294967187,4294967188,4294967189,4294967190,4294967191,4294967192,4294967193,4294967194,4294967195,4294967196,4294967197,4294967198,4294967199,4294967200,4294967201,4294967202,4294967203,4294967204,4294967205,4294967206,4294967207,4294967208,4294967209,4294967210,4294967211,4294967212,4294967213,4294967214,4294967215,4294967216,4294967217,4294967218,4294967219,4294967220,4294967221,4294967222,4294967223,4294967224,4294967225,4294967226,4294967227,4294967228,4294967229,4294967230,4294967231,4294967232,4294967233,4294967234,4294967235,4294967236,4294967237,4294967238,4294967239,4294967240,4294967241,4294967242,4294967243,4294967244,4294967245,4294967246,4294967247,4294967248,4294967249,4294967250,4294967251,4294967252,4294967253,4294967254,4294967255,4294967256,4294967257,4294967258,4294967259,4294967260,4294967261,4294967262,4294967263,4294967264,4294967265,4294967266,4294967267,4294967268,4294967269,4294967270,4294967271,4294967272,4294967273,4294967274,4294967275,4294967276,4294967277,4294967278,4294967279,4294967280,4294967281,4294967282,4294967283,4294967284,4294967285,4294967286,4294967287,4294967288,4294967289,4294967290,4294967291,4294967292,4294967293,4294967294,127,126,125,124,123,122,121,120,119,118,117,116,115,114,113,112,111,110,109,108,107,106,105,104,103,102,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0} +};*/ + +uchar ulaw_outward[13][256] = { +{127,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,255,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128}, +{112,114,116,118,120,122,124,126,127,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,113,115,117,119,121,123,125,255,253,251,249,247,245,243,241,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,254,252,250,248,246,244,242,240}, +{96,98,100,102,104,106,108,110,112,113,114,116,117,118,120,121,122,124,125,126,127,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,97,99,101,103,105,107,109,111,115,119,123,255,251,247,243,239,237,235,233,231,229,227,225,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,254,253,252,250,249,248,246,245,244,242,241,240,238,236,234,232,230,228,226,224}, +{80,82,84,86,88,90,92,94,96,97,98,100,101,102,104,105,106,108,109,110,112,113,114,115,116,117,118,120,121,122,123,124,125,126,127,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,81,83,85,87,89,91,93,95,99,103,107,111,119,255,247,239,235,231,227,223,221,219,217,215,213,211,209,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,254,253,252,251,250,249,248,246,245,244,243,242,241,240,238,237,236,234,233,232,230,229,228,226,225,224,222,220,218,216,214,212,210,208}, +{64,66,68,70,72,74,76,78,80,81,82,84,85,86,88,89,90,92,93,94,96,97,98,99,100,101,102,104,105,106,107,108,109,110,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,65,67,69,71,73,75,77,79,83,87,91,95,103,111,255,239,231,223,219,215,211,207,205,203,201,199,197,195,193,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,238,237,236,235,234,233,232,230,229,228,227,226,225,224,222,221,220,218,217,216,214,213,212,210,209,208,206,204,202,200,198,196,194,192}, +{49,51,53,55,57,59,61,63,64,66,67,68,70,71,72,74,75,76,78,79,80,81,82,84,85,86,87,88,89,90,92,93,94,95,96,97,98,99,100,101,102,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,50,52,54,56,58,60,62,65,69,73,77,83,91,103,255,231,219,211,205,201,197,193,190,188,186,184,182,180,178,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,230,229,228,227,226,225,224,223,222,221,220,218,217,216,215,214,213,212,210,209,208,207,206,204,203,202,200,199,198,196,195,194,192,191,189,187,185,183,181,179,177}, +{32,34,36,38,40,42,44,46,48,49,51,52,53,55,56,57,59,60,61,63,64,65,66,67,68,70,71,72,73,74,75,76,78,79,80,81,82,83,84,85,86,87,88,89,90,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,33,35,37,39,41,43,45,47,50,54,58,62,69,77,91,255,219,205,197,190,186,182,178,175,173,171,169,167,165,163,161,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,218,217,216,215,214,213,212,211,210,209,208,207,206,204,203,202,201,200,199,198,196,195,194,193,192,191,189,188,187,185,184,183,181,180,179,177,176,174,172,170,168,166,164,162,160}, +{16,18,20,22,24,26,28,30,32,33,34,36,37,38,40,41,42,44,45,46,48,49,50,51,52,53,55,56,57,58,59,60,61,63,64,65,66,67,68,69,70,71,72,73,74,75,76,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,17,19,21,23,25,27,29,31,35,39,43,47,54,62,77,255,205,190,182,175,171,167,163,159,157,155,153,151,149,147,145,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,204,203,202,201,200,199,198,197,196,195,194,193,192,191,189,188,187,186,185,184,183,181,180,179,178,177,176,174,173,172,170,169,168,166,165,164,162,161,160,158,156,154,152,150,148,146,144}, +{2,4,6,8,10,12,14,16,17,18,20,21,22,24,25,26,28,29,30,32,33,34,35,36,37,38,40,41,42,43,44,45,46,48,49,50,51,52,53,54,55,56,57,58,59,60,61,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,0,1,3,5,7,9,11,13,15,19,23,27,31,39,47,62,255,190,175,167,159,155,151,147,143,141,139,137,135,133,131,129,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,189,188,187,186,185,184,183,182,181,180,179,178,177,176,174,173,172,171,170,169,168,166,165,164,163,162,161,160,158,157,156,154,153,152,150,149,148,146,145,144,142,140,138,136,134,132,130,128}, +{1,2,4,5,6,8,9,10,12,13,14,16,17,18,19,20,21,22,24,25,26,27,28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,0,3,7,11,15,23,31,47,255,175,159,151,143,139,135,131,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,158,157,156,155,154,153,152,150,149,148,147,146,145,144,142,141,140,138,137,136,134,133,132,130,129,128}, +{1,2,3,4,5,6,8,9,10,11,12,13,14,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,0,7,15,31,255,159,143,135,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,142,141,140,139,138,137,136,134,133,132,131,130,129,128}, +{1,2,3,4,5,6,7,8,9,10,11,12,13,14,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,0,15,255,143,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128}, +{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,0,255,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128} +}; diff --git a/plugins/shn/convert.c b/plugins/shn/convert.c new file mode 100644 index 00000000..c11d86c0 --- /dev/null +++ b/plugins/shn/convert.c @@ -0,0 +1,42 @@ +/* convert.c - functions to convert little-endian data to endian of host + * Copyright (C) 2000-2007 Jason Jordan <shnutils@freeshell.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * $Id: convert.c,v 1.9 2007/03/23 05:49:48 jason Exp $ + */ + +#include <stdlib.h> +#include "shorten.h" + +ulong shn_uchar_to_ulong_le(uchar *buf) +/* converts 4 bytes stored in little-endian format to a ulong */ +{ + return (ulong)((buf[3] << 24) + (buf[2] << 16) + (buf[1] << 8) + buf[0]); +} + +slong shn_uchar_to_slong_le(uchar *buf) +/* converts 4 bytes stored in little-endian format to an slong */ +{ + return (slong)shn_uchar_to_ulong_le(buf); +} + +ushort shn_uchar_to_ushort_le(uchar *buf) +/* converts 4 bytes stored in little-endian format to a ushort */ +{ + return (ushort)((buf[1] << 8) + buf[0]); +} diff --git a/plugins/shn/misc.c b/plugins/shn/misc.c new file mode 100644 index 00000000..759bb1d1 --- /dev/null +++ b/plugins/shn/misc.c @@ -0,0 +1,151 @@ +/* misc.c - miscellaneous functions + * Copyright (C) 2000-2007 Jason Jordan <shnutils@freeshell.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * $Id: misc.c,v 1.14 2007/03/23 05:49:48 jason Exp $ + */ + +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include "shorten.h" + +void shn_snprintf(char *dest,int maxlen,char *formatstr, ...) +/* acts like snprintf, but makes 100% sure the string is NULL-terminated */ +{ + va_list args; + + va_start(args,formatstr); + + shn_vsnprintf(dest,maxlen,formatstr,args); + + dest[maxlen-1] = 0; + + va_end(args); +} + +int shn_filename_contains_a_dot(const char *filename) +{ + char *slash,*dot; + + dot = strrchr(filename,'.'); + if (!dot) + return 0; + + slash = strrchr(filename,'/'); + if (!slash) + return 1; + + if (slash < dot) + return 1; + else + return 0; +} + +char *shn_get_base_filename(const char *filename) +{ + const char *b,*e,*p; + char *base; + + b = strrchr(filename,'/'); + + if (b) + b++; + else + b = filename; + + e = strrchr(filename,'.'); + + if (e < b) + e = filename + strlen(filename); + + if (NULL == (base = malloc((e - b + 1) * sizeof(char)))) + { + shn_debug("Could not allocate memory for base filename"); + return NULL; + } + + for (p=b;p<e;p++) + *(base + (p - b)) = *p; + + *(base + (p - b)) = '\0'; + + return base; +} + +char *shn_get_base_directory(const char *filename) +{ + const char *e,*p; + char *base; + + e = strrchr(filename,'/'); + + if (!e) + e = filename; + + if (NULL == (base = malloc((e - filename + 1) * sizeof(char)))) + { + shn_debug("Could not allocate memory for base directory"); + return NULL; + } + + for (p=filename;p<e;p++) + *(base + (p - filename)) = *p; + + *(base + (p - filename)) = '\0'; + + return base; +} + +void shn_length_to_str(shn_file *info) +/* converts length of file to a string in m:ss or m:ss.ff format */ +{ + ulong newlength,rem1,rem2,frames,ms; + double tmp; + + if (PROB_NOT_CD(info->wave_header)) { + newlength = (ulong)info->wave_header.exact_length; + + tmp = info->wave_header.exact_length - (double)((ulong)info->wave_header.exact_length); + ms = (ulong)((tmp * 1000.0) + 0.5); + + if (1000 == ms) { + ms = 0; + newlength++; + } + + shn_snprintf(info->wave_header.m_ss,16,"%lu:%02lu.%03lu",newlength/60,newlength%60,ms); + } + else { + newlength = info->wave_header.length; + + rem1 = info->wave_header.data_size % CD_RATE; + rem2 = rem1 % CD_BLOCK_SIZE; + + frames = rem1 / CD_BLOCK_SIZE; + if (rem2 >= (CD_BLOCK_SIZE / 2)) + frames++; + + if (frames == CD_BLOCKS_PER_SEC) { + frames = 0; + newlength++; + } + + shn_snprintf(info->wave_header.m_ss,16,"%lu:%02lu.%02lu",newlength/60,newlength%60,frames); + } +} diff --git a/plugins/shn/output.c b/plugins/shn/output.c new file mode 100644 index 00000000..1c1f9092 --- /dev/null +++ b/plugins/shn/output.c @@ -0,0 +1,99 @@ +/* output.c - functions for message and error output + * Copyright (C) 2000-2007 Jason Jordan <shnutils@freeshell.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * $Id: output.c,v 1.11 2007/03/23 05:49:48 jason Exp $ + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include "shorten.h" +#include "shn.h" + +void print_lines(char *prefix,char *message) +{ + char *head, *tail; + + head = tail = message; + while (*head != '\0') { + if (*head == '\n') { + *head = '\0'; + fprintf(stderr,"%s%s\n",prefix,tail); + tail = head + 1; + } + head++; + } + fprintf(stderr,"%s%s\n",prefix,tail); +} + +void shn_error(char *msg, ...) +{ + va_list args; + char msgbuf[BUF_SIZE]; + + va_start(args,msg); + + shn_vsnprintf(msgbuf,BUF_SIZE,msg,args); + + switch (shn_cfg.error_output_method) { + case ERROR_OUTPUT_STDERR: + print_lines(PACKAGE ": ",msgbuf); + break; +// case ERROR_OUTPUT_WINDOW: +// shn_message_box(msgbuf); +// break; + default: + if (0 != shn_cfg.verbose) + print_lines(PACKAGE " [error]: ",msgbuf); + } + + va_end(args); +} + +void shn_debug(char *msg, ...) +{ + va_list args; + char msgbuf[BUF_SIZE]; + + va_start(args,msg); + + shn_vsnprintf(msgbuf,BUF_SIZE,msg,args); + + if (0 != shn_cfg.verbose) + print_lines(PACKAGE " [debug]: ",msgbuf); + + va_end(args); +} + +void shn_error_fatal(shn_file *this_shn,char *complaint, ...) +{ + va_list args; + + va_start(args,complaint); + + if (NULL != this_shn) { + if (0 == this_shn->vars.fatal_error) { + this_shn->vars.fatal_error = 1; + this_shn->vars.going = 0; + shn_vsnprintf(this_shn->vars.fatal_error_msg,BUF_SIZE,complaint,args); + } + } + + va_end(args); +} diff --git a/plugins/shn/seek.c b/plugins/shn/seek.c new file mode 100644 index 00000000..a0eb3af4 --- /dev/null +++ b/plugins/shn/seek.c @@ -0,0 +1,274 @@ +/* seek.c - functions related to real-time seeking + * Copyright (C) 2000-2007 Jason Jordan <shnutils@freeshell.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * $Id: seek.c,v 1.18 2007/03/23 05:49:48 jason Exp $ + */ + +#include <stdlib.h> +#include "shorten.h" +#include "shn.h" + +#define ID3V1_TAG_SIZE 128 + +shn_seek_entry *shn_seek_entry_search(shn_seek_entry *table,ulong goal,ulong min,ulong max,ulong resolution) +{ + ulong med = (min + max) / 2; + shn_seek_entry *middle = table + med; + ulong sample = shn_uchar_to_ulong_le(middle->data); + + shn_debug("Examining seek table entry %lu with sample %lu (min/max = %lu/%lu, goal sample is %lu, resolution is %lu samples)",med,sample,min,max,goal,resolution); + + if (goal < sample) + return shn_seek_entry_search(table,goal,min,med-1,resolution); + if (goal > sample + resolution) + return shn_seek_entry_search(table,goal,med+1,max,resolution); + return middle; +} + +int load_separate_seek_table_generic(char *filename,shn_file *this_shn) +{ + FILE *f; + slong seek_table_len; + + shn_debug("Looking for seek table in separate file: '%s'",filename); + + if (!(f=fopen(filename,"rb"))) + { + return 0; + } + + fseek(f,0,SEEK_END); + seek_table_len = (slong)ftell(f) - SEEK_HEADER_SIZE; + fseek(f,0,SEEK_SET); + + if (fread((void *)this_shn->seek_header.data,1,SEEK_HEADER_SIZE,f) == SEEK_HEADER_SIZE) + { + this_shn->seek_header.version = (slong)shn_uchar_to_ulong_le(this_shn->seek_header.data+4); + this_shn->seek_header.shnFileSize = shn_uchar_to_ulong_le(this_shn->seek_header.data+8); + if (memcmp(this_shn->seek_header.data,SEEK_HEADER_SIGNATURE,strlen(SEEK_HEADER_SIGNATURE)) == 0) + { + if (this_shn->seek_header.shnFileSize != this_shn->wave_header.actual_size) + { + shn_debug("warning: Seek table expected .shn file size %lu differs from actual .shn file size %lu - seek table might not belong to this file", + this_shn->seek_header.shnFileSize,this_shn->wave_header.actual_size); + } + + if ((this_shn->seek_table = malloc(seek_table_len))) + { + if (fread((void *)this_shn->seek_table,1,seek_table_len,f) == seek_table_len) + { + shn_debug("Successfully loaded seek table in separate file: '%s'",filename); + + this_shn->vars.seek_table_entries = seek_table_len / SEEK_ENTRY_SIZE; + + if (this_shn->vars.seek_table_entries > 1) + this_shn->vars.seek_resolution = shn_uchar_to_ulong_le(this_shn->seek_table->data+SEEK_ENTRY_SIZE); + else + this_shn->vars.seek_resolution = SEEK_RESOLUTION; + + fclose(f); + + return 1; + } + } + } + } + + fclose(f); + return 0; +} + +int load_appended_seek_table(shn_file *this_shn,const char *filename,long bytes_from_end) +{ + switch (bytes_from_end) + { + case 0: + shn_debug("Looking for seek table appended to file: '%s'",filename); + break; + case ID3V1_TAG_SIZE: + shn_debug("Looking for seek table hidden behind an ID3v1 tag at the end of file: '%s'",filename); + break; + default: + shn_debug("Looking for seek table located %ld bytes from the end of file: '%s'",bytes_from_end,filename); + break; + } + + deadbeef->fseek(this_shn->vars.fd,-(SEEK_TRAILER_SIZE+bytes_from_end),SEEK_END); + if (deadbeef->fread((void *)this_shn->seek_trailer.data,1,SEEK_TRAILER_SIZE,this_shn->vars.fd) == SEEK_TRAILER_SIZE) + { + this_shn->seek_trailer.seekTableSize = shn_uchar_to_ulong_le(this_shn->seek_trailer.data); + if (memcmp(this_shn->seek_trailer.data+4,SEEK_TRAILER_SIGNATURE,strlen(SEEK_TRAILER_SIGNATURE)) == 0) + { + deadbeef->fseek(this_shn->vars.fd,-(this_shn->seek_trailer.seekTableSize+bytes_from_end),SEEK_END); + this_shn->seek_trailer.seekTableSize -= (SEEK_HEADER_SIZE + SEEK_TRAILER_SIZE); + if (deadbeef->fread((void *)this_shn->seek_header.data,1,SEEK_HEADER_SIZE,this_shn->vars.fd) == SEEK_HEADER_SIZE) + { + this_shn->seek_header.version = (slong)shn_uchar_to_ulong_le(this_shn->seek_header.data+4); + this_shn->seek_header.shnFileSize = shn_uchar_to_ulong_le(this_shn->seek_header.data+8); + if ((this_shn->seek_table = malloc(this_shn->seek_trailer.seekTableSize))) + { + if (deadbeef->fread((void *)this_shn->seek_table,1,this_shn->seek_trailer.seekTableSize,this_shn->vars.fd) == this_shn->seek_trailer.seekTableSize) + { + shn_debug("Successfully loaded seek table appended to file: '%s'",filename); + + this_shn->vars.seek_table_entries = this_shn->seek_trailer.seekTableSize / SEEK_ENTRY_SIZE; + + if (this_shn->vars.seek_table_entries > 1) + this_shn->vars.seek_resolution = shn_uchar_to_ulong_le(this_shn->seek_table->data+SEEK_ENTRY_SIZE); + else + this_shn->vars.seek_resolution = SEEK_RESOLUTION; + + return 1; + } + } + } + } + } + + return 0; +} + +int load_separate_seek_table_samedir(shn_file *this_shn,const char *filename) +{ + char *altfilename,*basefile,*basedir; + + if (!(basefile = shn_get_base_filename(filename))) + { + return 0; + } + + if (!(basedir = shn_get_base_directory(filename))) + { + free(basefile); + return 0; + } + + if (!(altfilename = malloc(strlen(basedir)+strlen(basefile)+sizeof(SEEK_SUFFIX)+3))) + { + shn_debug("Could not allocate memory for same dir filename"); + free(basefile); + free(basedir); + return 0; + } + + sprintf(altfilename,"%s/%s.%s",basedir,basefile,SEEK_SUFFIX); + + free(basefile); + free(basedir); + + if (load_separate_seek_table_generic(altfilename,this_shn)) + { + free(altfilename); + return 1; + } + + free(altfilename); + return 0; +} + +int load_separate_seek_table_relative(shn_file *this_shn,const char *filename) +{ + char *altfilename,*basefile,*basedir; + + if (0 == strcmp(shn_cfg.relative_seek_tables_path,"")) + return 0; + + if (!(basefile = shn_get_base_filename(filename))) + { + return 0; + } + + if (!(basedir = shn_get_base_directory(filename))) + { + free(basefile); + return 0; + } + + if (!(altfilename = malloc(strlen(basedir)+strlen(shn_cfg.relative_seek_tables_path)+strlen(basefile)+sizeof(SEEK_SUFFIX)+4))) + { + shn_debug("Could not allocate memory for absolute filename"); + free(basefile); + free(basedir); + return 0; + } + + sprintf(altfilename,"%s/%s/%s.%s",basedir,shn_cfg.relative_seek_tables_path,basefile,SEEK_SUFFIX); + + free(basefile); + free(basedir); + + if (load_separate_seek_table_generic(altfilename,this_shn)) + { + free(altfilename); + return 1; + } + + free(altfilename); + return 0; +} + +int load_separate_seek_table_absolute(shn_file *this_shn,const char *filename) +{ + char *altfilename,*basefile; + + if (!(basefile = shn_get_base_filename(filename))) + { + return 0; + } + + if (!(altfilename = malloc(strlen(shn_cfg.seek_tables_path)+strlen(basefile)+sizeof(SEEK_SUFFIX)+3))) + { + shn_debug("Could not allocate memory for same dir filename"); + free(basefile); + return 0; + } + + sprintf(altfilename,"%s/%s.%s",shn_cfg.seek_tables_path,basefile,SEEK_SUFFIX); + + free(basefile); + + if (load_separate_seek_table_generic(altfilename,this_shn)) + { + free(altfilename); + return 1; + } + + free(altfilename); + return 0; +} + +void shn_load_seek_table(shn_file *this_shn,const char *filename) +{ + if (load_appended_seek_table(this_shn,filename,0)) + return; + + if (load_appended_seek_table(this_shn,filename,ID3V1_TAG_SIZE)) + return; + + if (load_separate_seek_table_samedir(this_shn,filename)) + return; + + if (load_separate_seek_table_relative(this_shn,filename)) + return; + + if (load_separate_seek_table_absolute(this_shn,filename)) + return; + + shn_debug("Could not find any seek tables"); +} diff --git a/plugins/shn/shn.c b/plugins/shn/shn.c new file mode 100644 index 00000000..17d2e231 --- /dev/null +++ b/plugins/shn/shn.c @@ -0,0 +1,1798 @@ +/* + DeaDBeeF - ultimate music player for GNU/Linux systems with X11 + Copyright (C) 2009-2010 Alexey Yakovenko <waker@users.sourceforge.net> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +// based on xmms-shn, http://www.etree.org/shnutils/xmms-shn/ + +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include "shorten.h" +#include "../../deadbeef.h" +#include "bitshift.h" + +#define trace(...) { fprintf(stderr, __VA_ARGS__); } +//#define trace(fmt,...) + +static DB_decoder_t plugin; +DB_functions_t *deadbeef; + +shn_file *load_shn(const char *filename); +static void shn_play(char *); +static void shn_stop(void); +static int shn_get_time(void); +static void shn_get_file_info(char *,char **,int *); +static void shn_display_file_info(char *); + +typedef struct { + DB_fileinfo_t info; + shn_file *shnfile; + + slong **buffer, **offset; + slong lpcqoffset; + int version, bitshift; + int ftype; + char *magic; + int blocksize, nchan; + int i, chan, nwrap, nskip; + int *qlpc, maxnlpc, nmean; + int cmd; + int internal_ftype; + int blk_size; + int cklen; + uchar tmp; + + int currentsample; + int startsample; + int endsample; +} shn_fileinfo_t; + +shn_config shn_cfg; + +DB_fileinfo_t * +shn_open (void) { + DB_fileinfo_t *_info = malloc (sizeof (shn_fileinfo_t)); + shn_fileinfo_t *info = (shn_fileinfo_t *)_info; + memset (info, 0, sizeof (shn_fileinfo_t)); + return _info; +} + +int +ddb_getc (DB_FILE *fp) { + uint8_t c; + if (deadbeef->fread (&c, 1, 1, fp) != 1) { + return EOF; + } + return (int)c; +} + +int init_decode_state(shn_file *this_shn) +{ + if (this_shn->decode_state) + { + if (this_shn->decode_state->getbuf) + { + free(this_shn->decode_state->getbuf); + this_shn->decode_state->getbuf = NULL; + } + + if (this_shn->decode_state->writebuf) + { + free(this_shn->decode_state->writebuf); + this_shn->decode_state->writebuf = NULL; + } + + if (this_shn->decode_state->writefub) + { + free(this_shn->decode_state->writefub); + this_shn->decode_state->writefub = NULL; + } + + free(this_shn->decode_state); + this_shn->decode_state = NULL; + } + + if (!(this_shn->decode_state = malloc(sizeof(shn_decode_state)))) + { + shn_debug("Could not allocate memory for decode state data structure"); + return 0; + } + + this_shn->decode_state->getbuf = NULL; + this_shn->decode_state->getbufp = NULL; + this_shn->decode_state->nbitget = 0; + this_shn->decode_state->nbyteget = 0; + this_shn->decode_state->gbuffer = 0; + this_shn->decode_state->writebuf = NULL; + this_shn->decode_state->writefub = NULL; + this_shn->decode_state->nwritebuf = 0; + + this_shn->vars.bytes_in_buf = 0; + + return 1; +} + +int +shn_init_decoder (shn_fileinfo_t *info) { + int version = FORMAT_VERSION; + info->ftype = TYPE_EOF; + info->magic = MAGIC; + info->blocksize = DEFAULT_BLOCK_SIZE; + info->nchan = DEFAULT_NCHAN; + info->nskip = DEFAULT_NSKIP; + info->maxnlpc = DEFAULT_MAXNLPC; + info->nmean = UNDEFINED_UINT; + + info->shnfile->vars.bytes_in_buf = 0; + if (!init_decode_state(info->shnfile)) { + trace ("shn: init_decode_state failed\n"); + return -1; + } + info->shnfile->vars.going = 1; + + info->blk_size = 512 * (info->shnfile->wave_header.bits_per_sample / 8) * info->shnfile->wave_header.channels; + + /* read magic number */ +#ifdef STRICT_FORMAT_COMPATABILITY + if(FORMAT_VERSION < 2) + { + for(i = 0; i < strlen(magic); i++) + if(getc_exit(this_shn->vars.fd) != magic[i]) { + shn_error_fatal(this_shn,"Bad magic number"); + goto exit_thread; + } + + /* get version number */ + version = getc_exit(this_shn->vars.fd); + } + else +#endif /* STRICT_FORMAT_COMPATABILITY */ + { + int nscan = 0; + + version = MAX_VERSION + 1; + while(version > MAX_VERSION) + { + int byte = ddb_getc(info->shnfile->vars.fd); + if(byte == EOF) { + shn_error_fatal(info->shnfile,"No magic number"); + trace ("shn_init: no magic number\n"); + return -1; + } + if(info->magic[nscan] != '\0' && byte == info->magic[nscan]) { + nscan++; + } + else { + if(info->magic[nscan] == '\0' && byte <= MAX_VERSION) + version = byte; + else + { + if(byte == info->magic[0]) + nscan = 1; + else + { + nscan = 0; + } + version = MAX_VERSION + 1; + } + } + } + } + + /* check version number */ + if(version > MAX_SUPPORTED_VERSION) { + shn_error_fatal(info->shnfile,"Can't decode version %d", version); + trace ("shn_init: can't decode version %d\n", version); + return -1; + } + + /* set up the default nmean, ignoring the command line state */ + info->nmean = (version < 2) ? DEFAULT_V0NMEAN : DEFAULT_V2NMEAN; + + /* initialise the variable length file read for the compressed stream */ + trace ("decode_state=%p\n", info->shnfile->decode_state); + var_get_init(info->shnfile); + if (info->shnfile->vars.fatal_error) { + trace ("var_get_init failed\n"); + return -1; + } + + /* initialise the fixed length file write for the uncompressed stream */ + fwrite_type_init(info->shnfile); + + /* get the internal file type */ + info->internal_ftype = UINT_GET(TYPESIZE, info->shnfile); + trace ("internal_ftype=%d\n", info->internal_ftype); + + /* has the user requested a change in file type? */ + if(info->internal_ftype != info->ftype) { + if(info->ftype == TYPE_EOF) { + info->ftype = info->internal_ftype; /* no problems here */ + } + else { /* check that the requested conversion is valid */ + if(info->internal_ftype == TYPE_AU1 || info->internal_ftype == TYPE_AU2 || + info->internal_ftype == TYPE_AU3 || info->ftype == TYPE_AU1 || info->ftype == TYPE_AU2 || info->ftype == TYPE_AU3) { + shn_error_fatal(info->shnfile,"Not able to perform requested output format conversion"); + trace ("shn_init_decoder: Not able to perform requested output format conversion\n"); + return -1; + } + } + trace ("ftype=%d\n", info->ftype); + } + + info->nchan = UINT_GET(CHANSIZE, info->shnfile); + + /* get blocksize if version > 0 */ + if(version > 0) + { + int byte; + info->blocksize = UINT_GET((int) (log((double) DEFAULT_BLOCK_SIZE) / M_LN2),info->shnfile); + info->maxnlpc = UINT_GET(LPCQSIZE, info->shnfile); + info->nmean = UINT_GET(0, info->shnfile); + info->nskip = UINT_GET(NSKIPSIZE, info->shnfile); + for(int i = 0; i < info->nskip; i++) + { + byte = uvar_get(XBYTESIZE,info->shnfile); + } + } + else + info->blocksize = DEFAULT_BLOCK_SIZE; + + info->nwrap = MAX(NWRAP, info->maxnlpc); + + /* grab some space for the input buffer */ + info->buffer = long2d((ulong) info->nchan, (ulong) (info->blocksize + info->nwrap),info->shnfile); + if (info->shnfile->vars.fatal_error) { + trace ("failed to alloc buffer\n"); + return -1; + } + info->offset = long2d((ulong) info->nchan, (ulong) MAX(1, info->nmean),info->shnfile); + if (info->shnfile->vars.fatal_error) { + if (info->buffer) { + free(info->buffer); + info->buffer = NULL; + } + trace ("failed to alloc offset\n"); + return -1; + } + + for(info->chan = 0; info->chan < info->nchan; info->chan++) + { + for(int i = 0; i < info->nwrap; i++) + info->buffer[info->chan][i] = 0; + info->buffer[info->chan] += info->nwrap; + } + + if(info->maxnlpc > 0) { + info->qlpc = (int*) pmalloc((ulong) (info->maxnlpc * sizeof(*info->qlpc)),info->shnfile); + if (info->shnfile->vars.fatal_error) { + if (info->buffer) { + free(info->buffer); + info->buffer = NULL; + } + if (info->offset) { + free(info->offset); + info->offset = NULL; + } + trace ("failed to alloc qlpc\n"); + return -1; + } + } + + if(version > 1) + info->lpcqoffset = V2LPCQOFFSET; + + init_offset (info->offset, info->nchan, MAX(1, info->nmean), info->internal_ftype); + + /* get commands from file and execute them */ + info->chan = 0; + info->version = version; + trace ("shn_init: success\n"); + return 0; +} + +int +shn_init(DB_fileinfo_t *_info, DB_playItem_t *it) { + shn_fileinfo_t *info = (shn_fileinfo_t *)_info; + + shn_cfg.error_output_method = ERROR_OUTPUT_DEVNULL; + shn_cfg.error_output_method_config_name = "error_output_method"; + shn_cfg.seek_tables_path = NULL; + shn_cfg.seek_tables_path_config_name = "seek_tables_path"; + shn_cfg.relative_seek_tables_path = NULL; + shn_cfg.relative_seek_tables_path_config_name = "relative_seek_tables_path"; + shn_cfg.verbose = 0; + shn_cfg.verbose_config_name = "verbose"; + shn_cfg.swap_bytes = 0; + shn_cfg.swap_bytes_config_name = "swap_bytes"; + shn_cfg.load_textfiles = 0; + shn_cfg.load_textfiles_config_name = "load_textfiles"; + shn_cfg.textfile_extensions = NULL; + shn_cfg.textfile_extensions_config_name = "textfile_extensions"; + +// {{{ xmms config reader +#if 0 + filename = g_strconcat(g_get_home_dir(), "/.xmms/config", NULL); + if ((cfg = xmms_cfg_open_file(filename)) != 0) + { + xmms_cfg_read_int(cfg, XMMS_SHN_VERSION_TAG, shn_cfg.error_output_method_config_name, &shn_cfg.error_output_method); + xmms_cfg_read_boolean(cfg, XMMS_SHN_VERSION_TAG, shn_cfg.verbose_config_name, &shn_cfg.verbose); + if (!xmms_cfg_read_string(cfg, XMMS_SHN_VERSION_TAG, shn_cfg.seek_tables_path_config_name, &shn_cfg.seek_tables_path)) + shn_cfg.seek_tables_path = g_strdup(g_get_home_dir()); + if (!xmms_cfg_read_string(cfg, XMMS_SHN_VERSION_TAG, shn_cfg.relative_seek_tables_path_config_name, &shn_cfg.relative_seek_tables_path)) + shn_cfg.relative_seek_tables_path = g_strdup(""); + xmms_cfg_read_boolean(cfg, XMMS_SHN_VERSION_TAG, shn_cfg.swap_bytes_config_name, &shn_cfg.swap_bytes); + xmms_cfg_read_boolean(cfg, XMMS_SHN_VERSION_TAG, shn_cfg.load_textfiles_config_name, &shn_cfg.load_textfiles); + if (!xmms_cfg_read_string(cfg, XMMS_SHN_VERSION_TAG, shn_cfg.textfile_extensions_config_name, &shn_cfg.textfile_extensions)) + shn_cfg.textfile_extensions = g_strdup("txt,nfo"); + xmms_cfg_free(cfg); + } + + g_free(filename); +#endif +// }}} + + char data[4]; + DB_FILE *f; + + f = deadbeef->fopen (it->fname); + if (!f) { + trace ("shn: failed to open %s\n", it->fname); + return -1; + } + + int id3v2_tag_size = deadbeef->junk_get_leading_size (f); + if (id3v2_tag_size > 0) { + deadbeef->fseek (f, id3v2_tag_size, SEEK_SET); + } + + if (deadbeef->fread((void *)data,1,4,f) != 4) + { + deadbeef->fclose(f); + trace ("shn: failed to read magic from %s\n", it->fname); + return -1; + } + deadbeef->fclose(f); + + if (memcmp(data,MAGIC,4)) { + trace ("shn: invalid MAGIC\n"); + return -1; + } + + if (!(info->shnfile = load_shn(it->fname))) { + trace ("shn: load_shn failed\n"); + return -1; + } + + _info->bps = info->shnfile->wave_header.bits_per_sample; + _info->channels = info->shnfile->wave_header.channels; + _info->samplerate = info->shnfile->wave_header.samples_per_sec; + _info->plugin = &plugin; + + int totalsamples = info->shnfile->wave_header.length * info->shnfile->wave_header.samples_per_sec; + trace ("totalsamples: %d\n", totalsamples); + + if (it->endsample > 0) { + info->startsample = it->startsample; + info->endsample = it->endsample; + plugin.seek_sample (_info, 0); + } + else { + info->startsample = 0; + info->endsample = totalsamples-1; + } + + if (info->shnfile->wave_header.file_has_id3v2_tag) { + deadbeef->fseek (info->shnfile->vars.fd, info->shnfile->wave_header.file_has_id3v2_tag, SEEK_SET); + } + else { + deadbeef->rewind (info->shnfile->vars.fd); + } + + if (shn_init_decoder (info) < 0) { + trace ("shn_init_decoder failed\n"); + return -1; + } + + return 0; +} + +void +shn_free (DB_fileinfo_t *_info) { + shn_fileinfo_t *info = (shn_fileinfo_t *)_info; + if (info->shnfile) { + if (info->shnfile->decode_state) { + if(info->shnfile->decode_state->writebuf != NULL) { + free(info->shnfile->decode_state->writebuf); + info->shnfile->decode_state->writebuf = NULL; + } + if(info->shnfile->decode_state->writefub != NULL) { + free(info->shnfile->decode_state->writefub); + info->shnfile->decode_state->writefub = NULL; + } + } + if (info->shnfile) { + shn_unload(info->shnfile); + info->shnfile = NULL; + } + } + if (info->buffer) { + free(info->buffer); + info->buffer = NULL; + } + if (info->offset) { + free(info->offset); + info->offset = NULL; + } + if(info->maxnlpc > 0 && info->qlpc) { + free(info->qlpc); + info->qlpc = NULL; + } + free (info); +} + +void +swap_bytes(shn_file *this_shn,int bytes) +{ + int i; + uchar tmp; + + for (i=0;i<bytes;i=i+2) { + tmp = this_shn->vars.buffer[i+1]; + this_shn->vars.buffer[i+1] = this_shn->vars.buffer[i]; + this_shn->vars.buffer[i] = tmp; + } +} + +int +shn_decode (shn_fileinfo_t *info) { + int i; + int version = info->version; + while(1) + { + info->cmd = uvar_get(FNSIZE,info->shnfile); + if (info->shnfile->vars.fatal_error) { + trace ("shn_decode: uvar_get error\n"); + return -1; + } + + switch(info->cmd) + { + case FN_ZERO: + case FN_DIFF0: + case FN_DIFF1: + case FN_DIFF2: + case FN_DIFF3: + case FN_QLPC: + { + slong coffset, *cbuffer = info->buffer[info->chan]; + int resn = 0, nlpc, j; + + if(info->cmd != FN_ZERO) + { + resn = uvar_get(ENERGYSIZE,info->shnfile); + if (info->shnfile->vars.fatal_error) { + trace ("shn_decode: error 1\n"); + return -1; + } + /* this is a hack as version 0 differed in definition of var_get */ + if(info->version == 0) + resn--; + } + + /* find mean offset : N.B. this code duplicated */ + if(info->nmean == 0) + coffset = info->offset[info->chan][0]; + else + { + slong sum = (info->version < 2) ? 0 : info->nmean / 2; + for(i = 0; i < info->nmean; i++) + sum += info->offset[info->chan][i]; + if(info->version < 2) + coffset = sum / info->nmean; + else + coffset = ROUNDEDSHIFTDOWN(sum / info->nmean, info->bitshift); + } + + switch(info->cmd) + { + case FN_ZERO: + for(i = 0; i < info->blocksize; i++) + cbuffer[i] = 0; + break; + case FN_DIFF0: + for(i = 0; i < info->blocksize; i++) { + cbuffer[i] = var_get(resn,info->shnfile) + coffset; + if (info->shnfile->vars.fatal_error) { + trace ("shn_decode: error 2\n"); + return -1; + } + } + break; + case FN_DIFF1: + for(i = 0; i < info->blocksize; i++) { + cbuffer[i] = var_get(resn,info->shnfile) + cbuffer[i - 1]; + if (info->shnfile->vars.fatal_error) { + trace ("shn_decode: error 3\n"); + return -1; + } + } + break; + case FN_DIFF2: + for(i = 0; i < info->blocksize; i++) { + cbuffer[i] = var_get(resn,info->shnfile) + (2 * cbuffer[i - 1] - cbuffer[i - 2]); + if (info->shnfile->vars.fatal_error) { + trace ("shn_decode: error 4\n"); + return -1; + } + } + break; + case FN_DIFF3: + for(i = 0; i < info->blocksize; i++) { + cbuffer[i] = var_get(resn,info->shnfile) + 3 * (cbuffer[i - 1] - cbuffer[i - 2]) + cbuffer[i - 3]; + if (info->shnfile->vars.fatal_error) { + trace ("shn_decode: error 5\n"); + return -1; + } + } + break; + case FN_QLPC: + nlpc = uvar_get(LPCQSIZE,info->shnfile); + if (info->shnfile->vars.fatal_error) { + trace ("shn_decode: error 6\n"); + return -1; + } + + for(i = 0; i < nlpc; i++) { + info->qlpc[i] = var_get(LPCQUANT,info->shnfile); + if (info->shnfile->vars.fatal_error) { + trace ("shn_decode: error 7\n"); + return -1; + } + } + for(i = 0; i < nlpc; i++) + cbuffer[i - nlpc] -= coffset; + for(i = 0; i < info->blocksize; i++) + { + slong sum = info->lpcqoffset; + + for(j = 0; j < nlpc; j++) + sum += info->qlpc[j] * cbuffer[i - j - 1]; + cbuffer[i] = var_get(resn,info->shnfile) + (sum >> LPCQUANT); + if (info->shnfile->vars.fatal_error) { + trace ("shn_decode: error 8\n"); + return -1; + } + } + if(coffset != 0) + for(i = 0; i < info->blocksize; i++) + cbuffer[i] += coffset; + break; + } + + /* store mean value if appropriate : N.B. Duplicated code */ + if(info->nmean > 0) + { + slong sum = (info->version < 2) ? 0 : info->blocksize / 2; + + for(i = 0; i < info->blocksize; i++) + sum += cbuffer[i]; + + for(i = 1; i < info->nmean; i++) + info->offset[info->chan][i - 1] = info->offset[info->chan][i]; + if(info->version < 2) + info->offset[info->chan][info->nmean - 1] = sum / info->blocksize; + else + info->offset[info->chan][info->nmean - 1] = (sum / info->blocksize) << info->bitshift; + } + + /* do the wrap */ + for(i = -info->nwrap; i < 0; i++) + cbuffer[i] = cbuffer[i + info->blocksize]; + + fix_bitshift(cbuffer, info->blocksize, info->bitshift, info->internal_ftype); + + if(info->chan == info->nchan - 1) + { + if (!info->shnfile->vars.going || info->shnfile->vars.fatal_error) { + trace ("shn_decode: error 9\n"); + return -1; + } + + fwrite_type(info->buffer, info->ftype, info->nchan, info->blocksize, info->shnfile); + info->chan = (info->chan + 1) % info->nchan; + // now we have buffer of size info->shnfile->vars.bytes_in_buf + if (shn_cfg.swap_bytes) { + swap_bytes(info->shnfile, info->shnfile->vars.bytes_in_buf); + } + return info->shnfile->vars.bytes_in_buf; + + +// !!!!!!!!!!!!!!!!!!FIXME + // write_and_wait(info->shnfile,blk_size); + +#if 0 // seeking + if (info->shnfile->vars.seek_to != -1) + { + shn_seek_entry *seek_info; + int j; + + shn_debug("Seeking to %d:%02d",info->shnfile->vars.seek_to/60,info->shnfile->vars.seek_to%60); + + seek_info = shn_seek_entry_search(info->shnfile->seek_table,info->shnfile->vars.seek_to * (ulong)info->shnfile->wave_header.samples_per_sec,0, + (ulong)(info->shnfile->vars.seek_table_entries - 1),info->shnfile->vars.seek_resolution); + + /* loop through number of channels in this file */ + for (i=0;i<info->nchan;i++) { + /* load the three sample buffer values for this channel */ + for (j=0;j<3;j++) + info->buffer[i][j-3] = shn_uchar_to_slong_le(seek_info->data+32+12*i-4*j); + + /* load the variable number of offset history values for this channel */ + for (j=0;j<MAX(1,info->nmean);j++) + info->offset[i][j] = shn_uchar_to_slong_le(seek_info->data+48+16*i+4*j); + } + + info->bitshift = shn_uchar_to_ushort_le(seek_info->data+22); + + info->seekto_offset = shn_uchar_to_ulong_le(seek_info->data+8) + info->shnfile->vars.seek_offset; + + deadbeef->fseek(info->shnfile->vars.fd,(slong)seekto_offset,SEEK_SET); + deadbeef->fread((uchar*) info->shnfile->decode_state->getbuf, 1, BUFSIZ, info->shnfile->vars.fd); + + info->shnfile->decode_state->getbufp = info->shnfile->decode_state->getbuf + shn_uchar_to_ushort_le(seek_info->data+14); + info->shnfile->decode_state->nbitget = shn_uchar_to_ushort_le(seek_info->data+16); + info->shnfile->decode_state->nbyteget = shn_uchar_to_ushort_le(seek_info->data+12); + info->shnfile->decode_state->gbuffer = shn_uchar_to_ulong_le(seek_info->data+18); + + info->shnfile->vars.bytes_in_buf = 0; + + shn_ip.output->flush(info->shnfile->vars.seek_to * 1000); + info->shnfile->vars.seek_to = -1; + } +#endif + + } + info->chan = (info->chan + 1) % info->nchan; + break; + } + + break; + + case FN_QUIT: + /* empty out last of buffer */ + info->shnfile->vars.eof = 1; + if (shn_cfg.swap_bytes) { + swap_bytes(info->shnfile, info->shnfile->vars.bytes_in_buf); + } + return info->shnfile->vars.bytes_in_buf; +#if 0 + write_and_wait(info->shnfile,info->shnfile->vars.bytes_in_buf); + info->shnfile->vars.eof = 1; + + while (1) + { + if (!info->shnfile->vars.going) + goto finish; + if (info->shnfile->vars.seek_to != -1) + { + var_get_quit(info->shnfile); + fwrite_type_quit(info->shnfile); + + if (buffer) free((void *) buffer); + if (offset) free((void *) offset); + if(maxnlpc > 0 && qlpc) + free((void *) qlpc); + + fseek(info->shnfile->vars.fd,0,SEEK_SET); + goto restart; + } + else + xmms_usleep(10000); + } + + goto cleanup; +#endif + break; + + case FN_BLOCKSIZE: + info->blocksize = UINT_GET((int) (log((double) info->blocksize) / M_LN2), info->shnfile); + if (info->shnfile->vars.fatal_error) { + trace ("shn_decode: error 10\n"); + return -1; + } + break; + case FN_BITSHIFT: + info->bitshift = uvar_get(BITSHIFTSIZE,info->shnfile); + if (info->shnfile->vars.fatal_error) { + trace ("shn_decode: error 11\n"); + return -1; + } + break; + case FN_VERBATIM: + info->cklen = uvar_get(VERBATIM_CKSIZE_SIZE,info->shnfile); + if (info->shnfile->vars.fatal_error) { + trace ("shn_decode: error 12\n"); + return -1; + } + + while (info->cklen--) { + info->tmp = (uchar)uvar_get(VERBATIM_BYTE_SIZE,info->shnfile); + if (info->shnfile->vars.fatal_error) { + trace ("shn_decode: error 13\n"); + return -1; + } + } + + break; + + default: + shn_error_fatal(info->shnfile,"Sanity check fails trying to decode function: %d",info->cmd); + trace ("shn_decode: error 14\n"); + return -1; + } + } + return 0; +} + +int +shn_read_int16 (DB_fileinfo_t *_info, char *bytes, int size) { + shn_fileinfo_t *info = (shn_fileinfo_t *)_info; + if (info->currentsample + size / (2 * _info->channels) > info->endsample) { + size = (info->endsample - info->currentsample + 1) * 2 * _info->channels; + if (size <= 0) { + return 0; + } + } + int initsize = size; + int ch = min (_info->channels, 2); + int sample_size = ch * (_info->bps >> 3); + + while (size > 0) { + if (info->shnfile->vars.bytes_in_buf > 0) { + int n = size / sample_size; + int nsamples = info->shnfile->vars.bytes_in_buf / (_info->channels * 2); + n = min (nsamples, n); + char *src = info->shnfile->vars.buffer; + for (int i = 0; i < n; i++) { + memcpy (bytes, src, sample_size); + bytes += sample_size; + src += _info->channels * 2; + } + + size -= n * sample_size; + if (n == info->shnfile->vars.bytes_in_buf / (_info->channels * 2)) { + info->shnfile->vars.bytes_in_buf = 0; + } + else { + memmove (info->shnfile->vars.buffer, src, info->shnfile->vars.bytes_in_buf - n * (_info->channels * 2)); + info->shnfile->vars.bytes_in_buf -= n * (_info->channels * 2); + } + continue; + } + if (shn_decode (info) <= 0) { + trace ("shn_decode returned error\n"); + break; + } + } + + info->currentsample += (initsize-size) / sample_size; + if (size != 0) { + trace ("shn_read_int16 eof\n"); + } + return initsize-size; +} + +int +shn_seek_sample (DB_fileinfo_t *_info, int sample) { + shn_fileinfo_t *info = (shn_fileinfo_t *)_info; + + sample += info->startsample; + + info->shnfile->vars.seek_to = sample / _info->samplerate; + + ulong seekto_offset; + int i, j; + shn_seek_entry *seek_info; + + trace ("Seeking to %d:%02d\n",info->shnfile->vars.seek_to/60,info->shnfile->vars.seek_to%60); + + seek_info = shn_seek_entry_search(info->shnfile->seek_table,info->shnfile->vars.seek_to * (ulong)info->shnfile->wave_header.samples_per_sec,0, + (ulong)(info->shnfile->vars.seek_table_entries - 1),info->shnfile->vars.seek_resolution); + + /* loop through number of channels in this file */ + for (i=0;i<info->nchan;i++) { + /* load the three sample buffer values for this channel */ + for (j=0;j<3;j++) + info->buffer[i][j-3] = shn_uchar_to_slong_le(seek_info->data+32+12*i-4*j); + + /* load the variable number of offset history values for this channel */ + for (j=0;j<MAX(1,info->nmean);j++) + info->offset[i][j] = shn_uchar_to_slong_le(seek_info->data+48+16*i+4*j); + } + + info->bitshift = shn_uchar_to_ushort_le(seek_info->data+22); + + seekto_offset = shn_uchar_to_ulong_le(seek_info->data+8) + info->shnfile->vars.seek_offset; + + deadbeef->fseek(info->shnfile->vars.fd,(slong)seekto_offset,SEEK_SET); + deadbeef->fread((uchar*) info->shnfile->decode_state->getbuf, 1, BUFSIZ, info->shnfile->vars.fd); + + info->shnfile->decode_state->getbufp = info->shnfile->decode_state->getbuf + shn_uchar_to_ushort_le(seek_info->data+14); + info->shnfile->decode_state->nbitget = shn_uchar_to_ushort_le(seek_info->data+16); + info->shnfile->decode_state->nbyteget = shn_uchar_to_ushort_le(seek_info->data+12); + info->shnfile->decode_state->gbuffer = shn_uchar_to_ulong_le(seek_info->data+18); + + info->shnfile->vars.bytes_in_buf = 0; + + info->currentsample = info->shnfile->vars.seek_to * _info->samplerate; + _info->readpos = info->shnfile->vars.seek_to; + return 0; +} + +int +shn_seek (DB_fileinfo_t *_info, float time) { + return shn_seek_sample (_info, time * _info->samplerate); + return 0; +} + +DB_playItem_t * +shn_insert (DB_playItem_t *after, const char *fname) { + shn_file *tmp_file; + DB_FILE *f; + char data[4]; + + f = deadbeef->fopen (fname); + if (!f) { + return NULL; + } + + int id3v2_tag_size = deadbeef->junk_get_leading_size (f); + if (id3v2_tag_size > 0) { + deadbeef->fseek (f, id3v2_tag_size, SEEK_SET); + } + + if (deadbeef->fread((void *)data,1,4,f) != 4) + { + deadbeef->fclose(f); + return NULL; + } + deadbeef->fclose(f); + + if (memcmp(data,MAGIC,4)) { + trace ("shn: invalid MAGIC\n"); + return NULL; + } + + if (!(tmp_file = load_shn(fname))) { + trace ("shn: load_shn failed\n"); + return NULL; + } + + DB_playItem_t *it = deadbeef->pl_item_alloc (); + it->decoder_id = deadbeef->plug_get_decoder_id (plugin.plugin.id); + it->fname = strdup (fname); + it->filetype = "Shorten"; + deadbeef->pl_set_item_duration (it, tmp_file->wave_header.length); + + int apeerr = deadbeef->junk_apev2_read (it, tmp_file->vars.fd); + int v2err = deadbeef->junk_id3v2_read (it, tmp_file->vars.fd); + int v1err = deadbeef->junk_id3v1_read (it, tmp_file->vars.fd); + + shn_unload(tmp_file); + + deadbeef->pl_add_meta (it, "title", NULL); + + after = deadbeef->pl_insert_item (after, it); + deadbeef->pl_item_unref (it); + return after; +} + +#define CAPMAXSCHAR(x) ((x > 127) ? 127 : x) +#define CAPMAXUCHAR(x) ((x > 255) ? 255 : x) +#define CAPMAXSHORT(x) ((x > 32767) ? 32767 : x) +#define CAPMAXUSHORT(x) ((x > 65535) ? 65535 : x) + +static int sizeof_sample[TYPE_EOF]; + +void init_sizeof_sample() { + sizeof_sample[TYPE_AU1] = sizeof(uchar); + sizeof_sample[TYPE_S8] = sizeof(schar); + sizeof_sample[TYPE_U8] = sizeof(uchar); + sizeof_sample[TYPE_S16HL] = sizeof(ushort); + sizeof_sample[TYPE_U16HL] = sizeof(ushort); + sizeof_sample[TYPE_S16LH] = sizeof(ushort); + sizeof_sample[TYPE_U16LH] = sizeof(ushort); + sizeof_sample[TYPE_ULAW] = sizeof(uchar); + sizeof_sample[TYPE_AU2] = sizeof(uchar); + sizeof_sample[TYPE_AU3] = sizeof(uchar); + sizeof_sample[TYPE_ALAW] = sizeof(uchar); +} + + +/***************/ +/* fixed write */ +/***************/ + +void fwrite_type_init(shn_file *this_shn) { + init_sizeof_sample(); + this_shn->decode_state->writebuf = (schar*) NULL; + this_shn->decode_state->writefub = (schar*) NULL; + this_shn->decode_state->nwritebuf = 0; +} + +void fwrite_type_quit(shn_file *this_shn) { + if(this_shn->decode_state->writebuf != NULL) { + free(this_shn->decode_state->writebuf); + this_shn->decode_state->writebuf = NULL; + } + if(this_shn->decode_state->writefub != NULL) { + free(this_shn->decode_state->writefub); + this_shn->decode_state->writefub = NULL; + } +} + +/* convert from signed ints to a given type and write */ +void fwrite_type(slong **data,int ftype,int nchan,int nitem,shn_file *this_shn) +{ + int hiloint = 1, hilo = !(*((char*) &hiloint)); + int i, nwrite = 0, datasize = sizeof_sample[ftype], chan; + slong *data0 = data[0]; + int bufAvailable = OUT_BUFFER_SIZE - this_shn->vars.bytes_in_buf; + + if(this_shn->decode_state->nwritebuf < nchan * nitem * datasize) { + this_shn->decode_state->nwritebuf = nchan * nitem * datasize; + if(this_shn->decode_state->writebuf != NULL) free(this_shn->decode_state->writebuf); + if(this_shn->decode_state->writefub != NULL) free(this_shn->decode_state->writefub); + this_shn->decode_state->writebuf = (schar*) pmalloc((ulong) this_shn->decode_state->nwritebuf,this_shn); + if (!this_shn->decode_state->writebuf) + return; + this_shn->decode_state->writefub = (schar*) pmalloc((ulong) this_shn->decode_state->nwritebuf,this_shn); + if (!this_shn->decode_state->writefub) + return; + } + + switch(ftype) { + case TYPE_AU1: /* leave the conversion to fix_bitshift() */ + case TYPE_AU2: { + uchar *writebufp = (uchar*) this_shn->decode_state->writebuf; + if(nchan == 1) + for(i = 0; i < nitem; i++) + *writebufp++ = data0[i]; + else + for(i = 0; i < nitem; i++) + for(chan = 0; chan < nchan; chan++) + *writebufp++ = data[chan][i]; + break; + } + case TYPE_U8: { + uchar *writebufp = (uchar*) this_shn->decode_state->writebuf; + if(nchan == 1) + for(i = 0; i < nitem; i++) + *writebufp++ = CAPMAXUCHAR(data0[i]); + else + for(i = 0; i < nitem; i++) + for(chan = 0; chan < nchan; chan++) + *writebufp++ = CAPMAXUCHAR(data[chan][i]); + break; + } + case TYPE_S8: { + schar *writebufp = (schar*) this_shn->decode_state->writebuf; + if(nchan == 1) + for(i = 0; i < nitem; i++) + *writebufp++ = CAPMAXSCHAR(data0[i]); + else + for(i = 0; i < nitem; i++) + for(chan = 0; chan < nchan; chan++) + *writebufp++ = CAPMAXSCHAR(data[chan][i]); + break; + } + case TYPE_S16HL: + case TYPE_S16LH: { + short *writebufp = (short*) this_shn->decode_state->writebuf; + if(nchan == 1) + for(i = 0; i < nitem; i++) + *writebufp++ = CAPMAXSHORT(data0[i]); + else + for(i = 0; i < nitem; i++) + for(chan = 0; chan < nchan; chan++) + *writebufp++ = CAPMAXSHORT(data[chan][i]); + break; + } + case TYPE_U16HL: + case TYPE_U16LH: { + ushort *writebufp = (ushort*) this_shn->decode_state->writebuf; + if(nchan == 1) + for(i = 0; i < nitem; i++) + *writebufp++ = CAPMAXUSHORT(data0[i]); + else + for(i = 0; i < nitem; i++) + for(chan = 0; chan < nchan; chan++) + *writebufp++ = CAPMAXUSHORT(data[chan][i]); + break; + } + case TYPE_ULAW: { + uchar *writebufp = (uchar*) this_shn->decode_state->writebuf; + if(nchan == 1) + for(i = 0; i < nitem; i++) + *writebufp++ = Slinear2ulaw(CAPMAXSHORT((data0[i] << 3))); + else + for(i = 0; i < nitem; i++) + for(chan = 0; chan < nchan; chan++) + *writebufp++ = Slinear2ulaw(CAPMAXSHORT((data[chan][i] << 3))); + break; + } + case TYPE_AU3: { + uchar *writebufp = (uchar*) this_shn->decode_state->writebuf; + if(nchan == 1) + for(i = 0; i < nitem; i++) + if(data0[i] < 0) + *writebufp++ = (127 - data0[i]) ^ 0xd5; + else + *writebufp++ = (data0[i] + 128) ^ 0x55; + else + for(i = 0; i < nitem; i++) + for(chan = 0; chan < nchan; chan++) + if(data[chan][i] < 0) + *writebufp++ = (127 - data[chan][i]) ^ 0xd5; + else + *writebufp++ = (data[chan][i] + 128) ^ 0x55; + break; + } + case TYPE_ALAW: { + uchar *writebufp = (uchar*) this_shn->decode_state->writebuf; + if(nchan == 1) + for(i = 0; i < nitem; i++) + *writebufp++ = Slinear2alaw(CAPMAXSHORT((data0[i] << 3))); + else + for(i = 0; i < nitem; i++) + for(chan = 0; chan < nchan; chan++) + *writebufp++ = Slinear2alaw(CAPMAXSHORT((data[chan][i] << 3))); + break; + } + } + + switch(ftype) { + case TYPE_AU1: + case TYPE_S8: + case TYPE_U8: + case TYPE_ULAW: + case TYPE_AU2: + case TYPE_AU3: + case TYPE_ALAW: + if (datasize*nchan*nitem <= bufAvailable) { + memcpy((void *)&this_shn->vars.buffer[this_shn->vars.bytes_in_buf],(const void *)this_shn->decode_state->writebuf,datasize*nchan*nitem); + this_shn->vars.bytes_in_buf += datasize*nchan*nitem; + nwrite = nitem; + } + else + shn_debug("Buffer overrun in fwrite_type() [case 1]: %d bytes to read, but only %d bytes are available",datasize*nchan*nitem,bufAvailable); + break; + case TYPE_S16HL: + case TYPE_U16HL: + if(hilo) + { + if (datasize*nchan*nitem <= bufAvailable) { + memcpy((void *)&this_shn->vars.buffer[this_shn->vars.bytes_in_buf],(const void *)this_shn->decode_state->writebuf,datasize*nchan*nitem); + this_shn->vars.bytes_in_buf += datasize*nchan*nitem; + nwrite = nitem; + } + else + shn_debug("Buffer overrun in fwrite_type() [case 2]: %d bytes to read, but only %d bytes are available",datasize*nchan*nitem,bufAvailable); + } + else + { + swab(this_shn->decode_state->writebuf, this_shn->decode_state->writefub, datasize * nchan * nitem); + if (datasize*nchan*nitem <= bufAvailable) { + memcpy((void *)&this_shn->vars.buffer[this_shn->vars.bytes_in_buf],(const void *)this_shn->decode_state->writefub,datasize*nchan*nitem); + this_shn->vars.bytes_in_buf += datasize*nchan*nitem; + nwrite = nitem; + } + else + shn_debug("Buffer overrun in fwrite_type() [case 3]: %d bytes to read, but only %d bytes are available",datasize*nchan*nitem,bufAvailable); + } + break; + case TYPE_S16LH: + case TYPE_U16LH: + if(hilo) + { + swab(this_shn->decode_state->writebuf, this_shn->decode_state->writefub, datasize * nchan * nitem); + if (datasize*nchan*nitem <= bufAvailable) { + memcpy((void *)&this_shn->vars.buffer[this_shn->vars.bytes_in_buf],(const void *)this_shn->decode_state->writefub,datasize*nchan*nitem); + this_shn->vars.bytes_in_buf += datasize*nchan*nitem; + nwrite = nitem; + } + else + shn_debug("Buffer overrun in fwrite_type() [case 4]: %d bytes to read, but only %d bytes are available",datasize*nchan*nitem,bufAvailable); + } + else + { + if (datasize*nchan*nitem <= bufAvailable) { + memcpy((void *)&this_shn->vars.buffer[this_shn->vars.bytes_in_buf],(const void *)this_shn->decode_state->writebuf,datasize*nchan*nitem); + this_shn->vars.bytes_in_buf += datasize*nchan*nitem; + nwrite = nitem; + } + else + shn_debug("Buffer overrun in fwrite_type() [case 5]: %d bytes to read, but only %d bytes are available",datasize*nchan*nitem,bufAvailable); + } + break; + } + + if(nwrite != nitem) + shn_error_fatal(this_shn,"Failed to write decompressed stream -\npossible corrupt or truncated file"); +} + +/*************/ +/* bitshifts */ +/*************/ + +void fix_bitshift(buffer, nitem, bitshift, ftype) slong *buffer; int nitem, + bitshift, ftype; { + int i; + + if(ftype == TYPE_AU1) + for(i = 0; i < nitem; i++) + buffer[i] = ulaw_outward[bitshift][buffer[i] + 128]; + else if(ftype == TYPE_AU2) + for(i = 0; i < nitem; i++) { + if(buffer[i] >= 0) + buffer[i] = ulaw_outward[bitshift][buffer[i] + 128]; + else if(buffer[i] == -1) + buffer[i] = NEGATIVE_ULAW_ZERO; + else + buffer[i] = ulaw_outward[bitshift][buffer[i] + 129]; + } + else + if(bitshift != 0) + for(i = 0; i < nitem; i++) + buffer[i] <<= bitshift; +} + +int get_wave_header(shn_file *this_shn) +{ + slong **buffer = NULL, **offset = NULL; + slong lpcqoffset = 0; + int version = FORMAT_VERSION, bitshift = 0; + int ftype = TYPE_EOF; + char *magic = MAGIC; + int blocksize = DEFAULT_BLOCK_SIZE, nchan = DEFAULT_NCHAN; + int i, chan, nwrap, nskip = DEFAULT_NSKIP; + int *qlpc = NULL, maxnlpc = DEFAULT_MAXNLPC, nmean = UNDEFINED_UINT; + int cmd; + int internal_ftype; + int cklen; + int retval = 0; + + if (!init_decode_state(this_shn)) + return 0; + + /***********************/ + /* EXTRACT starts here */ + /***********************/ + + /* read magic number */ +#ifdef STRICT_FORMAT_COMPATABILITY + if(FORMAT_VERSION < 2) + { + for(i = 0; i < strlen(magic); i++) { + if(getc_exit(this_shn->vars.fd) != magic[i]) + return 0; + this_shn->vars.bytes_read++; + } + + /* get version number */ + version = getc_exit(this_shn->vars.fd); + this_shn->vars.bytes_read++; + } + else +#endif /* STRICT_FORMAT_COMPATABILITY */ + { + int nscan = 0; + + version = MAX_VERSION + 1; + while(version > MAX_VERSION) + { + int byte = ddb_getc(this_shn->vars.fd); + this_shn->vars.bytes_read++; + if(byte == EOF) + return 0; + if(magic[nscan] != '\0' && byte == magic[nscan]) + nscan++; + else + if(magic[nscan] == '\0' && byte <= MAX_VERSION) + version = byte; + else + { + if(byte == magic[0]) + nscan = 1; + else + { + nscan = 0; + } + version = MAX_VERSION + 1; + } + } + } + + /* check version number */ + if(version > MAX_SUPPORTED_VERSION) + return 0; + + /* set up the default nmean, ignoring the command line state */ + nmean = (version < 2) ? DEFAULT_V0NMEAN : DEFAULT_V2NMEAN; + + /* initialise the variable length file read for the compressed stream */ + var_get_init(this_shn); + if (this_shn->vars.fatal_error) + return 0; + + /* initialise the fixed length file write for the uncompressed stream */ + fwrite_type_init(this_shn); + + /* get the internal file type */ + internal_ftype = UINT_GET(TYPESIZE, this_shn); + + /* has the user requested a change in file type? */ + if(internal_ftype != ftype) { + if(ftype == TYPE_EOF) { + ftype = internal_ftype; /* no problems here */ + } + else { /* check that the requested conversion is valid */ + if(internal_ftype == TYPE_AU1 || internal_ftype == TYPE_AU2 || + internal_ftype == TYPE_AU3 || ftype == TYPE_AU1 ||ftype == TYPE_AU2 || ftype == TYPE_AU3) + { + retval = 0; + goto got_enough_data; + } + } + } + + nchan = UINT_GET(CHANSIZE, this_shn); + this_shn->vars.actual_nchan = nchan; + + /* get blocksize if version > 0 */ + if(version > 0) + { + int byte; + blocksize = UINT_GET((int) (log((double) DEFAULT_BLOCK_SIZE) / M_LN2),this_shn); + maxnlpc = UINT_GET(LPCQSIZE, this_shn); + this_shn->vars.actual_maxnlpc = maxnlpc; + nmean = UINT_GET(0, this_shn); + this_shn->vars.actual_nmean = nmean; + nskip = UINT_GET(NSKIPSIZE, this_shn); + for(i = 0; i < nskip; i++) + { + byte = uvar_get(XBYTESIZE,this_shn); + } + } + else + blocksize = DEFAULT_BLOCK_SIZE; + + nwrap = MAX(NWRAP, maxnlpc); + + /* grab some space for the input buffer */ + buffer = long2d((ulong) nchan, (ulong) (blocksize + nwrap),this_shn); + if (this_shn->vars.fatal_error) + return 0; + offset = long2d((ulong) nchan, (ulong) MAX(1, nmean),this_shn); + if (this_shn->vars.fatal_error) { + if (buffer) { + free(buffer); + buffer = NULL; + } + return 0; + } + + for(chan = 0; chan < nchan; chan++) + { + for(i = 0; i < nwrap; i++) + buffer[chan][i] = 0; + buffer[chan] += nwrap; + } + + if(maxnlpc > 0) { + qlpc = (int*) pmalloc((ulong) (maxnlpc * sizeof(*qlpc)),this_shn); + if (this_shn->vars.fatal_error) { + if (buffer) { + free(buffer); + buffer = NULL; + } + if (offset) { + free(offset); + buffer = NULL; + } + return 0; + } + } + + if(version > 1) + lpcqoffset = V2LPCQOFFSET; + + init_offset(offset, nchan, MAX(1, nmean), internal_ftype); + + /* get commands from file and execute them */ + chan = 0; + while(1) + { + this_shn->vars.reading_function_code = 1; + cmd = uvar_get(FNSIZE,this_shn); + this_shn->vars.reading_function_code = 0; + + switch(cmd) + { + case FN_ZERO: + case FN_DIFF0: + case FN_DIFF1: + case FN_DIFF2: + case FN_DIFF3: + case FN_QLPC: + { + slong coffset, *cbuffer = buffer[chan]; + int resn = 0, nlpc, j; + + if(cmd != FN_ZERO) + { + resn = uvar_get(ENERGYSIZE,this_shn); + if (this_shn->vars.fatal_error) { + retval = 0; + goto got_enough_data; + } + /* this is a hack as version 0 differed in definition of var_get */ + if(version == 0) + resn--; + } + + /* find mean offset : N.B. this code duplicated */ + if(nmean == 0) + coffset = offset[chan][0]; + else + { + slong sum = (version < 2) ? 0 : nmean / 2; + for(i = 0; i < nmean; i++) + sum += offset[chan][i]; + if(version < 2) + coffset = sum / nmean; + else + coffset = ROUNDEDSHIFTDOWN(sum / nmean, bitshift); + } + + switch(cmd) + { + case FN_ZERO: + for(i = 0; i < blocksize; i++) + cbuffer[i] = 0; + break; + case FN_DIFF0: + for(i = 0; i < blocksize; i++) { + cbuffer[i] = var_get(resn,this_shn) + coffset; + if (this_shn->vars.fatal_error) { + retval = 0; + goto got_enough_data; + } + } + break; + case FN_DIFF1: + for(i = 0; i < blocksize; i++) { + cbuffer[i] = var_get(resn,this_shn) + cbuffer[i - 1]; + if (this_shn->vars.fatal_error) { + retval = 0; + goto got_enough_data; + } + } + break; + case FN_DIFF2: + for(i = 0; i < blocksize; i++) { + cbuffer[i] = var_get(resn,this_shn) + (2 * cbuffer[i - 1] - cbuffer[i - 2]); + if (this_shn->vars.fatal_error) { + retval = 0; + goto got_enough_data; + } + } + break; + case FN_DIFF3: + for(i = 0; i < blocksize; i++) { + cbuffer[i] = var_get(resn,this_shn) + 3 * (cbuffer[i - 1] - cbuffer[i - 2]) + cbuffer[i - 3]; + if (this_shn->vars.fatal_error) { + retval = 0; + goto got_enough_data; + } + } + break; + case FN_QLPC: + nlpc = uvar_get(LPCQSIZE,this_shn); + if (this_shn->vars.fatal_error) { + retval = 0; + goto got_enough_data; + } + + for(i = 0; i < nlpc; i++) { + qlpc[i] = var_get(LPCQUANT,this_shn); + if (this_shn->vars.fatal_error) { + retval = 0; + goto got_enough_data; + } + } + for(i = 0; i < nlpc; i++) + cbuffer[i - nlpc] -= coffset; + for(i = 0; i < blocksize; i++) + { + slong sum = lpcqoffset; + + for(j = 0; j < nlpc; j++) + sum += qlpc[j] * cbuffer[i - j - 1]; + cbuffer[i] = var_get(resn,this_shn) + (sum >> LPCQUANT); + if (this_shn->vars.fatal_error) { + retval = 0; + goto got_enough_data; + } + } + if(coffset != 0) + for(i = 0; i < blocksize; i++) + cbuffer[i] += coffset; + break; + } + + /* store mean value if appropriate : N.B. Duplicated code */ + if(nmean > 0) + { + slong sum = (version < 2) ? 0 : blocksize / 2; + + for(i = 0; i < blocksize; i++) + sum += cbuffer[i]; + + for(i = 1; i < nmean; i++) + offset[chan][i - 1] = offset[chan][i]; + if(version < 2) + offset[chan][nmean - 1] = sum / blocksize; + else + offset[chan][nmean - 1] = (sum / blocksize) << bitshift; + } + + if (0 == chan) { + this_shn->vars.initial_file_position = this_shn->vars.last_file_position_no_really; + goto got_enough_data; + } + + /* do the wrap */ + for(i = -nwrap; i < 0; i++) + cbuffer[i] = cbuffer[i + blocksize]; + + fix_bitshift(cbuffer, blocksize, bitshift, internal_ftype); + + if(chan == nchan - 1) + { + fwrite_type(buffer, ftype, nchan, blocksize, this_shn); + this_shn->vars.bytes_in_buf = 0; + } + + chan = (chan + 1) % nchan; + break; + } + break; + + case FN_BLOCKSIZE: + UINT_GET((int) (log((double) blocksize) / M_LN2), this_shn); + break; + + case FN_VERBATIM: + cklen = uvar_get(VERBATIM_CKSIZE_SIZE,this_shn); + + while (cklen--) { + if (this_shn->vars.bytes_in_header >= OUT_BUFFER_SIZE) { + shn_debug("Unexpectedly large header - " PACKAGE " can only handle a maximum of %d bytes",OUT_BUFFER_SIZE); + goto got_enough_data; + } + this_shn->vars.bytes_in_buf = 0; + this_shn->vars.header[this_shn->vars.bytes_in_header++] = (char)uvar_get(VERBATIM_BYTE_SIZE,this_shn); + } + retval = 1; + break; + + case FN_BITSHIFT: + bitshift = uvar_get(BITSHIFTSIZE,this_shn); + this_shn->vars.actual_bitshift = bitshift; + break; + + default: + goto got_enough_data; + } + } + +got_enough_data: + + /* wind up */ + var_get_quit(this_shn); + fwrite_type_quit(this_shn); + + if (buffer) free((void *) buffer); + if (offset) free((void *) offset); + if(maxnlpc > 0 && qlpc) + free((void *) qlpc); + + this_shn->vars.bytes_in_buf = 0; + + return retval; +} + +void shn_unload(shn_file *this_shn) +{ + if (this_shn) + { + if (this_shn->vars.fd) + { + deadbeef->fclose(this_shn->vars.fd); + this_shn->vars.fd = NULL; + } + + if (this_shn->decode_state) + { + if (this_shn->decode_state->getbuf) + { + free(this_shn->decode_state->getbuf); + this_shn->decode_state->getbuf = NULL; + } + + if (this_shn->decode_state->writebuf) + { + free(this_shn->decode_state->writebuf); + this_shn->decode_state->writebuf = NULL; + } + + if (this_shn->decode_state->writefub) + { + free(this_shn->decode_state->writefub); + this_shn->decode_state->writefub = NULL; + } + + free(this_shn->decode_state); + this_shn->decode_state = NULL; + } + + if (this_shn->seek_table) + { + free(this_shn->seek_table); + this_shn->seek_table = NULL; + } + + free(this_shn); + this_shn = NULL; + } +} + +shn_file *load_shn(const char *filename) +{ + shn_file *tmp_file; + shn_seek_entry *first_seek_table; + + shn_debug("Loading file: '%s'",filename); + + if (!(tmp_file = malloc(sizeof(shn_file)))) + { + shn_debug("Could not allocate memory for SHN data structure"); + return NULL; + } + + memset(tmp_file, 0, sizeof(shn_file)); + + tmp_file->vars.fd = NULL; + tmp_file->vars.seek_to = -1; + tmp_file->vars.eof = 0; + tmp_file->vars.going = 0; + tmp_file->vars.seek_table_entries = NO_SEEK_TABLE; + tmp_file->vars.bytes_in_buf = 0; + tmp_file->vars.bytes_in_header = 0; + tmp_file->vars.reading_function_code = 0; + tmp_file->vars.initial_file_position = 0; + tmp_file->vars.last_file_position = 0; + tmp_file->vars.last_file_position_no_really = 0; + tmp_file->vars.bytes_read = 0; + tmp_file->vars.actual_bitshift = 0; + tmp_file->vars.actual_maxnlpc = 0; + tmp_file->vars.actual_nmean = 0; + tmp_file->vars.actual_nchan = 0; + tmp_file->vars.seek_offset = 0; + + tmp_file->decode_state = NULL; + + tmp_file->wave_header.filename = filename; + tmp_file->wave_header.wave_format = 0; + tmp_file->wave_header.channels = 0; + tmp_file->wave_header.block_align = 0; + tmp_file->wave_header.bits_per_sample = 0; + tmp_file->wave_header.samples_per_sec = 0; + tmp_file->wave_header.avg_bytes_per_sec = 0; + tmp_file->wave_header.rate = 0; + tmp_file->wave_header.header_size = 0; + tmp_file->wave_header.data_size = 0; + tmp_file->wave_header.file_has_id3v2_tag = 0; + tmp_file->wave_header.id3v2_tag_size = 0; + + tmp_file->seek_header.version = NO_SEEK_TABLE; + tmp_file->seek_header.shnFileSize = 0; + + tmp_file->seek_trailer.seekTableSize = 0; + + tmp_file->seek_table = NULL; + + tmp_file->vars.fd = deadbeef->fopen (filename); + if (!tmp_file->vars.fd) { + shn_debug("Could not open file: '%s'",filename); + shn_unload(tmp_file); + return NULL; + } + + tmp_file->wave_header.id3v2_tag_size = deadbeef->junk_get_leading_size (tmp_file->vars.fd); + if (tmp_file->wave_header.id3v2_tag_size > 0) { + tmp_file->wave_header.file_has_id3v2_tag = 2; + trace ("found id3v2 tag, size: %d\n", tmp_file->wave_header.id3v2_tag_size); + if (0 != deadbeef->fseek(tmp_file->vars.fd,(long)tmp_file->wave_header.id3v2_tag_size,SEEK_SET)) { + shn_debug("Error while discarding ID3v2 tag in file '%s'.",filename); + deadbeef->rewind (tmp_file->vars.fd); + } + } + + if (0 == get_wave_header(tmp_file)) + { + shn_debug("Unable to read WAVE header from file '%s'",filename); + shn_unload(tmp_file); + return NULL; + } + + if (tmp_file->wave_header.file_has_id3v2_tag) + { + deadbeef->fseek(tmp_file->vars.fd,tmp_file->wave_header.id3v2_tag_size,SEEK_SET); + tmp_file->vars.bytes_read += tmp_file->wave_header.id3v2_tag_size; + tmp_file->vars.seek_offset = tmp_file->wave_header.id3v2_tag_size; + } + else + { + deadbeef->fseek(tmp_file->vars.fd,0,SEEK_SET); + } + + if (0 == shn_verify_header(tmp_file)) + { + shn_debug("Invalid WAVE header in file: '%s'",filename); + shn_unload(tmp_file); + return NULL; + } + + if (tmp_file->decode_state) + { + free(tmp_file->decode_state); + tmp_file->decode_state = NULL; + } + + shn_load_seek_table(tmp_file,filename); + + if (NO_SEEK_TABLE != tmp_file->vars.seek_table_entries) + { + /* verify seek tables */ + + first_seek_table = (shn_seek_entry *)tmp_file->seek_table; + + if (tmp_file->vars.actual_bitshift != shn_uchar_to_ushort_le(first_seek_table->data+22)) + { + /* initial bitshift value in the file does not match the first bitshift value of the first seektable entry - seeking is broken */ + shn_debug("Broken seek table detected (invalid bitshift) - seeking disabled for this file."); + tmp_file->vars.seek_table_entries = NO_SEEK_TABLE; + } + else if (tmp_file->vars.actual_nchan > 2) + { + /* nchan is greater than the number of such entries stored in a seek table entry - seeking won't work */ + shn_debug("Broken seek table detected (nchan %d not in range [1 .. 2]) - seeking disabled for this file.",tmp_file->vars.actual_nchan); + tmp_file->vars.seek_table_entries = NO_SEEK_TABLE; + } + else if (tmp_file->vars.actual_maxnlpc > 3) + { + /* maxnlpc is greater than the number of such entries stored in a seek table entry - seeking won't work */ + shn_debug("Broken seek table detected (maxnlpc %d not in range [0 .. 3]) - seeking disabled for this file.",tmp_file->vars.actual_maxnlpc); + tmp_file->vars.seek_table_entries = NO_SEEK_TABLE; + } + else if (tmp_file->vars.actual_nmean > 4) + { + /* nmean is greater than the number of such entries stored in a seek table entry - seeking won't work */ + shn_debug("Broken seek table detected (nmean %d not in range [0 .. 4]) - seeking disabled for this file.",tmp_file->vars.actual_nmean); + tmp_file->vars.seek_table_entries = NO_SEEK_TABLE; + } + else + { + /* seek table appears to be valid - now adjust byte offsets in seek table to match the file */ + tmp_file->vars.seek_offset += tmp_file->vars.initial_file_position - shn_uchar_to_ulong_le(first_seek_table->data+8); + + if (0 != tmp_file->vars.seek_offset) + { + shn_debug("Adjusting seek table offsets by %ld bytes due to mismatch between seek table values and input file - seeking might not work correctly.", + tmp_file->vars.seek_offset); + } + } + } + + shn_debug("Successfully loaded file: '%s'",filename); + + return tmp_file; +} + +#if 0 +void write_and_wait(shn_file *this_shn,int block_size) +{ + int bytes_to_write,bytes_in_block,i; + + if (this_shn->vars.bytes_in_buf < block_size) + return; + + bytes_in_block = min(this_shn->vars.bytes_in_buf, block_size); + + if (bytes_in_block <= 0) + return; + + bytes_to_write = bytes_in_block; + while ((bytes_to_write + bytes_in_block) <= this_shn->vars.bytes_in_buf) + bytes_to_write += bytes_in_block; + + shn_ip.add_vis_pcm(shn_ip.output->written_time(), (this_shn->wave_header.bits_per_sample == 16) ? FMT_S16_LE : FMT_U8, + this_shn->wave_header.channels, bytes_to_write, this_shn->vars.buffer); + + while(shn_ip.output->buffer_free() < bytes_to_write && this_shn->vars.going && this_shn->vars.seek_to == -1) + xmms_usleep(10000); + + if(this_shn->vars.going && this_shn->vars.seek_to == -1) { + if (shn_cfg.swap_bytes) + swap_bytes(this_shn, bytes_to_write); + shn_ip.output->write_audio(this_shn->vars.buffer, bytes_to_write); + } else + return; + + /* shift data from end of buffer to the front */ + this_shn->vars.bytes_in_buf -= bytes_to_write; + + for(i=0;i<this_shn->vars.bytes_in_buf;i++) + this_shn->vars.buffer[i] = this_shn->vars.buffer[i+bytes_to_write]; +} +#endif + +static const char * exts[] = { "shn", NULL }; +static const char *filetypes[] = { "Shorten", NULL }; + +// define plugin interface +static DB_decoder_t plugin = { + DB_PLUGIN_SET_API_VERSION + .plugin.version_major = 0, + .plugin.version_minor = 1, + .plugin.type = DB_PLUGIN_DECODER, + .plugin.id = "shn", + .plugin.name = "SHN player", + .plugin.descr = "SHN player based on xmms-shn", + .plugin.author = "Alexey Yakovenko", + .plugin.email = "waker@users.sourceforge.net", + .plugin.website = "http://deadbeef.sf.net", + .open = shn_open, + .init = shn_init, + .free = shn_free, + .read_int16 = shn_read_int16, + .seek = shn_seek, + .seek_sample = shn_seek_sample, + .insert = shn_insert, + .exts = exts, + .filetypes = filetypes +}; + +DB_plugin_t * +shn_load (DB_functions_t *api) { + deadbeef = api; + return DB_PLUGIN (&plugin); +} diff --git a/plugins/shn/shn.h b/plugins/shn/shn.h new file mode 100644 index 00000000..3f64a23c --- /dev/null +++ b/plugins/shn/shn.h @@ -0,0 +1,277 @@ +/* xmms-shn - a shorten (.shn) plugin for XMMS + * Copyright (C) 2000-2007 Jason Jordan <shnutils@freeshell.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * $Id: shn.h,v 1.27 2007/03/23 05:49:48 jason Exp $ + */ + +#ifndef _SHN_H +#define _SHN_H + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <unistd.h> +#include <sys/stat.h> +#include "../../deadbeef.h" + +extern DB_functions_t *deadbeef; + +#define shn_vsnprintf(a,b,c,d) vsnprintf(a,b,c,d) + +#define min(a,b) (((a)<(b))?(a):(b)) + +/* surely no headers will be this large. right? RIGHT? */ +#define OUT_BUFFER_SIZE 16384 + +#define BUF_SIZE 4096 + +#define ERROR_OUTPUT_DEVNULL 0 +#define ERROR_OUTPUT_STDERR 1 +#define ERROR_OUTPUT_WINDOW 2 + +#define SEEK_SUFFIX "skt" + +#define NO_SEEK_TABLE -1 + +#define SEEK_HEADER_SIGNATURE "SEEK" +#define SEEK_TRAILER_SIGNATURE "SHNAMPSK" + +#define SEEK_HEADER_SIZE 12 +#define SEEK_TRAILER_SIZE 12 +#define SEEK_ENTRY_SIZE 80 +#define SEEK_RESOLUTION 25600 + +#define WAVE_RIFF (0x46464952) /* 'RIFF' in little-endian */ +#define WAVE_WAVE (0x45564157) /* 'WAVE' in little-endian */ +#define WAVE_FMT (0x20746d66) /* ' fmt' in little-endian */ +#define WAVE_DATA (0x61746164) /* 'data' in little-endian */ + +#define AIFF_FORM (0x4D524F46) /* 'FORM' in little-endian */ + +#define WAVE_FORMAT_UNKNOWN (0x0000) +#define WAVE_FORMAT_PCM (0x0001) +#define WAVE_FORMAT_ADPCM (0x0002) +#define WAVE_FORMAT_IEEE_FLOAT (0x0003) +#define WAVE_FORMAT_ALAW (0x0006) +#define WAVE_FORMAT_MULAW (0x0007) +#define WAVE_FORMAT_OKI_ADPCM (0x0010) +#define WAVE_FORMAT_IMA_ADPCM (0x0011) +#define WAVE_FORMAT_DIGISTD (0x0015) +#define WAVE_FORMAT_DIGIFIX (0x0016) +#define WAVE_FORMAT_DOLBY_AC2 (0x0030) +#define WAVE_FORMAT_GSM610 (0x0031) +#define WAVE_FORMAT_ROCKWELL_ADPCM (0x003b) +#define WAVE_FORMAT_ROCKWELL_DIGITALK (0x003c) +#define WAVE_FORMAT_G721_ADPCM (0x0040) +#define WAVE_FORMAT_G728_CELP (0x0041) +#define WAVE_FORMAT_MPEG (0x0050) +#define WAVE_FORMAT_MPEGLAYER3 (0x0055) +#define WAVE_FORMAT_G726_ADPCM (0x0064) +#define WAVE_FORMAT_G722_ADPCM (0x0065) + +#define CD_BLOCK_SIZE (2352) +#define CD_BLOCKS_PER_SEC (75) +#define CD_MIN_BURNABLE_SIZE (705600) +#define CD_CHANNELS (2) +#define CD_SAMPLES_PER_SEC (44100) +#define CD_BITS_PER_SAMPLE (16) +#define CD_RATE (176400) + +#define CANONICAL_HEADER_SIZE (44) + +#define PROBLEM_NOT_CD_QUALITY (0x00000001) +#define PROBLEM_CD_BUT_BAD_BOUND (0x00000002) +#define PROBLEM_CD_BUT_TOO_SHORT (0x00000004) +#define PROBLEM_HEADER_NOT_CANONICAL (0x00000008) +#define PROBLEM_EXTRA_CHUNKS (0x00000010) +#define PROBLEM_HEADER_INCONSISTENT (0x00000020) + +#define PROB_NOT_CD(f) ((f.problems) & (PROBLEM_NOT_CD_QUALITY)) +#define PROB_BAD_BOUND(f) ((f.problems) & (PROBLEM_CD_BUT_BAD_BOUND)) +#define PROB_TOO_SHORT(f) ((f.problems) & (PROBLEM_CD_BUT_TOO_SHORT)) +#define PROB_HDR_NOT_CANONICAL(f) ((f.problems) & (PROBLEM_HEADER_NOT_CANONICAL)) +#define PROB_EXTRA_CHUNKS(f) ((f.problems) & (PROBLEM_EXTRA_CHUNKS)) +#define PROB_HDR_INCONSISTENT(f) ((f.problems) & (PROBLEM_HEADER_INCONSISTENT)) + +typedef struct _shn_config +{ + int error_output_method; + char *error_output_method_config_name; + char *seek_tables_path; + char *seek_tables_path_config_name; + char *relative_seek_tables_path; + char *relative_seek_tables_path_config_name; + int verbose; + char *verbose_config_name; + int swap_bytes; + char *swap_bytes_config_name; + int load_textfiles; + char *load_textfiles_config_name; + char *textfile_extensions; + char *textfile_extensions_config_name; +} shn_config; + +typedef struct _shn_decode_state +{ + uchar *getbuf; + uchar *getbufp; + int nbitget; + int nbyteget; + ulong gbuffer; + schar *writebuf; + schar *writefub; + int nwritebuf; +} shn_decode_state; + +typedef struct _shn_seek_header +{ + uchar data[SEEK_HEADER_SIZE]; + slong version; + ulong shnFileSize; +} shn_seek_header; + +typedef struct _shn_seek_trailer +{ + uchar data[SEEK_TRAILER_SIZE]; + ulong seekTableSize; +} shn_seek_trailer; + +typedef struct _shn_seek_entry +{ + uchar data[SEEK_ENTRY_SIZE]; +} shn_seek_entry; + +/* old way, kept for reference. + (changed because some compilers apparently don't support #pragma pack(1)) + +typedef struct _shn_seek_header +{ + char signature[4]; + unsigned long version; + unsigned long shnFileSize; +} shn_seek_header; + +typedef struct _shn_seek_trailer +{ + unsigned long seekTableSize; + char signature[8]; +} shn_seek_trailer; + +typedef struct _shn_seek_entry +{ + unsigned long shnSample; + unsigned long shnByteOffset; + unsigned long shnLastPosition; + unsigned short shnByteGet; + unsigned short shnBufferOffset; + unsigned short shnBitOffset; + unsigned long shnGBuffer; + unsigned short shnBitShift; + long cbuf0[3]; + long cbuf1[3]; + long offset0[4]; + long offset1[4]; +} shn_seek_entry; +*/ + +typedef struct _shn_wave_header +{ + const char *filename; + char m_ss[16]; + + uint header_size; + + ushort channels, + block_align, + bits_per_sample, + wave_format; + + ulong samples_per_sec, + avg_bytes_per_sec, + rate, + length, + data_size, + total_size, + chunk_size, + actual_size; + + double exact_length; + + int file_has_id3v2_tag; + long id3v2_tag_size; + + ulong problems; +} shn_wave_header; + +typedef struct _shn_vars +{ + DB_FILE *fd; + int seek_to; + int eof; + int going; + slong seek_table_entries; + ulong seek_resolution; + int bytes_in_buf; + uchar buffer[OUT_BUFFER_SIZE]; + int bytes_in_header; + uchar header[OUT_BUFFER_SIZE]; + int fatal_error; + schar fatal_error_msg[BUF_SIZE]; + int reading_function_code; + ulong last_file_position; + ulong last_file_position_no_really; + ulong initial_file_position; + ulong bytes_read; + unsigned short actual_bitshift; + int actual_maxnlpc; + int actual_nmean; + int actual_nchan; + long seek_offset; +} shn_vars; + +typedef struct _shn_file +{ + shn_vars vars; + shn_decode_state *decode_state; + shn_wave_header wave_header; + shn_seek_header seek_header; + shn_seek_trailer seek_trailer; + shn_seek_entry *seek_table; +} shn_file; + +extern shn_config shn_cfg; + +extern shn_seek_entry *shn_seek_entry_search(shn_seek_entry *,ulong,ulong,ulong,ulong); +extern void shn_load_seek_table(shn_file *,const char *); +extern void shn_unload(shn_file *); +extern int shn_verify_header(shn_file *); +extern int shn_filename_contains_a_dot(const char *); +extern char *shn_get_base_filename(const char *); +extern char *shn_get_base_directory(const char *); +extern void shn_length_to_str(shn_file *); +extern char *shn_format_to_str(ushort); +extern ulong shn_uchar_to_ulong_le(uchar *); +extern slong shn_uchar_to_slong_le(uchar *); +extern ushort shn_uchar_to_ushort_le(uchar *); +extern void shn_debug(char *, ...); +extern void shn_error(char *, ...); +extern void shn_error_fatal(shn_file *,char *, ...); +extern void shn_snprintf(char *,int,char *, ...); + +#endif diff --git a/plugins/shn/shorten.c b/plugins/shn/shorten.c new file mode 100644 index 00000000..0c92af83 --- /dev/null +++ b/plugins/shn/shorten.c @@ -0,0 +1,54 @@ +/****************************************************************************** +* * +* Copyright (C) 1992-1995 Tony Robinson * +* * +* See the file doc/LICENSE.shorten for conditions on distribution and usage * +* * +******************************************************************************/ + +/* + * $Id: shorten.c,v 1.7 2003/08/26 05:34:04 jason Exp $ + */ + +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <setjmp.h> +#include "shorten.h" + +void init_offset(slong **offset,int nchan,int nblock,int ftype) +{ + slong mean = 0; + int chan, i; + + /* initialise offset */ + switch(ftype) + { + case TYPE_AU1: + case TYPE_S8: + case TYPE_S16HL: + case TYPE_S16LH: + case TYPE_ULAW: + case TYPE_AU2: + case TYPE_AU3: + case TYPE_ALAW: + mean = 0; + break; + case TYPE_U8: + mean = 0x80; + break; + case TYPE_U16HL: + case TYPE_U16LH: + mean = 0x8000; + break; + default: + shn_debug("Unknown file type: %d", ftype); + } + + for(chan = 0; chan < nchan; chan++) + for(i = 0; i < nblock; i++) + offset[chan][i] = mean; +} diff --git a/plugins/shn/shorten.h b/plugins/shn/shorten.h new file mode 100644 index 00000000..006b9bee --- /dev/null +++ b/plugins/shn/shorten.h @@ -0,0 +1,222 @@ +/****************************************************************************** +* * +* Copyright (C) 1992-1995 Tony Robinson * +* * +* See the file doc/LICENSE.shorten for conditions on distribution and usage * +* * +******************************************************************************/ + +/* + * $Id: shorten.h,v 1.4 2001/12/30 05:12:04 jason Exp $ + */ + +#ifndef _SHORTEN_H +#define _SHORTEN_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdlib.h> +#include <pthread.h> + +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#else +# if SIZEOF_UNSIGNED_LONG == 4 +# define uint32_t unsigned long +# define int32_t long +# else +# define uint32_t unsigned int +# define int32_t int +# endif +# define uint16_t unsigned short +# define uint8_t unsigned char +# define int16_t short +# define int8_t char +#endif + +#undef ulong +#undef ushort +#undef uchar +#undef slong +#undef sshort +#undef schar +#define ulong uint32_t +#define ushort uint16_t +#define uchar uint8_t +#define slong int32_t +#define sshort int16_t +#define schar int8_t + +#include "shn.h" + +extern shn_file *shnfile; + +#define MAGIC "ajkg" +#define FORMAT_VERSION 2 +#define MIN_SUPPORTED_VERSION 1 +#define MAX_SUPPORTED_VERSION 3 +#define MAX_VERSION 7 + +#define UNDEFINED_UINT -1 +#define DEFAULT_BLOCK_SIZE 256 +#define DEFAULT_V0NMEAN 0 +#define DEFAULT_V2NMEAN 4 +#define DEFAULT_MAXNLPC 0 +#define DEFAULT_NCHAN 1 +#define DEFAULT_NSKIP 0 +#define DEFAULT_NDISCARD 0 +#define NBITPERLONG 32 +#define DEFAULT_MINSNR 256 +#define DEFAULT_MAXRESNSTR "32.0" +#define DEFAULT_QUANTERROR 0 +#define MINBITRATE 2.5 + +#define MAX_LPC_ORDER 64 +#define CHANSIZE 0 +#define ENERGYSIZE 3 +#define BITSHIFTSIZE 2 +#define NWRAP 3 + +#define FNSIZE 2 +#define FN_DIFF0 0 +#define FN_DIFF1 1 +#define FN_DIFF2 2 +#define FN_DIFF3 3 +#define FN_QUIT 4 +#define FN_BLOCKSIZE 5 +#define FN_BITSHIFT 6 +#define FN_QLPC 7 +#define FN_ZERO 8 +#define FN_VERBATIM 9 + +#define VERBATIM_CKSIZE_SIZE 5 /* a var_put code size */ +#define VERBATIM_BYTE_SIZE 8 /* code size 8 on single bytes means + * no compression at all */ +#define VERBATIM_CHUNK_MAX 256 /* max. size of a FN_VERBATIM chunk */ + +#define ULONGSIZE 2 +#define NSKIPSIZE 1 +#define LPCQSIZE 2 +#define LPCQUANT 5 +#define XBYTESIZE 7 + +#define TYPESIZE 4 +#define TYPE_AU1 0 /* original lossless ulaw */ +#define TYPE_S8 1 /* signed 8 bit characters */ +#define TYPE_U8 2 /* unsigned 8 bit characters */ +#define TYPE_S16HL 3 /* signed 16 bit shorts: high-low */ +#define TYPE_U16HL 4 /* unsigned 16 bit shorts: high-low */ +#define TYPE_S16LH 5 /* signed 16 bit shorts: low-high */ +#define TYPE_U16LH 6 /* unsigned 16 bit shorts: low-high */ +#define TYPE_ULAW 7 /* lossy ulaw: internal conversion to linear */ +#define TYPE_AU2 8 /* new ulaw with zero mapping */ +#define TYPE_AU3 9 /* lossless alaw */ +#define TYPE_ALAW 10 /* lossy alaw: internal conversion to linear */ +#define TYPE_RIFF_WAVE 11 /* Microsoft .WAV files */ +#define TYPE_EOF 12 +#define TYPE_GENERIC_ULAW 128 +#define TYPE_GENERIC_ALAW 129 + +#define POSITIVE_ULAW_ZERO 0xff +#define NEGATIVE_ULAW_ZERO 0x7f + +#ifndef MAX_PATH +#define MAX_PATH 2048 +#endif + +#ifndef MIN +#define MIN(a,b) (((a)<(b))?(a):(b)) +#endif + +#ifndef MAX +#define MAX(a,b) (((a)>(b))?(a):(b)) +#endif + +#if defined(unix) && !defined(linux) +#define labs abs +#endif + +#define ROUNDEDSHIFTDOWN(x, n) (((n) == 0) ? (x) : ((x) >> ((n) - 1)) >> 1) + +#ifndef M_LN2 +#define M_LN2 0.69314718055994530942 +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +/* BUFSIZ must be a multiple of four to contain a whole number of words */ +#ifdef BUFSIZ +#undef BUFSIZ +#endif + +#define BUFSIZ 512 + +#define V2LPCQOFFSET (1 << LPCQUANT); + +#define UINT_GET(nbit, shnfile) \ + ((version == 0) ? uvar_get(nbit, shnfile) : ulong_get(shnfile)) + +#define putc_exit(val, stream)\ +{ char rval;\ + if((rval = putc((val), (stream))) != (char) (val))\ + complain("FATALERROR: write failed: putc returns EOF");\ +} + +extern int getc_exit_val; +#define getc_exit(stream)\ +(((getc_exit_val = getc(stream)) == EOF) ? \ + complain("FATALERROR: read failed: getc returns EOF"), 0: getc_exit_val) + +/************************/ +/* defined in shorten.c */ +extern void init_offset(slong**, int, int, int); +extern int shorten(FILE*, FILE*, int, char**); + +/**************************/ +/* defined in Sulawalaw.c */ +extern int Sulaw2lineartab[]; +#define Sulaw2linear(i) (Sulaw2lineartab[i]) +#ifndef Sulaw2linear +extern int Sulaw2linear(uchar); +#endif +extern uchar Slinear2ulaw(int); + +extern int Salaw2lineartab[]; +#define Salaw2linear(i) (Salaw2lineartab[i]) +#ifndef Salaw2linear +extern int Salaw2linear(uchar); +#endif +extern uchar Slinear2alaw(int); + +/**********************/ +/* defined in fixio.c */ +extern void init_sizeof_sample(void); +extern void fwrite_type_init(shn_file*); +extern void fwrite_type(slong**,int,int,int,shn_file*); +extern void fwrite_type_quit(shn_file*); +extern void fix_bitshift(slong*, int, int, int); + +/**********************/ +/* defined in vario.c */ +extern void var_get_init(shn_file*); +extern slong uvar_get(int, shn_file*); +extern slong var_get(int, shn_file*); +extern ulong ulong_get(shn_file*); +extern void var_get_quit(shn_file*); + +extern int sizeof_uvar(ulong, int); +extern int sizeof_var(slong, int); + +extern void mkmasktab(void); +extern ulong word_get(shn_file*); + +/**********************/ +/* defined in array.c */ +extern void* pmalloc(ulong, shn_file*); +extern slong** long2d(ulong, ulong, shn_file*); + +#endif diff --git a/plugins/shn/sulawalaw.c b/plugins/shn/sulawalaw.c new file mode 100644 index 00000000..61b417b8 --- /dev/null +++ b/plugins/shn/sulawalaw.c @@ -0,0 +1,192 @@ +/* + * $Id: sulawalaw.c,v 1.5 2001/12/30 05:12:04 jason Exp $ + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <math.h> +#include "shorten.h" + +int Sulaw2lineartab[] = {-32124, -31100, -30076, -29052, -28028, -27004, + -25980, -24956, -23932, -22908, -21884, -20860, -19836, -18812, + -17788, -16764, -15996, -15484, -14972, -14460, -13948, -13436, + -12924, -12412, -11900, -11388, -10876, -10364, -9852, -9340, -8828, + -8316, -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140, -5884, + -5628, -5372, -5116, -4860, -4604, -4348, -4092, -3900, -3772, -3644, + -3516, -3388, -3260, -3132, -3004, -2876, -2748, -2620, -2492, -2364, + -2236, -2108, -1980, -1884, -1820, -1756, -1692, -1628, -1564, -1500, + -1436, -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, -876, + -844, -812, -780, -748, -716, -684, -652, -620, -588, -556, -524, + -492, -460, -428, -396, -372, -356, -340, -324, -308, -292, -276, + -260, -244, -228, -212, -196, -180, -164, -148, -132, -120, -112, + -104, -96, -88, -80, -72, -64, -56, -48, -40, -32, -24, -16, -8, 0, + 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956, 23932, 22908, + 21884, 20860, 19836, 18812, 17788, 16764, 15996, 15484, 14972, 14460, + 13948, 13436, 12924, 12412, 11900, 11388, 10876, 10364, 9852, 9340, + 8828, 8316, 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140, 5884, + 5628, 5372, 5116, 4860, 4604, 4348, 4092, 3900, 3772, 3644, 3516, + 3388, 3260, 3132, 3004, 2876, 2748, 2620, 2492, 2364, 2236, 2108, + 1980, 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436, 1372, 1308, + 1244, 1180, 1116, 1052, 988, 924, 876, 844, 812, 780, 748, 716, 684, + 652, 620, 588, 556, 524, 492, 460, 428, 396, 372, 356, 340, 324, 308, + 292, 276, 260, 244, 228, 212, 196, 180, 164, 148, 132, 120, 112, 104, + 96, 88, 80, 72, 64, 56, 48, 40, 32, 24, 16, 8, 0}; + +#ifndef Sulaw2linear +#ifdef __STDC__ +int Sulaw2linear(uchar ulaw) { +#else +int Sulaw2linear(ulaw) uchar ulaw; { +#endif + return(Sulaw2lineartab[ulaw]); +} +#endif + +/* adapted by ajr for int input */ +#ifdef __STDC__ +uchar Slinear2ulaw(int sample) { +#else +uchar Slinear2ulaw(sample) int sample; { +#endif +/* +** This routine converts from linear to ulaw. +** +** Craig Reese: IDA/Supercomputing Research Center +** Joe Campbell: Department of Defense +** 29 September 1989 +** +** References: +** 1) CCITT Recommendation G.711 (very difficult to follow) +** 2) "A New Digital Technique for Implementation of Any +** Continuous PCM Companding Law," Villeret, Michel, +** et al. 1973 IEEE Int. Conf. on Communications, Vol 1, +** 1973, pg. 11.12-11.17 +** 3) MIL-STD-188-113,"Interoperability and Performance Standards +** for Analog-to_Digital Conversion Techniques," +** 17 February 1987 +** +** Input: Signed 16 bit linear sample +** Output: 8 bit ulaw sample +*/ + +#define BIAS 0x84 /* define the add-in bias for 16 bit samples */ +#define CLIP 32635 + + static int exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7}; + int sign, exponent, mantissa; + uchar ulawbyte; + + /* Get the sample into sign-magnitude. */ + if(sample < 0) { + sign = 0x80; + sample = -sample; + } + else + sign = 0; + + /* clip the magnitude */ + if(sample > CLIP) sample = CLIP; + + /* Convert from 16 bit linear to ulaw. */ + sample = sample + BIAS; + exponent = exp_lut[( sample >> 7 ) & 0xFF]; + mantissa = (sample >> (exponent + 3)) & 0x0F; + ulawbyte = ~(sign | (exponent << 4) | mantissa); + + return(ulawbyte); +} + + +/****************** + * ALAW starts here + */ + +int Salaw2lineartab[] = {-5504, -5248, -6016, -5760, -4480, -4224, + -4992, -4736, -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, + -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, -3776, -3648, + -4032, -3904, -3264, -3136, -3520, -3392, -22016, -20992, -24064, + -23040, -17920, -16896, -19968, -18944, -30208, -29184, -32256, + -31232, -26112, -25088, -28160, -27136, -11008, -10496, -12032, + -11520, -8960, -8448, -9984, -9472, -15104, -14592, -16128, -15616, + -13056, -12544, -14080, -13568, -344, -328, -376, -360, -280, -264, + -312, -296, -472, -456, -504, -488, -408, -392, -440, -424, -88, -72, + -120, -104, -24, -8, -56, -40, -216, -200, -248, -232, -152, -136, + -184, -168, -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184, + -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, -688, -656, + -752, -720, -560, -528, -624, -592, -944, -912, -1008, -976, -816, + -784, -880, -848, 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, + 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, 2752, 2624, 3008, + 2880, 2240, 2112, 2496, 2368, 3776, 3648, 4032, 3904, 3264, 3136, + 3520, 3392, 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, + 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, 11008, 10496, + 12032, 11520, 8960, 8448, 9984, 9472, 15104, 14592, 16128, 15616, + 13056, 12544, 14080, 13568, 344, 328, 376, 360, 280, 264, 312, 296, + 472, 456, 504, 488, 408, 392, 440, 424, 88, 72, 120, 104, 24, 8, 56, + 40, 216, 200, 248, 232, 152, 136, 184, 168, 1376, 1312, 1504, 1440, + 1120, 1056, 1248, 1184, 1888, 1824, 2016, 1952, 1632, 1568, 1760, + 1696, 688, 656, 752, 720, 560, 528, 624, 592, 944, 912, 1008, 976, + 816, 784, 880, 848}; + +#ifndef Salaw2linear +#ifdef __STDC__ +int Salaw2linear(uchar alaw) { +#else +int Salaw2linear(alaw) uchar alaw; { +#endif + return(Salaw2lineartab[alaw]); +} +#endif + +/* this is derived from the Sun code - it is a bit simpler and has int input */ +#define QUANT_MASK (0xf) /* Quantization field mask. */ +#define NSEGS (8) /* Number of A-law segments. */ +#define SEG_SHIFT (4) /* Left shift for segment number. */ +#ifdef __STDC__ +uchar Slinear2alaw(int linear) { +#else +uchar Slinear2alaw(linear) int linear; { +#endif + int seg; + uchar aval, mask; + static sshort seg_aend[NSEGS] = {0x1f,0x3f,0x7f,0xff,0x1ff,0x3ff,0x7ff,0xfff}; + + linear = linear >> 3; + + if(linear >= 0) { + mask = 0xd5; /* sign (7th) bit = 1 */ + } else { + mask = 0x55; /* sign bit = 0 */ + linear = -linear - 1; + } + + /* Convert the scaled magnitude to segment number. */ + for(seg = 0; seg < NSEGS && linear > seg_aend[seg]; seg++); + + /* Combine the sign, segment, and quantization bits. */ + if(seg >= NSEGS) /* out of range, return maximum value. */ + return (uchar) (0x7F ^ mask); + else { + aval = (uchar) seg << SEG_SHIFT; + if (seg < 2) + aval |= (linear >> 1) & QUANT_MASK; + else + aval |= (linear >> seg) & QUANT_MASK; + return (aval ^ mask); + } +} diff --git a/plugins/shn/vario.c b/plugins/shn/vario.c new file mode 100644 index 00000000..988e2eb8 --- /dev/null +++ b/plugins/shn/vario.c @@ -0,0 +1,146 @@ +/****************************************************************************** +* * +* Copyright (C) 1992-1995 Tony Robinson * +* * +* See the file doc/LICENSE.shorten for conditions on distribution and usage * +* * +******************************************************************************/ + +/* + * $Id: vario.c,v 1.10 2004/05/04 02:26:36 jason Exp $ + */ + +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include "shorten.h" + +#define MASKTABSIZE 33 +ulong masktab[MASKTABSIZE]; + +void mkmasktab() { + int i; + ulong val = 0; + + masktab[0] = val; + for(i = 1; i < MASKTABSIZE; i++) { + val <<= 1; + val |= 1; + masktab[i] = val; + } +} + +void var_get_init(shn_file *this_shn) +{ + mkmasktab(); + + this_shn->decode_state->getbuf = (uchar*) pmalloc((ulong) BUFSIZ,this_shn); + this_shn->decode_state->getbufp = this_shn->decode_state->getbuf; + this_shn->decode_state->nbyteget = 0; + this_shn->decode_state->gbuffer = 0; + this_shn->decode_state->nbitget = 0; +} + +ulong word_get(shn_file *this_shn) +{ + ulong buffer; + int bytes; + + if(this_shn->decode_state->nbyteget < 4) + { + this_shn->vars.last_file_position = this_shn->vars.bytes_read; + + bytes = deadbeef->fread((uchar*) this_shn->decode_state->getbuf, 1, BUFSIZ, this_shn->vars.fd); + this_shn->decode_state->nbyteget += bytes; + + if(this_shn->decode_state->nbyteget < 4) { + shn_error_fatal(this_shn,"Premature EOF on compressed stream -\npossible corrupt or truncated file"); + return (ulong)0; + } + + this_shn->vars.bytes_read += bytes; + + this_shn->decode_state->getbufp = this_shn->decode_state->getbuf; + } + + buffer = (((slong) (this_shn->decode_state->getbufp[0])) << 24) | (((slong) (this_shn->decode_state->getbufp[1])) << 16) | + (((slong) (this_shn->decode_state->getbufp[2])) << 8) | ((slong) (this_shn->decode_state->getbufp[3])); + + this_shn->decode_state->getbufp += 4; + this_shn->decode_state->nbyteget -= 4; + + return(buffer); +} + +slong uvar_get(int nbin,shn_file *this_shn) +{ + slong result; + + if (this_shn->vars.reading_function_code) { + this_shn->vars.last_file_position_no_really = this_shn->vars.last_file_position; + } + + if(this_shn->decode_state->nbitget == 0) + { + this_shn->decode_state->gbuffer = word_get(this_shn); + if (this_shn->vars.fatal_error) + return (ulong)0; + this_shn->decode_state->nbitget = 32; + } + + for(result = 0; !(this_shn->decode_state->gbuffer & (1L << --(this_shn->decode_state->nbitget))); result++) + { + if(this_shn->decode_state->nbitget == 0) + { + this_shn->decode_state->gbuffer = word_get(this_shn); + if (this_shn->vars.fatal_error) + return (ulong)0; + this_shn->decode_state->nbitget = 32; + } + } + + while(nbin != 0) + { + if(this_shn->decode_state->nbitget >= nbin) + { + result = (result << nbin) | ((this_shn->decode_state->gbuffer >> (this_shn->decode_state->nbitget-nbin)) &masktab[nbin]); + this_shn->decode_state->nbitget -= nbin; + nbin = 0; + } + else + { + result = (result << this_shn->decode_state->nbitget) | (this_shn->decode_state->gbuffer & masktab[this_shn->decode_state->nbitget]); + this_shn->decode_state->gbuffer = word_get(this_shn); + if (this_shn->vars.fatal_error) + return (ulong)0; + nbin -= this_shn->decode_state->nbitget; + this_shn->decode_state->nbitget = 32; + } + } + + return(result); +} + +ulong ulong_get(shn_file *this_shn) +{ + unsigned int nbit = uvar_get(ULONGSIZE,this_shn); + if (this_shn->vars.fatal_error) + return (ulong)0; + return(uvar_get(nbit,this_shn)); +} + +slong var_get(int nbin,shn_file *this_shn) +{ + ulong uvar = uvar_get(nbin + 1,this_shn); + if (this_shn->vars.fatal_error) + return (slong)0; + + if(uvar & 1) return((slong) ~(uvar >> 1)); + else return((slong) (uvar >> 1)); +} + +void var_get_quit(shn_file *this_shn) +{ + free((void *) this_shn->decode_state->getbuf); + this_shn->decode_state->getbuf = NULL; +} diff --git a/plugins/shn/wave.c b/plugins/shn/wave.c new file mode 100644 index 00000000..a21a6941 --- /dev/null +++ b/plugins/shn/wave.c @@ -0,0 +1,264 @@ +/* wave.c - functions to parse and verify WAVE headers + * Copyright (C) 2000-2007 Jason Jordan <shnutils@freeshell.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * $Id: wave.c,v 1.13 2007/03/23 05:49:48 jason Exp $ + */ + +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <sys/stat.h> +#include "shorten.h" +#include "shn.h" + +int is_valid_file(shn_file *info) +/* determines whether the given filename (info->filename) is a regular file, and is readable */ +{ + struct stat sz; + FILE *f; + + if (0 != stat(info->wave_header.filename,&sz)) { + if (errno == ENOENT) + shn_error("cannot open '%s' because it does not exist",info->wave_header.filename); + else if (errno == EACCES) + shn_error("cannot open '%s' due to insufficient permissions",info->wave_header.filename); + else if (errno == EFAULT) + shn_error("cannot open '%s' due to bad address",info->wave_header.filename); + else if (errno == ENOMEM) + shn_error("cannot open '%s' because the kernel ran out of memory",info->wave_header.filename); + else if (errno == ENAMETOOLONG) + shn_error("cannot open '%s' because the file name is too long",info->wave_header.filename); + else + shn_error("cannot open '%s' due to an unknown problem",info->wave_header.filename); + return 0; + } + if (0 == S_ISREG(sz.st_mode)) { + if (S_ISLNK(sz.st_mode)) + shn_error("'%s' is a symbolic link, not a regular file",info->wave_header.filename); + else if (S_ISDIR(sz.st_mode)) + shn_error("'%s' is a directory, not a regular file",info->wave_header.filename); + else if (S_ISCHR(sz.st_mode)) + shn_error("'%s' is a character device, not a regular file",info->wave_header.filename); + else if (S_ISBLK(sz.st_mode)) + shn_error("'%s' is a block device, not a regular file",info->wave_header.filename); + else if (S_ISFIFO(sz.st_mode)) + shn_error("'%s' is a fifo, not a regular file",info->wave_header.filename); + else if (S_ISSOCK(sz.st_mode)) + shn_error("'%s' is a socket, not a regular file",info->wave_header.filename); + return 0; + } + info->wave_header.actual_size = (ulong)sz.st_size; + + if (NULL == (f = fopen(info->wave_header.filename,"rb"))) { + shn_error("could not open '%s': %s",info->wave_header.filename,strerror(errno)); + return 0; + } + fclose(f); + + return 1; +} + +int shn_verify_header(shn_file *this_shn) +{ + ulong l; + int cur = 0; + + if (0 == is_valid_file(this_shn)) + { + shn_debug("while processing '%s': something went wrong while opening this file, see above",this_shn->wave_header.filename); + return 0; + } + + if (this_shn->vars.bytes_in_header < CANONICAL_HEADER_SIZE) { + shn_debug("while processing '%s': header is only %d bytes (should be at least %d bytes)", + this_shn->wave_header.filename,this_shn->vars.bytes_in_header,CANONICAL_HEADER_SIZE); + return 0; + } + + if (WAVE_RIFF != shn_uchar_to_ulong_le(this_shn->vars.header+cur)) + { + if (AIFF_FORM == shn_uchar_to_ulong_le(this_shn->vars.header+cur)) + shn_debug("while processing '%s': file contains AIFF data, which is currently not supported",this_shn->wave_header.filename); + else + shn_debug("while processing '%s': WAVE header is missing RIFF tag - possible corrupt file",this_shn->wave_header.filename); + return 0; + } + cur += 4; + + this_shn->wave_header.chunk_size = shn_uchar_to_ulong_le(this_shn->vars.header+cur); + cur += 4; + + if (WAVE_WAVE != shn_uchar_to_ulong_le(this_shn->vars.header+cur)) + { + shn_debug("while processing '%s': WAVE header is missing WAVE tag",this_shn->wave_header.filename); + return 0; + } + cur += 4; + + for (;;) + { + cur += 4; + + l = shn_uchar_to_ulong_le(this_shn->vars.header+cur); + cur += 4; + + if (WAVE_FMT == shn_uchar_to_ulong_le(this_shn->vars.header+cur-8)) + break; + + cur += l; + } + + if (l < 16) + { + shn_debug("while processing '%s': fmt chunk in WAVE header was too short",this_shn->wave_header.filename); + return 0; + } + + this_shn->wave_header.wave_format = shn_uchar_to_ushort_le(this_shn->vars.header+cur); + cur += 2; + + switch (this_shn->wave_header.wave_format) + { + case WAVE_FORMAT_PCM: + break; + default: + shn_debug("while processing '%s': unsupported format 0x%04x (%s) - only PCM data is supported at this time", + this_shn->wave_header.filename,this_shn->wave_header.wave_format,shn_format_to_str(this_shn->wave_header.wave_format)); + return 0; + } + + this_shn->wave_header.channels = shn_uchar_to_ushort_le(this_shn->vars.header+cur); + cur += 2; + this_shn->wave_header.samples_per_sec = shn_uchar_to_ulong_le(this_shn->vars.header+cur); + cur += 4; + this_shn->wave_header.avg_bytes_per_sec = shn_uchar_to_ulong_le(this_shn->vars.header+cur); + cur += 4; + this_shn->wave_header.block_align = shn_uchar_to_ushort_le(this_shn->vars.header+cur); + cur += 2; + this_shn->wave_header.bits_per_sample = shn_uchar_to_ushort_le(this_shn->vars.header+cur); + cur += 2; + + if (this_shn->wave_header.bits_per_sample != 8 && this_shn->wave_header.bits_per_sample != 16) + { + shn_debug("while processing '%s': bits per sample is neither 8 nor 16",this_shn->wave_header.filename); + return 0; + } + + l -= 16; + + if (l > 0) + cur += l; + + for (;;) + { + cur += 4; + + l = shn_uchar_to_ulong_le(this_shn->vars.header+cur); + cur += 4; + + if (WAVE_DATA == shn_uchar_to_ulong_le(this_shn->vars.header+cur-8)) + break; + + cur += l; + } + + this_shn->wave_header.rate = ((uint)this_shn->wave_header.samples_per_sec * + (uint)this_shn->wave_header.channels * + (uint)this_shn->wave_header.bits_per_sample) / 8; + this_shn->wave_header.header_size = cur; + this_shn->wave_header.data_size = l; + this_shn->wave_header.total_size = this_shn->wave_header.chunk_size + 8; + this_shn->wave_header.length = this_shn->wave_header.data_size / this_shn->wave_header.rate; + this_shn->wave_header.exact_length = (double)this_shn->wave_header.data_size / (double)this_shn->wave_header.rate; + + if (this_shn->wave_header.channels == CD_CHANNELS && + this_shn->wave_header.bits_per_sample == CD_BITS_PER_SAMPLE && + this_shn->wave_header.samples_per_sec == CD_SAMPLES_PER_SEC && + this_shn->wave_header.avg_bytes_per_sec == CD_RATE && + this_shn->wave_header.rate == CD_RATE) + { + if (this_shn->wave_header.data_size < CD_MIN_BURNABLE_SIZE) + this_shn->wave_header.problems |= PROBLEM_CD_BUT_TOO_SHORT; + if (this_shn->wave_header.data_size % CD_BLOCK_SIZE != 0) + this_shn->wave_header.problems |= PROBLEM_CD_BUT_BAD_BOUND; + } + else + this_shn->wave_header.problems |= PROBLEM_NOT_CD_QUALITY; + + if (this_shn->wave_header.header_size != CANONICAL_HEADER_SIZE) + this_shn->wave_header.problems |= PROBLEM_HEADER_NOT_CANONICAL; + + if ((ulong)this_shn->wave_header.header_size + this_shn->wave_header.data_size > this_shn->wave_header.total_size) + this_shn->wave_header.problems |= PROBLEM_HEADER_INCONSISTENT; + + if ((ulong)this_shn->wave_header.header_size + this_shn->wave_header.data_size < this_shn->wave_header.total_size) + this_shn->wave_header.problems |= PROBLEM_EXTRA_CHUNKS; + + shn_length_to_str(this_shn); + + /* header looks ok */ + return 1; +} + +char *shn_format_to_str(ushort format) +{ + switch (format) { + case WAVE_FORMAT_UNKNOWN: + return "Microsoft Official Unknown"; + case WAVE_FORMAT_PCM: + return "Microsoft PCM"; + case WAVE_FORMAT_ADPCM: + return "Microsoft ADPCM"; + case WAVE_FORMAT_IEEE_FLOAT: + return "IEEE Float"; + case WAVE_FORMAT_ALAW: + return "Microsoft A-law"; + case WAVE_FORMAT_MULAW: + return "Microsoft U-law"; + case WAVE_FORMAT_OKI_ADPCM: + return "OKI ADPCM format"; + case WAVE_FORMAT_IMA_ADPCM: + return "IMA ADPCM"; + case WAVE_FORMAT_DIGISTD: + return "Digistd format"; + case WAVE_FORMAT_DIGIFIX: + return "Digifix format"; + case WAVE_FORMAT_DOLBY_AC2: + return "Dolby AC2"; + case WAVE_FORMAT_GSM610: + return "GSM 6.10"; + case WAVE_FORMAT_ROCKWELL_ADPCM: + return "Rockwell ADPCM"; + case WAVE_FORMAT_ROCKWELL_DIGITALK: + return "Rockwell DIGITALK"; + case WAVE_FORMAT_G721_ADPCM: + return "G.721 ADPCM"; + case WAVE_FORMAT_G728_CELP: + return "G.728 CELP"; + case WAVE_FORMAT_MPEG: + return "MPEG"; + case WAVE_FORMAT_MPEGLAYER3: + return "MPEG Layer 3"; + case WAVE_FORMAT_G726_ADPCM: + return "G.726 ADPCM"; + case WAVE_FORMAT_G722_ADPCM: + return "G.722 ADPCM"; + } + return "Unknown"; +} |