1 diff -urN src-0.8.22/src/Makefile.in src-0.8.22-mmu/src/Makefile.in
2 --- src-0.8.22/src/Makefile.in 2001-11-19 13:34:18.000000000 +0100
3 +++ src-0.8.22-mmu/src/Makefile.in 2003-07-25 12:11:11.000000000 +0200
6 INCLUDES=-I. -I@top_srcdir@/src/include/
8 -OBJS = main.o newcpu.o memory.o @CPUOBJS@ custom.o cia.o serial.o blitter.o \
9 +OBJS = main.o newcpu.o mmu.o memory.o @CPUOBJS@ custom.o cia.o serial.o blitter.o \
10 autoconf.o ersatz.o filesys.o hardfile.o keybuf.o expansion.o zfile.o \
11 fpp.o readcpu.o cpudefs.o gfxutil.o gfxlib.o blitfunc.o blittable.o \
12 disk.o audio.o compiler.o uaelib.o drawing.o picasso96.o cpustbl.o \
14 $(MAKE) -C tools build68kc
16 $(MAKE) -C tools cpuopti
18 +tools/gencpu: gencpu.c
19 $(MAKE) -C tools gencpu
23 cpudefs.c: tools/build68k @top_srcdir@/src/table68k
24 ./tools/build68k <@top_srcdir@/src/table68k >cpudefs.c
26 -cpuemu.c: tools/gencpu
27 +cpuemu.c: tools/gencpu @top_srcdir@/src/table68k
30 # gencpu also creates cpustbl.c and cputbl.h
33 +cpustbl.c: cpuemu.c @top_srcdir@/src/table68k
34 +cputbl.h: cpuemu.c @top_srcdir@/src/table68k
36 -cpufast.s: cpuemu.c tools/cpuopti
37 +cpufast.s: cpuemu.c tools/cpuopti @top_srcdir@/src/table68k
38 $(CC) $(INCLUDES) -S $(INCDIRS) $(CFLAGS) $(X_CFLAGS) $(DEBUGFLAGS) $(NO_SCHED_CFLAGS) $< -o cputmp.s
39 ./tools/cpuopti <cputmp.s >$@
41 diff -urN src-0.8.22/src/custom.c src-0.8.22-mmu/src/custom.c
42 --- src-0.8.22/src/custom.c 2002-04-07 15:47:50.000000000 +0200
43 +++ src-0.8.22-mmu/src/custom.c 2003-07-25 12:13:07.000000000 +0200
52 @@ -4514,8 +4515,10 @@
53 uae_u16 rval = (value << 8) | (value & 0xFF);
54 special_mem |= S_WRITE;
55 custom_wput (addr, rval);
57 - write_log ("Byte put to custom register.\n"), warned++;
58 + if (!warned || ((addr & 0xff0000) == 0xda0000)) {
59 + write_log ("Byte put to custom register (addr=%lx val=%lx)\n", addr, value);
64 void REGPARAM2 custom_lput(uaecptr addr, uae_u32 value)
65 diff -urN src-0.8.22/src/custom.c~ src-0.8.22-mmu/src/custom.c~
66 --- src-0.8.22/src/custom.c~ 1970-01-01 01:00:00.000000000 +0100
67 +++ src-0.8.22-mmu/src/custom.c~ 2003-07-25 12:11:11.000000000 +0200
70 + * UAE - The Un*x Amiga Emulator
72 + * Custom chip emulation
74 + * Copyright 1995-2002 Bernd Schmidt
75 + * Copyright 1995 Alessandro Bissacco
76 + * Copyright 2000-2002 Toni Wilen
79 +#include "sysconfig.h"
87 +#include "threaddep/thread.h"
89 +#include "gensound.h"
90 +#include "sounddep/sound.h"
99 +#include "joystick.h"
104 +#include "autoconf.h"
106 +#include "picasso96.h"
107 +#include "drawing.h"
108 +#include "savestate.h"
110 +#define SPRITE_COLLISIONS
112 +static uae_u16 last_custom_value;
114 +static unsigned int n_consecutive_skipped = 0;
115 +static unsigned int total_skipped = 0;
117 +/* Mouse and joystick emulation */
120 +static int mouse_x, mouse_y;
121 +int joy0button, joy1button;
122 +unsigned int joy0dir, joy1dir;
126 +unsigned long int currcycle, nextevent, is_lastline;
127 +static int rpt_did_reset;
128 +struct ev eventtab[ev_max];
130 +frame_time_t vsynctime, vsyncmintime;
134 +static int next_lineno;
135 +static enum nln_how nextline_how;
136 +static int lof_changed = 0;
138 +static uae_u32 sprtaba[256],sprtabb[256];
139 +static uae_u32 sprite_ab_merge[256];
140 +/* Tables for collision detection. */
141 +static uae_u32 sprclx[16], clxmask[16];
144 + * Hardware registers of all sorts.
147 +static void custom_wput_1 (int, uaecptr, uae_u32) REGPARAM;
149 +static uae_u16 cregs[256];
151 +uae_u16 intena,intreq;
153 +uae_u16 adkcon; /* used by audio code */
155 +static uae_u32 cop1lc,cop2lc,copcon;
157 +int maxhpos = MAXHPOS_PAL;
158 +int maxvpos = MAXVPOS_PAL;
159 +int minfirstline = MINFIRSTLINE_PAL;
160 +int vblank_endline = VBLANK_ENDLINE_PAL;
161 +int vblank_hz = VBLANK_HZ_PAL;
162 +unsigned long syncbase;
164 +static unsigned int beamcon0, new_beamcon0;
166 +#define MAX_SPRITES 8
168 +/* This is but an educated guess. It seems to be correct, but this stuff
169 + * isn't documented well. */
170 +enum sprstate { SPR_restart, SPR_waiting_start, SPR_waiting_stop };
178 + enum sprstate state;
181 +static struct sprite spr[8];
183 +static int sprite_vblank_endline = 25;
185 +static unsigned int sprctl[MAX_SPRITES], sprpos[MAX_SPRITES];
186 +static uae_u16 sprdata[MAX_SPRITES][4], sprdatb[MAX_SPRITES][4];
187 +static int sprite_last_drawn_at[MAX_SPRITES];
188 +static int last_sprite_point, nr_armed;
189 +static int sprite_width, sprres, sprite_buffer_res;
191 +static uae_u32 bpl1dat, bpl2dat, bpl3dat, bpl4dat, bpl5dat, bpl6dat, bpl7dat, bpl8dat;
192 +static uae_s16 bpl1mod, bpl2mod;
194 +static uaecptr bplpt[8];
195 +uae_u8 *real_bplpt[8];
196 +/* Used as a debugging aid, to offset any bitplane temporarily. */
199 +/*static int blitcount[256]; blitter debug */
201 +static struct color_entry current_colors;
202 +static unsigned int bplcon0, bplcon1, bplcon2, bplcon3, bplcon4;
203 +static unsigned int diwstrt, diwstop, diwhigh;
204 +static int diwhigh_written;
205 +static unsigned int ddfstrt, ddfstop;
207 +/* The display and data fetch windows */
211 + DIW_waiting_start, DIW_waiting_stop
214 +static int plffirstline, plflastline;
215 +static int plfstrt, plfstop;
216 +static int last_diw_pix_hpos, last_ddf_pix_hpos, last_decide_line_hpos;
217 +static int last_fetch_hpos, last_sprite_hpos;
218 +int diwfirstword, diwlastword;
219 +static enum diw_states diwstate, hdiwstate;
221 +/* Sprite collisions */
222 +static unsigned int clxdat, clxcon, clxcon2, clxcon_bpl_enable, clxcon_bpl_match;
223 +static int clx_sprmask;
225 +enum copper_states {
243 + /* The current instruction words. */
244 + unsigned int i1, i2;
245 + unsigned int saved_i1, saved_i2;
246 + enum copper_states state;
247 + /* Instruction pointer. */
248 + uaecptr ip, saved_ip;
250 + unsigned int ignore_next;
253 + /* When we schedule a copper event, knowing a few things about the future
254 + of the copper list can reduce the number of sync_with_cpu calls
256 + unsigned int first_sync;
257 + unsigned int regtypes_modified;
260 +#define REGTYPE_NONE 0
261 +#define REGTYPE_COLOR 1
262 +#define REGTYPE_SPRITE 2
263 +#define REGTYPE_PLANE 4
264 +#define REGTYPE_BLITTER 8
265 +#define REGTYPE_JOYPORT 16
266 +#define REGTYPE_DISK 32
267 +#define REGTYPE_POS 64
268 +#define REGTYPE_AUDIO 128
270 +#define REGTYPE_ALL 255
271 +/* Always set in regtypes_modified, to enable a forced update when things like
272 + DMACON, BPLCON0, COPJMPx get written. */
273 +#define REGTYPE_FORCE 256
276 +static unsigned int regtypes[512];
278 +static struct copper cop_state;
279 +static int copper_enabled_thisline;
280 +static int cop_min_waittime;
286 +/* Used also by bebox.cpp */
287 +unsigned long int msecs = 0, frametime = 0, lastframetime = 0, timeframes = 0;
288 +static unsigned long int seconds_base;
292 +#define DEBUG_COPPER 0
294 +/* 10000 isn't enough! */
295 +#define NR_COPPER_RECORDS 40000
297 +#define NR_COPPER_RECORDS 1
300 +/* Record copper activity for the debugger. */
306 +static struct cop_record cop_record[2][NR_COPPER_RECORDS];
307 +static int nr_cop_records[2];
308 +static int curr_cop_set;
310 +/* Recording of custom chip register changes. */
311 +static int current_change_set;
313 +#ifdef OS_WITHOUT_MEMORY_MANAGEMENT
314 +/* sam: Those arrays uses around 7Mb of BSS... That seems */
315 +/* too much for AmigaDOS (uae crashes as soon as one loads */
316 +/* it. So I use a different strategy here (realloc the */
317 +/* arrays when needed. That strategy might be usefull for */
318 +/* computer with low memory. */
319 +struct sprite_entry *sprite_entries[2];
320 +struct color_change *color_changes[2];
321 +static int max_sprite_entry = 400;
322 +static int delta_sprite_entry = 0;
323 +static int max_color_change = 400;
324 +static int delta_color_change = 0;
326 +struct sprite_entry sprite_entries[2][MAX_SPR_PIXELS / 16];
327 +struct color_change color_changes[2][MAX_REG_CHANGE];
330 +struct decision line_decisions[2 * (MAXVPOS + 1) + 1];
331 +struct draw_info line_drawinfo[2][2 * (MAXVPOS + 1) + 1];
332 +struct color_entry color_tables[2][(MAXVPOS + 1) * 2];
334 +static int next_sprite_entry = 0;
335 +static int prev_next_sprite_entry;
336 +static int next_sprite_forced = 1;
338 +struct sprite_entry *curr_sprite_entries, *prev_sprite_entries;
339 +struct color_change *curr_color_changes, *prev_color_changes;
340 +struct draw_info *curr_drawinfo, *prev_drawinfo;
341 +struct color_entry *curr_color_tables, *prev_color_tables;
343 +static int next_color_change;
344 +static int next_color_entry, remembered_color_entry;
345 +static int color_src_match, color_dest_match, color_compare_result;
347 +static uae_u32 thisline_changed;
350 +#define MARK_LINE_CHANGED do { thisline_changed = 1; } while (0)
352 +#define MARK_LINE_CHANGED do { ; } while (0)
355 +static struct decision thisline_decision;
356 +static int passed_plfstop, fetch_cycle;
368 +uae_u32 get_copper_address (int copno)
371 + case 1: return cop1lc;
372 + case 2: return cop2lc;
377 +STATIC_INLINE void record_copper (uaecptr addr, int hpos, int vpos)
380 + int t = nr_cop_records[curr_cop_set];
381 + if (t < NR_COPPER_RECORDS) {
382 + cop_record[curr_cop_set][t].addr = addr;
383 + cop_record[curr_cop_set][t].hpos = hpos;
384 + cop_record[curr_cop_set][t].vpos = vpos;
385 + nr_cop_records[curr_cop_set] = t + 1;
390 +int find_copper_record (uaecptr addr, int *phpos, int *pvpos)
392 + int s = curr_cop_set ^ 1;
393 + int t = nr_cop_records[s];
395 + for (i = 0; i < t; i++) {
396 + if (cop_record[s][i].addr == addr) {
397 + *phpos = cop_record[s][i].hpos;
398 + *pvpos = cop_record[s][i].vpos;
405 +int rpt_available = 0;
407 +void reset_frame_rate_hack (void)
409 + if (currprefs.m68k_speed != -1)
412 + if (! rpt_available) {
413 + currprefs.m68k_speed = 0;
419 + vsyncmintime = read_processor_time() + vsynctime;
420 + write_log ("Resetting frame rate hack\n");
423 +void check_prefs_changed_custom (void)
425 + currprefs.gfx_framerate = changed_prefs.gfx_framerate;
426 + /* Not really the right place... */
427 + if (currprefs.jport0 != changed_prefs.jport0
428 + || currprefs.jport1 != changed_prefs.jport1) {
429 + currprefs.jport0 = changed_prefs.jport0;
430 + currprefs.jport1 = changed_prefs.jport1;
431 + joystick_setting_changed ();
433 + currprefs.immediate_blits = changed_prefs.immediate_blits;
434 + currprefs.blits_32bit_enabled = changed_prefs.blits_32bit_enabled;
435 + currprefs.collision_level = changed_prefs.collision_level;
436 + currprefs.fast_copper = changed_prefs.fast_copper;
439 +STATIC_INLINE void setclr (uae_u16 *p, uae_u16 val)
442 + *p |= val & 0x7FFF;
447 +__inline__ int current_hpos (void)
449 + return (get_cycles () - eventtab[ev_hsync].oldcycles) / CYCLE_UNIT;
452 +STATIC_INLINE uae_u8 *pfield_xlateptr (uaecptr plpt, int bytecount)
454 + if (!chipmem_bank.check (plpt, bytecount)) {
455 + static int count = 0;
457 + count++, write_log ("Warning: Bad playfield pointer\n");
460 + return chipmem_bank.xlateaddr (plpt);
463 +STATIC_INLINE void docols (struct color_entry *colentry)
467 + if (currprefs.chipset_mask & CSMASK_AGA) {
468 + for (i = 0; i < 256; i++) {
469 + int v = color_reg_get (colentry, i);
470 + if (v < 0 || v > 16777215)
472 + colentry->acolors[i] = CONVERT_RGB (v);
475 + for (i = 0; i < 32; i++) {
476 + int v = color_reg_get (colentry, i);
477 + if (v < 0 || v > 4095)
479 + colentry->acolors[i] = xcolors[v];
484 +void notice_new_xcolors (void)
488 + docols(¤t_colors);
489 +/* docols(&colors_for_drawing);*/
490 + for (i = 0; i < (MAXVPOS + 1)*2; i++) {
491 + docols(color_tables[0]+i);
492 + docols(color_tables[1]+i);
496 +static void do_sprites (int currhp);
498 +static void remember_ctable (void)
500 + if (remembered_color_entry == -1) {
501 + /* The colors changed since we last recorded a color map. Record a
503 + color_reg_cpy (curr_color_tables + next_color_entry, ¤t_colors);
504 + remembered_color_entry = next_color_entry++;
506 + thisline_decision.ctable = remembered_color_entry;
507 + if (color_src_match == -1 || color_dest_match != remembered_color_entry
508 + || line_decisions[next_lineno].ctable != color_src_match)
510 + /* The remembered comparison didn't help us - need to compare again. */
511 + int oldctable = line_decisions[next_lineno].ctable;
514 + if (oldctable == -1) {
516 + color_src_match = color_dest_match = -1;
518 + color_compare_result = color_reg_cmp (&prev_color_tables[oldctable], ¤t_colors) != 0;
519 + if (color_compare_result)
521 + color_src_match = oldctable;
522 + color_dest_match = remembered_color_entry;
524 + thisline_changed |= changed;
526 + /* We know the result of the comparison */
527 + if (color_compare_result)
528 + thisline_changed = 1;
532 +static void remember_ctable_for_border (void)
534 + remember_ctable ();
537 +/* Called to determine the state of the horizontal display window state
538 + * machine at the current position. It might have changed since we last
540 +static void decide_diw (int hpos)
542 + int pix_hpos = coord_diw_to_window_x (hpos * 2);
543 + if (hdiwstate == DIW_waiting_start && thisline_decision.diwfirstword == -1
544 + && pix_hpos >= diwfirstword && last_diw_pix_hpos < diwfirstword)
546 + thisline_decision.diwfirstword = diwfirstword < 0 ? 0 : diwfirstword;
547 + hdiwstate = DIW_waiting_stop;
548 + thisline_decision.diwlastword = -1;
550 + if (hdiwstate == DIW_waiting_stop && thisline_decision.diwlastword == -1
551 + && pix_hpos >= diwlastword && last_diw_pix_hpos < diwlastword)
553 + thisline_decision.diwlastword = diwlastword < 0 ? 0 : diwlastword;
554 + hdiwstate = DIW_waiting_start;
556 + last_diw_pix_hpos = pix_hpos;
559 +/* The HRM says 0xD8, but that can't work... */
560 +#define HARD_DDF_STOP (0xD4)
562 +static void finish_playfield_line (void)
566 + /* The latter condition might be able to happen in interlaced frames. */
567 + if (vpos >= minfirstline && (thisframe_first_drawn_line == -1 || vpos < thisframe_first_drawn_line))
568 + thisframe_first_drawn_line = vpos;
569 + thisframe_last_drawn_line = vpos;
571 + if ((currprefs.chipset_mask & CSMASK_AGA) && (fmode & 0x4000)) {
572 + if (((diwstrt >> 8) ^ vpos) & 1)
581 + if (dmaen (DMA_BITPLANE))
582 + switch (GET_PLANES (bplcon0)) {
583 + case 8: bplpt[7] += m2;
584 + case 7: bplpt[6] += m1;
585 + case 6: bplpt[5] += m2;
586 + case 5: bplpt[4] += m1;
587 + case 4: bplpt[3] += m2;
588 + case 3: bplpt[2] += m1;
589 + case 2: bplpt[1] += m2;
590 + case 1: bplpt[0] += m1;
593 + /* These are for comparison. */
594 + thisline_decision.bplcon0 = bplcon0;
595 + thisline_decision.bplcon2 = bplcon2;
596 + thisline_decision.bplcon3 = bplcon3;
597 + thisline_decision.bplcon4 = bplcon4;
600 + if (line_decisions[next_lineno].plflinelen != thisline_decision.plflinelen
601 + || line_decisions[next_lineno].plfleft != thisline_decision.plfleft
602 + || line_decisions[next_lineno].bplcon0 != thisline_decision.bplcon0
603 + || line_decisions[next_lineno].bplcon2 != thisline_decision.bplcon2
604 + || line_decisions[next_lineno].bplcon3 != thisline_decision.bplcon3
605 + || line_decisions[next_lineno].bplcon4 != thisline_decision.bplcon4
607 +#endif /* SMART_UPDATE */
608 + thisline_changed = 1;
611 +static int fetchmode;
613 +/* The fetch unit mainly controls ddf stop. It's the number of cycles that
614 + are contained in an indivisible block during which ddf is active. E.g.
615 + if DDF starts at 0x30, and fetchunit is 8, then possible DDF stops are
617 +static int fetchunit, fetchunit_mask;
618 +/* The delay before fetching the same bitplane again. Can be larger than
619 + the number of bitplanes; in that case there are additional empty cycles
620 + with no data fetch (this happens for high fetchmodes and low
622 +static int fetchstart, fetchstart_shift, fetchstart_mask;
623 +/* fm_maxplane holds the maximum number of planes possible with the current
624 + fetch mode. This selects the cycle diagram:
628 +static int fm_maxplane, fm_maxplane_shift;
630 +/* The corresponding values, by fetchmode and display resolution. */
631 +static int fetchunits[] = { 8,8,8,0, 16,8,8,0, 32,16,8,0 };
632 +static int fetchstarts[] = { 3,2,1,0, 4,3,2,0, 5,4,3,0 };
633 +static int fm_maxplanes[] = { 3,2,1,0, 3,3,2,0, 3,3,3,0 };
635 +static int cycle_diagram_table[3][3][9][32];
636 +static int *curr_diagram;
637 +static int cycle_sequences[3*8] = { 2,1,2,1,2,1,2,1, 4,2,3,1,4,2,3,1, 8,4,6,2,7,3,5,1 };
639 +static void debug_cycle_diagram(void)
641 + int fm, res, planes, cycle, v;
644 + for (fm = 0; fm < 3; fm++) {
645 + write_log ("FMODE %d\n=======\n", fm);
646 + for (res = 0; res <= 2; res++) {
647 + for (planes = 0; planes <= 8; planes++) {
648 + write_log("%d: ",planes);
649 + for (cycle = 0; cycle < 32; cycle++) {
650 + v=cycle_diagram_table[fm][res][planes][cycle];
651 + if (v==0) aa='-'; else if(v>0) aa='1'; else aa='X';
652 + write_log("%c",aa);
662 +static void create_cycle_diagram_table(void)
664 + int fm, res, cycle, planes, v;
665 + int fetch_start, max_planes;
666 + int *cycle_sequence;
668 + for (fm = 0; fm <= 2; fm++) {
669 + for (res = 0; res <= 2; res++) {
670 + max_planes = fm_maxplanes[fm * 4 + res];
671 + fetch_start = 1 << fetchstarts[fm * 4 + res];
672 + cycle_sequence = &cycle_sequences[(max_planes - 1) * 8];
673 + max_planes = 1 << max_planes;
674 + for (planes = 0; planes <= 8; planes++) {
675 + for (cycle = 0; cycle < 32; cycle++)
676 + cycle_diagram_table[fm][res][planes][cycle] = -1;
677 + if (planes <= max_planes) {
678 + for (cycle = 0; cycle < fetch_start; cycle++) {
679 + if (cycle < max_planes && planes >= cycle_sequence[cycle & 7]) {
684 + cycle_diagram_table[fm][res][planes][cycle] = v;
691 + debug_cycle_diagram ();
696 +/* Used by the copper. */
697 +static int estimated_last_fetch_cycle;
698 +static int cycle_diagram_shift;
700 +static void estimate_last_fetch_cycle (int hpos)
702 + int fetchunit = fetchunits[fetchmode * 4 + GET_RES (bplcon0)];
704 + if (! passed_plfstop) {
705 + int stop = plfstop < hpos || plfstop > HARD_DDF_STOP ? HARD_DDF_STOP : plfstop;
706 + /* We know that fetching is up-to-date up until hpos, so we can use fetch_cycle. */
707 + int fetch_cycle_at_stop = fetch_cycle + (stop - hpos);
708 + int starting_last_block_at = (fetch_cycle_at_stop + fetchunit - 1) & ~(fetchunit - 1);
710 + estimated_last_fetch_cycle = hpos + (starting_last_block_at - fetch_cycle) + fetchunit;
712 + int starting_last_block_at = (fetch_cycle + fetchunit - 1) & ~(fetchunit - 1);
713 + if (passed_plfstop == 2)
714 + starting_last_block_at -= fetchunit;
716 + estimated_last_fetch_cycle = hpos + (starting_last_block_at - fetch_cycle) + fetchunit;
720 +static uae_u32 outword[MAX_PLANES];
721 +static int out_nbits, out_offs;
722 +static uae_u32 todisplay[MAX_PLANES][4];
723 +static uae_u32 fetched[MAX_PLANES];
724 +static uae_u32 fetched_aga0[MAX_PLANES];
725 +static uae_u32 fetched_aga1[MAX_PLANES];
727 +/* Expansions from bplcon0/bplcon1. */
728 +static int toscr_res, toscr_delay1, toscr_delay2, toscr_nr_planes, fetchwidth;
730 +/* The number of bits left from the last fetched words.
731 + This is an optimization - conceptually, we have to make sure the result is
732 + the same as if toscr is called in each clock cycle. However, to speed this
733 + up, we accumulate display data; this variable keeps track of how much.
734 + Thus, once we do call toscr_nbits (which happens at least every 16 bits),
735 + we can do more work at once. */
736 +static int toscr_nbits;
738 +static int delayoffset;
740 +STATIC_INLINE void compute_delay_offset (int hpos)
742 + /* this fixes most horizontal scrolling jerkyness but can't be correct */
743 + delayoffset = ((hpos - fm_maxplane - 0x18) & fetchstart_mask) << 1;
745 + if (delayoffset & 8)
747 + else if (delayoffset & 16)
749 + else if (delayoffset & 32)
755 +static void expand_fmodes (void)
757 + int res = GET_RES(bplcon0);
758 + int fm = fetchmode;
759 + fetchunit = fetchunits[fm * 4 + res];
760 + fetchunit_mask = fetchunit - 1;
761 + fetchstart_shift = fetchstarts[fm * 4 + res];
762 + fetchstart = 1 << fetchstart_shift;
763 + fetchstart_mask = fetchstart - 1;
764 + fm_maxplane_shift = fm_maxplanes[fm * 4 + res];
765 + fm_maxplane = 1 << fm_maxplane_shift;
768 +static int maxplanes_ocs[]={ 6,4,0,0 };
769 +static int maxplanes_ecs[]={ 6,4,2,0 };
770 +static int maxplanes_aga[]={ 8,4,2,0, 8,8,4,0, 8,8,8,0 };
772 +/* Expand bplcon0/bplcon1 into the toscr_xxx variables. */
773 +static void compute_toscr_delay_1 (void)
775 + int delay1 = (bplcon1 & 0x0f) | ((bplcon1 & 0x0c00) >> 6);
776 + int delay2 = ((bplcon1 >> 4) & 0x0f) | (((bplcon1 >> 4) & 0x0c00) >> 6);
778 + int fetchwidth = 16 << fetchmode;
780 + delay1 += delayoffset;
781 + delay2 += delayoffset;
782 + delaymask = (fetchwidth - 1) >> toscr_res;
783 + toscr_delay1 = (delay1 & delaymask) << toscr_res;
784 + toscr_delay2 = (delay2 & delaymask) << toscr_res;
787 +static void compute_toscr_delay (int hpos)
792 + if (currprefs.chipset_mask & CSMASK_AGA)
793 + planes = maxplanes_aga;
794 + else if (! (currprefs.chipset_mask & CSMASK_ECS_DENISE))
795 + planes = maxplanes_ocs;
797 + planes = maxplanes_ecs;
798 + /* Disable bitplane DMA if planes > maxplanes. This is needed e.g. by the
799 + Sanity WOC demo (at the "Party Effect"). */
800 + if (GET_PLANES(v) > planes[fetchmode*4 + GET_RES (v)])
802 + toscr_res = GET_RES (v);
804 + toscr_nr_planes = GET_PLANES (v);
806 + compute_toscr_delay_1 ();
809 +STATIC_INLINE void maybe_first_bpl1dat (int hpos)
811 + if (thisline_decision.plfleft == -1) {
812 + thisline_decision.plfleft = hpos;
813 + compute_delay_offset (hpos);
814 + compute_toscr_delay_1 ();
818 +STATIC_INLINE void fetch (int nr, int fm)
821 + if (nr >= toscr_nr_planes)
823 + p = bplpt[nr] + bpl_off[nr];
826 + fetched[nr] = chipmem_wget (p);
830 + fetched_aga0[nr] = chipmem_lget (p);
834 + fetched_aga1[nr] = chipmem_lget (p);
835 + fetched_aga0[nr] = chipmem_lget (p + 4);
840 + fetch_state = fetch_was_plane0;
843 +static void clear_fetchbuffer (uae_u32 *ptr, int nwords)
847 + if (! thisline_changed)
848 + for (i = 0; i < nwords; i++)
850 + thisline_changed = 1;
854 + memset (ptr, 0, nwords * 4);
857 +static void update_toscr_planes (void)
859 + if (toscr_nr_planes > thisline_decision.nr_planes) {
861 + for (j = thisline_decision.nr_planes; j < toscr_nr_planes; j++)
862 + clear_fetchbuffer ((uae_u32 *)(line_data[next_lineno] + 2 * MAX_WORDS_PER_LINE * j), out_offs);
864 + if (thisline_decision.nr_planes > 0)
865 + printf ("Planes from %d to %d\n", thisline_decision.nr_planes, toscr_nr_planes);
867 + thisline_decision.nr_planes = toscr_nr_planes;
871 +STATIC_INLINE void toscr_3_ecs (int nbits)
873 + int delay1 = toscr_delay1;
874 + int delay2 = toscr_delay2;
876 + uae_u32 mask = 0xFFFF >> (16 - nbits);
878 + for (i = 0; i < toscr_nr_planes; i += 2) {
879 + outword[i] <<= nbits;
880 + outword[i] |= (todisplay[i][0] >> (16 - nbits + delay1)) & mask;
881 + todisplay[i][0] <<= nbits;
883 + for (i = 1; i < toscr_nr_planes; i += 2) {
884 + outword[i] <<= nbits;
885 + outword[i] |= (todisplay[i][0] >> (16 - nbits + delay2)) & mask;
886 + todisplay[i][0] <<= nbits;
890 +STATIC_INLINE void shift32plus (uae_u32 *p, int n)
894 + t |= p[0] >> (32 - n);
898 +STATIC_INLINE void aga_shift (uae_u32 *p, int n, int fm)
901 + shift32plus (p + 2, n);
902 + shift32plus (p + 1, n);
904 + shift32plus (p + 0, n);
908 +STATIC_INLINE void toscr_3_aga (int nbits, int fm)
910 + int delay1 = toscr_delay1;
911 + int delay2 = toscr_delay2;
913 + uae_u32 mask = 0xFFFF >> (16 - nbits);
916 + int offs = (16 << fm) - nbits + delay1;
917 + int off1 = offs >> 5;
921 + for (i = 0; i < toscr_nr_planes; i += 2) {
922 + uae_u32 t0 = todisplay[i][off1];
923 + uae_u32 t1 = todisplay[i][off1 + 1];
924 + uae_u64 t = (((uae_u64)t1) << 32) | t0;
925 + outword[i] <<= nbits;
926 + outword[i] |= (t >> offs) & mask;
927 + aga_shift (todisplay[i], nbits, fm);
931 + int offs = (16 << fm) - nbits + delay2;
932 + int off1 = offs >> 5;
936 + for (i = 1; i < toscr_nr_planes; i += 2) {
937 + uae_u32 t0 = todisplay[i][off1];
938 + uae_u32 t1 = todisplay[i][off1 + 1];
939 + uae_u64 t = (((uae_u64)t1) << 32) | t0;
940 + outword[i] <<= nbits;
941 + outword[i] |= (t >> offs) & mask;
942 + aga_shift (todisplay[i], nbits, fm);
947 +static void toscr_2_0 (int nbits) { toscr_3_ecs (nbits); }
948 +static void toscr_2_1 (int nbits) { toscr_3_aga (nbits, 1); }
949 +static void toscr_2_2 (int nbits) { toscr_3_aga (nbits, 2); }
951 +STATIC_INLINE void toscr_1 (int nbits, int fm)
965 + out_nbits += nbits;
966 + if (out_nbits == 32) {
968 + uae_u8 *dataptr = line_data[next_lineno] + out_offs * 4;
969 + /* Don't use toscr_nr_planes here; if the plane count drops during the
970 + line we still want the data to be correct for the full number of planes
971 + over the full width of the line. */
972 + for (i = 0; i < thisline_decision.nr_planes; i++) {
973 + uae_u32 *dataptr32 = (uae_u32 *)dataptr;
974 + if (*dataptr32 != outword[i])
975 + thisline_changed = 1;
976 + *dataptr32 = outword[i];
977 + dataptr += MAX_WORDS_PER_LINE * 2;
984 +static void toscr_fm0 (int);
985 +static void toscr_fm1 (int);
986 +static void toscr_fm2 (int);
988 +STATIC_INLINE void toscr (int nbits, int fm)
991 + case 0: toscr_fm0 (nbits); break;
992 + case 1: toscr_fm1 (nbits); break;
993 + case 2: toscr_fm2 (nbits); break;
997 +STATIC_INLINE void toscr_0 (int nbits, int fm)
1006 + t = 32 - out_nbits;
1011 + toscr_1 (nbits, fm);
1014 +static void toscr_fm0 (int nbits) { toscr_0 (nbits, 0); }
1015 +static void toscr_fm1 (int nbits) { toscr_0 (nbits, 1); }
1016 +static void toscr_fm2 (int nbits) { toscr_0 (nbits, 2); }
1018 +static int flush_plane_data (int fm)
1021 + int fetchwidth = 16 << fm;
1023 + if (out_nbits <= 16) {
1027 + if (out_nbits != 0) {
1028 + i += 32 - out_nbits;
1029 + toscr_1 (32 - out_nbits, fm);
1035 + return i >> (1 + toscr_res);
1038 +STATIC_INLINE void flush_display (int fm)
1040 + if (toscr_nbits > 0 && thisline_decision.plfleft != -1)
1041 + toscr (toscr_nbits, fm);
1045 +/* Called when all planes have been fetched, i.e. when a new block
1046 + of data is available to be displayed. The data in fetched[] is
1047 + moved into todisplay[]. */
1048 +STATIC_INLINE void beginning_of_plane_block (int pos, int dma, int fm)
1052 + flush_display (fm);
1055 + for (i = 0; i < MAX_PLANES; i++)
1056 + todisplay[i][0] |= fetched[i];
1058 + for (i = 0; i < MAX_PLANES; i++) {
1060 + todisplay[i][1] = fetched_aga1[i];
1061 + todisplay[i][0] = fetched_aga0[i];
1064 + maybe_first_bpl1dat (pos);
1071 +/* The usual inlining tricks - don't touch unless you know what you are doing. */
1072 +STATIC_INLINE void long_fetch_ecs (int plane, int nwords, int weird_number_of_bits, int dma)
1074 + uae_u16 *real_pt = (uae_u16 *)pfield_xlateptr (bplpt[plane] + bpl_off[plane], nwords * 2);
1075 + int delay = ((plane & 1) ? toscr_delay2 : toscr_delay1);
1076 + int tmp_nbits = out_nbits;
1077 + uae_u32 shiftbuffer = todisplay[plane][0];
1078 + uae_u32 outval = outword[plane];
1079 + uae_u32 fetchval = fetched[plane];
1080 + uae_u32 *dataptr = (uae_u32 *)(line_data[next_lineno] + 2 * plane * MAX_WORDS_PER_LINE + 4 * out_offs);
1083 + bplpt[plane] += nwords * 2;
1086 + /* @@@ Don't do this, fall back on chipmem_wget instead. */
1089 + while (nwords > 0) {
1090 + int bits_left = 32 - tmp_nbits;
1093 + shiftbuffer |= fetchval;
1095 + t = (shiftbuffer >> delay) & 0xFFFF;
1097 + if (weird_number_of_bits && bits_left < 16) {
1098 + outval <<= bits_left;
1099 + outval |= t >> (16 - bits_left);
1100 + thisline_changed |= *dataptr ^ outval;
1101 + *dataptr++ = outval;
1104 + tmp_nbits = 16 - bits_left;
1105 + shiftbuffer <<= 16;
1107 + outval = (outval << 16) | t;
1108 + shiftbuffer <<= 16;
1110 + if (tmp_nbits == 32) {
1111 + thisline_changed |= *dataptr ^ outval;
1112 + *dataptr++ = outval;
1118 + fetchval = do_get_mem_word (real_pt);
1122 + fetched[plane] = fetchval;
1123 + todisplay[plane][0] = shiftbuffer;
1124 + outword[plane] = outval;
1127 +STATIC_INLINE void long_fetch_aga (int plane, int nwords, int weird_number_of_bits, int fm, int dma)
1129 + uae_u32 *real_pt = (uae_u32 *)pfield_xlateptr (bplpt[plane] + bpl_off[plane], nwords * 2);
1130 + int delay = ((plane & 1) ? toscr_delay2 : toscr_delay1);
1131 + int tmp_nbits = out_nbits;
1132 + uae_u32 *shiftbuffer = todisplay[plane];
1133 + uae_u32 outval = outword[plane];
1134 + uae_u32 fetchval0 = fetched_aga0[plane];
1135 + uae_u32 fetchval1 = fetched_aga1[plane];
1136 + uae_u32 *dataptr = (uae_u32 *)(line_data[next_lineno] + 2 * plane * MAX_WORDS_PER_LINE + 4 * out_offs);
1137 + int offs = (16 << fm) - 16 + delay;
1138 + int off1 = offs >> 5;
1141 + offs -= off1 * 32;
1144 + bplpt[plane] += nwords * 2;
1147 + /* @@@ Don't do this, fall back on chipmem_wget instead. */
1150 + while (nwords > 0) {
1153 + shiftbuffer[0] = fetchval0;
1155 + shiftbuffer[1] = fetchval1;
1157 + for (i = 0; i < (1 << fm); i++) {
1158 + int bits_left = 32 - tmp_nbits;
1160 + uae_u32 t0 = shiftbuffer[off1];
1161 + uae_u32 t1 = shiftbuffer[off1 + 1];
1162 + uae_u64 t = (((uae_u64)t1) << 32) | t0;
1164 + t0 = (t >> offs) & 0xFFFF;
1166 + if (weird_number_of_bits && bits_left < 16) {
1167 + outval <<= bits_left;
1168 + outval |= t0 >> (16 - bits_left);
1170 + thisline_changed |= *dataptr ^ outval;
1171 + *dataptr++ = outval;
1174 + tmp_nbits = 16 - bits_left;
1175 + aga_shift (shiftbuffer, 16, fm);
1177 + outval = (outval << 16) | t0;
1178 + aga_shift (shiftbuffer, 16, fm);
1180 + if (tmp_nbits == 32) {
1181 + thisline_changed |= *dataptr ^ outval;
1182 + *dataptr++ = outval;
1188 + nwords -= 1 << fm;
1192 + fetchval0 = do_get_mem_long (real_pt);
1194 + fetchval1 = do_get_mem_long (real_pt);
1195 + fetchval0 = do_get_mem_long (real_pt + 1);
1200 + fetched_aga0[plane] = fetchval0;
1201 + fetched_aga1[plane] = fetchval1;
1202 + outword[plane] = outval;
1205 +static void long_fetch_ecs_0 (int hpos, int nwords, int dma) { long_fetch_ecs (hpos, nwords, 0, dma); }
1206 +static void long_fetch_ecs_1 (int hpos, int nwords, int dma) { long_fetch_ecs (hpos, nwords, 1, dma); }
1207 +static void long_fetch_aga_1_0 (int hpos, int nwords, int dma) { long_fetch_aga (hpos, nwords, 0, 1, dma); }
1208 +static void long_fetch_aga_1_1 (int hpos, int nwords, int dma) { long_fetch_aga (hpos, nwords, 1, 1, dma); }
1209 +static void long_fetch_aga_2_0 (int hpos, int nwords, int dma) { long_fetch_aga (hpos, nwords, 0, 2, dma); }
1210 +static void long_fetch_aga_2_1 (int hpos, int nwords, int dma) { long_fetch_aga (hpos, nwords, 1, 2, dma); }
1212 +static void do_long_fetch (int hpos, int nwords, int dma, int fm)
1217 + flush_display (fm);
1220 + if (out_nbits & 15) {
1221 + for (i = 0; i < toscr_nr_planes; i++)
1222 + long_fetch_ecs_1 (i, nwords, dma);
1224 + for (i = 0; i < toscr_nr_planes; i++)
1225 + long_fetch_ecs_0 (i, nwords, dma);
1229 + if (out_nbits & 15) {
1230 + for (i = 0; i < toscr_nr_planes; i++)
1231 + long_fetch_aga_1_1 (i, nwords, dma);
1233 + for (i = 0; i < toscr_nr_planes; i++)
1234 + long_fetch_aga_1_0 (i, nwords, dma);
1238 + if (out_nbits & 15) {
1239 + for (i = 0; i < toscr_nr_planes; i++)
1240 + long_fetch_aga_2_1 (i, nwords, dma);
1242 + for (i = 0; i < toscr_nr_planes; i++)
1243 + long_fetch_aga_2_0 (i, nwords, dma);
1248 + out_nbits += nwords * 16;
1249 + out_offs += out_nbits >> 5;
1252 + if (dma && toscr_nr_planes > 0)
1253 + fetch_state = fetch_was_plane0;
1258 +/* make sure fetch that goes beyond maxhpos is finished */
1259 +static void finish_final_fetch (int i, int fm)
1261 + passed_plfstop = 3;
1263 + if (thisline_decision.plfleft != -1) {
1264 + i += flush_plane_data (fm);
1265 + thisline_decision.plfright = i;
1266 + thisline_decision.plflinelen = out_offs;
1267 + thisline_decision.bplres = toscr_res;
1268 + finish_playfield_line ();
1272 +STATIC_INLINE int one_fetch_cycle_0 (int i, int ddfstop_to_test, int dma, int fm)
1274 + if (! passed_plfstop && i == ddfstop_to_test)
1275 + passed_plfstop = 1;
1277 + if ((fetch_cycle & fetchunit_mask) == 0) {
1278 + if (passed_plfstop == 2) {
1279 + finish_final_fetch (i, fm);
1282 + if (passed_plfstop)
1286 + /* fetchstart_mask can be larger than fm_maxplane if FMODE > 0. This means
1287 + that the remaining cycles are idle; we'll fall through the whole switch
1288 + without doing anything. */
1289 + int cycle_start = fetch_cycle & fetchstart_mask;
1290 + switch (fm_maxplane) {
1292 + switch (cycle_start) {
1293 + case 0: fetch (7, fm); break;
1294 + case 1: fetch (3, fm); break;
1295 + case 2: fetch (5, fm); break;
1296 + case 3: fetch (1, fm); break;
1297 + case 4: fetch (6, fm); break;
1298 + case 5: fetch (2, fm); break;
1299 + case 6: fetch (4, fm); break;
1300 + case 7: fetch (0, fm); break;
1304 + switch (cycle_start) {
1305 + case 0: fetch (3, fm); break;
1306 + case 1: fetch (1, fm); break;
1307 + case 2: fetch (2, fm); break;
1308 + case 3: fetch (0, fm); break;
1312 + switch (cycle_start) {
1313 + case 0: fetch (1, fm); break;
1314 + case 1: fetch (0, fm); break;
1320 + toscr_nbits += 2 << toscr_res;
1322 + if (toscr_nbits == 16)
1323 + flush_display (fm);
1324 + if (toscr_nbits > 16)
1330 +static int one_fetch_cycle_fm0 (int i, int ddfstop_to_test, int dma) { return one_fetch_cycle_0 (i, ddfstop_to_test, dma, 0); }
1331 +static int one_fetch_cycle_fm1 (int i, int ddfstop_to_test, int dma) { return one_fetch_cycle_0 (i, ddfstop_to_test, dma, 1); }
1332 +static int one_fetch_cycle_fm2 (int i, int ddfstop_to_test, int dma) { return one_fetch_cycle_0 (i, ddfstop_to_test, dma, 2); }
1334 +STATIC_INLINE int one_fetch_cycle (int i, int ddfstop_to_test, int dma, int fm)
1337 + case 0: return one_fetch_cycle_fm0 (i, ddfstop_to_test, dma);
1338 + case 1: return one_fetch_cycle_fm1 (i, ddfstop_to_test, dma);
1339 + case 2: return one_fetch_cycle_fm2 (i, ddfstop_to_test, dma);
1340 + default: abort ();
1344 +STATIC_INLINE void update_fetch (int until, int fm)
1347 + int dma = dmaen (DMA_BITPLANE);
1349 + int ddfstop_to_test;
1351 + if (framecnt != 0 || passed_plfstop == 3)
1354 + /* We need an explicit test against HARD_DDF_STOP here to guard against
1355 + programs that move the DDFSTOP before our current position before we
1357 + ddfstop_to_test = HARD_DDF_STOP;
1358 + if (ddfstop >= last_fetch_hpos && ddfstop < HARD_DDF_STOP)
1359 + ddfstop_to_test = ddfstop;
1361 + compute_toscr_delay (last_fetch_hpos);
1362 + update_toscr_planes ();
1364 + pos = last_fetch_hpos;
1365 + cycle_diagram_shift = (last_fetch_hpos - fetch_cycle) & fetchstart_mask;
1367 + /* First, a loop that prepares us for the speedup code. We want to enter
1368 + the SPEEDUP case with fetch_state == fetch_was_plane0, and then unroll
1369 + whole blocks, so that we end on the same fetch_state again. */
1371 + if (pos == until) {
1372 + if (until >= maxhpos && passed_plfstop == 2) {
1373 + finish_final_fetch (pos, fm);
1376 + flush_display (fm);
1380 + if (fetch_state == fetch_was_plane0)
1383 + fetch_state = fetch_started;
1384 + if (one_fetch_cycle (pos, ddfstop_to_test, dma, fm))
1389 + /* Unrolled version of the for loop below. */
1390 + if (! passed_plfstop
1392 + && (fetch_cycle & fetchstart_mask) == (fm_maxplane & fetchstart_mask)
1394 + /* @@@ We handle this case, but the code would be simpler if we
1395 + * disallowed it - it may even be possible to guarantee that
1396 + * this condition never is false. Later. */
1397 + && (out_nbits & 15) == 0
1399 + && toscr_nr_planes == thisline_decision.nr_planes)
1401 + int offs = (pos - fetch_cycle) & fetchunit_mask;
1402 + int ddf2 = ((ddfstop_to_test - offs + fetchunit - 1) & ~fetchunit_mask) + offs;
1403 + int ddf3 = ddf2 + fetchunit;
1404 + int stop = until < ddf2 ? until : until < ddf3 ? ddf2 : ddf3;
1407 + count = stop - pos;
1409 + if (count >= fetchstart) {
1410 + count &= ~fetchstart_mask;
1412 + if (thisline_decision.plfleft == -1) {
1413 + compute_delay_offset (pos);
1414 + compute_toscr_delay_1 ();
1416 + do_long_fetch (pos, count >> (3 - toscr_res), dma, fm);
1418 + /* This must come _after_ do_long_fetch so as not to confuse flush_display
1419 + into thinking the first fetch has produced any output worth emitting to
1420 + the screen. But the calculation of delay_offset must happen _before_. */
1421 + maybe_first_bpl1dat (pos);
1423 + if (pos <= ddfstop_to_test && pos + count > ddfstop_to_test)
1424 + passed_plfstop = 1;
1425 + if (pos <= ddfstop_to_test && pos + count > ddf2)
1426 + passed_plfstop = 2;
1428 + fetch_cycle += count;
1432 + for (; pos < until; pos++) {
1433 + if (fetch_state == fetch_was_plane0)
1434 + beginning_of_plane_block (pos, dma, fm);
1435 + fetch_state = fetch_started;
1437 + if (one_fetch_cycle (pos, ddfstop_to_test, dma, fm))
1440 + if (until >= maxhpos && passed_plfstop == 2) {
1441 + finish_final_fetch (pos, fm);
1444 + flush_display (fm);
1447 +static void update_fetch_0 (int hpos) { update_fetch (hpos, 0); }
1448 +static void update_fetch_1 (int hpos) { update_fetch (hpos, 1); }
1449 +static void update_fetch_2 (int hpos) { update_fetch (hpos, 2); }
1451 +STATIC_INLINE void decide_fetch (int hpos)
1453 + if (fetch_state != fetch_not_started && hpos > last_fetch_hpos) {
1454 + switch (fetchmode) {
1455 + case 0: update_fetch_0 (hpos); break;
1456 + case 1: update_fetch_1 (hpos); break;
1457 + case 2: update_fetch_2 (hpos); break;
1458 + default: abort ();
1461 + last_fetch_hpos = hpos;
1464 +/* This function is responsible for turning on datafetch if necessary. */
1465 +STATIC_INLINE void decide_line (int hpos)
1467 + if (hpos <= last_decide_line_hpos)
1469 + if (fetch_state != fetch_not_started)
1472 + /* Test if we passed the start of the DDF window. */
1473 + if (last_decide_line_hpos < plfstrt && hpos >= plfstrt) {
1474 + /* First, take care of the vertical DIW. Surprisingly enough, this seems to be
1475 + correct here - putting this into decide_diw() results in garbage. */
1476 + if (diwstate == DIW_waiting_start && vpos == plffirstline) {
1477 + diwstate = DIW_waiting_stop;
1479 + if (diwstate == DIW_waiting_stop && vpos == plflastline) {
1480 + diwstate = DIW_waiting_start;
1483 + /* If DMA isn't on by the time we reach plfstrt, then there's no
1484 + bitplane DMA at all for the whole line. */
1485 + if (dmaen (DMA_BITPLANE)
1486 + && diwstate == DIW_waiting_stop)
1488 + fetch_state = fetch_started;
1490 + last_fetch_hpos = plfstrt;
1495 + compute_toscr_delay (last_fetch_hpos);
1497 + /* If someone already wrote BPL1DAT, clear the area between that point and
1498 + the real fetch start. */
1499 + if (framecnt == 0) {
1500 + if (thisline_decision.plfleft != -1) {
1501 + out_nbits = (plfstrt - thisline_decision.plfleft) << (1 + toscr_res);
1502 + out_offs = out_nbits >> 5;
1505 + update_toscr_planes ();
1507 + estimate_last_fetch_cycle (plfstrt);
1508 + last_decide_line_hpos = hpos;
1509 + do_sprites (plfstrt);
1514 + if (last_decide_line_hpos < 0x34)
1515 + do_sprites (hpos);
1517 + last_decide_line_hpos = hpos;
1520 +/* Called when a color is about to be changed (write to a color register),
1521 + * but the new color has not been entered into the table yet. */
1522 +static void record_color_change (int hpos, int regno, unsigned long value)
1524 + if (regno == -1 && value) {
1525 + thisline_decision.ham_seen = 1;
1527 + thisline_decision.ham_at_start = 1;
1530 + /* Early positions don't appear on-screen. */
1531 + if (framecnt != 0 || vpos < minfirstline || hpos < 0x18
1532 + /*|| currprefs.emul_accuracy == 0*/)
1535 + decide_diw (hpos);
1536 + decide_line (hpos);
1538 + if (thisline_decision.ctable == -1)
1539 + remember_ctable ();
1541 +#ifdef OS_WITHOUT_MEMORY_MANAGEMENT
1542 + if (next_color_change >= max_color_change) {
1543 + ++delta_color_change;
1547 + curr_color_changes[next_color_change].linepos = hpos;
1548 + curr_color_changes[next_color_change].regno = regno;
1549 + curr_color_changes[next_color_change++].value = value;
1552 +typedef int sprbuf_res_t, cclockres_t, hwres_t, bplres_t;
1554 +static void do_playfield_collisions (void)
1556 + uae_u8 *ld = line_data[next_lineno];
1559 + if (clxcon_bpl_enable == 0) {
1564 + for (i = thisline_decision.plfleft; i < thisline_decision.plfright; i += 2) {
1566 + uae_u32 total = 0xFFFFFFFF;
1567 + for (j = 0; j < 8; j++) {
1569 + if ((clxcon_bpl_enable & (1 << j)) == 0)
1571 + else if (j < thisline_decision.nr_planes) {
1572 + t = *(uae_u32 *)(line_data[next_lineno] + 2 * i + 2 * j * MAX_WORDS_PER_LINE);
1573 + t ^= ~(((clxcon_bpl_match >> j) & 1) - 1);
1582 +/* Sprite-to-sprite collisions are taken care of in record_sprite. This one does
1583 + playfield/sprite collisions.
1584 + That's the theory. In practice this doesn't work yet. I also suspect this code
1585 + is way too slow. */
1586 +static void do_sprite_collisions (void)
1588 + int nr_sprites = curr_drawinfo[next_lineno].nr_sprites;
1589 + int first = curr_drawinfo[next_lineno].first_sprite_entry;
1591 + unsigned int collision_mask = clxmask[clxcon >> 12];
1592 + int bplres = GET_RES (bplcon0);
1593 + hwres_t ddf_left = thisline_decision.plfleft * 2 << bplres;
1594 + hwres_t hw_diwlast = coord_window_to_diw_x (thisline_decision.diwlastword);
1595 + hwres_t hw_diwfirst = coord_window_to_diw_x (thisline_decision.diwfirstword);
1597 + if (clxcon_bpl_enable == 0) {
1602 + for (i = 0; i < nr_sprites; i++) {
1603 + struct sprite_entry *e = curr_sprite_entries + first + i;
1605 + sprbuf_res_t minpos = e->pos;
1606 + sprbuf_res_t maxpos = e->max;
1607 + hwres_t minp1 = minpos >> sprite_buffer_res;
1608 + hwres_t maxp1 = maxpos >> sprite_buffer_res;
1610 + if (maxp1 > hw_diwlast)
1611 + maxpos = hw_diwlast << sprite_buffer_res;
1612 + if (maxp1 > thisline_decision.plfright * 2)
1613 + maxpos = thisline_decision.plfright * 2 << sprite_buffer_res;
1614 + if (minp1 < hw_diwfirst)
1615 + minpos = hw_diwfirst << sprite_buffer_res;
1616 + if (minp1 < thisline_decision.plfleft * 2)
1617 + minpos = thisline_decision.plfleft * 2 << sprite_buffer_res;
1619 + for (j = minpos; j < maxpos; j++) {
1620 + int sprpix = spixels[e->first_pixel + j - e->pos] & collision_mask;
1627 + offs = ((j << bplres) >> sprite_buffer_res) - ddf_left;
1628 + sprpix = sprite_ab_merge[sprpix & 255] | (sprite_ab_merge[sprpix >> 8] << 2);
1631 + /* Loop over number of playfields. */
1632 + for (k = 0; k < 2; k++) {
1635 + int planes = ((currprefs.chipset_mask & CSMASK_AGA) ? 8 : 6);
1637 + for (l = k; match && l < planes; l += 2) {
1638 + if (clxcon_bpl_enable & (1 << l)) {
1640 + if (l < thisline_decision.nr_planes) {
1641 + uae_u32 *ldata = (uae_u32 *)(line_data[next_lineno] + 2 * l * MAX_WORDS_PER_LINE);
1642 + uae_u32 word = ldata[offs >> 5];
1643 + t = (word >> (31 - (offs & 31))) & 1;
1645 + if (t != ((clxcon_bpl_match >> l) & 1))
1657 +static void expand_sprres (void)
1659 + switch ((bplcon3 >> 6) & 3) {
1660 + case 0: /* ECS defaults (LORES,HIRES=140ns,SHRES=70ns) */
1661 + if ((currprefs.chipset_mask & CSMASK_ECS_DENISE) && GET_RES (bplcon0) == RES_SUPERHIRES)
1662 + sprres = RES_HIRES;
1664 + sprres = RES_LORES;
1667 + sprres = RES_LORES;
1670 + sprres = RES_HIRES;
1673 + sprres = RES_SUPERHIRES;
1678 +STATIC_INLINE void record_sprite_1 (uae_u16 *buf, uae_u32 datab, int num, int dbl,
1679 + unsigned int mask, int do_collisions, uae_u32 collision_mask)
1683 + unsigned int tmp = *buf;
1684 + unsigned int col = (datab & 3) << (2 * num);
1686 + if ((j & mask) == 0)
1692 + if (do_collisions) {
1693 + tmp &= collision_mask;
1695 + unsigned int shrunk_tmp = sprite_ab_merge[tmp & 255] | (sprite_ab_merge[tmp >> 8] << 2);
1696 + clxdat |= sprclx[shrunk_tmp];
1702 +/* DATAB contains the sprite data; 16 pixels in two-bit packets. Bits 0/1
1703 + determine the color of the leftmost pixel, bits 2/3 the color of the next
1705 + This function assumes that for all sprites in a given line, SPRXP either
1706 + stays equal or increases between successive calls.
1708 + The data is recorded either in lores pixels (if ECS), or in hires pixels
1709 + (if AGA). No support for SHRES sprites. */
1711 +static void record_sprite (int line, int num, int sprxp, uae_u16 *data, uae_u16 *datb, unsigned int ctl)
1713 + struct sprite_entry *e = curr_sprite_entries + next_sprite_entry;
1717 + uae_u32 collision_mask;
1718 + int width = sprite_width;
1720 + unsigned int mask = 0;
1722 + if (sprres != RES_LORES)
1723 + thisline_decision.any_hires_sprites = 1;
1725 + if (currprefs.chipset_mask & CSMASK_AGA) {
1726 + width = (width << 1) >> sprres;
1727 + dbl = sprite_buffer_res - sprres;
1728 + mask = sprres == RES_SUPERHIRES ? 1 : 0;
1731 + /* Try to coalesce entries if they aren't too far apart. */
1732 + if (! next_sprite_forced && e[-1].max + 16 >= sprxp) {
1735 + next_sprite_entry++;
1737 + e->has_attached = 0;
1740 + if (sprxp < e->pos)
1743 + e->max = sprxp + width;
1744 + e[1].first_pixel = e->first_pixel + ((e->max - e->pos + 3) & ~3);
1745 + next_sprite_forced = 0;
1747 + collision_mask = clxmask[clxcon >> 12];
1748 + word_offs = e->first_pixel + sprxp - e->pos;
1750 + for (i = 0; i < sprite_width; i += 16) {
1751 + unsigned int da = *data;
1752 + unsigned int db = *datb;
1753 + uae_u32 datab = ((sprtaba[da & 0xFF] << 16) | sprtaba[da >> 8]
1754 + | (sprtabb[db & 0xFF] << 16) | sprtabb[db >> 8]);
1756 + buf = spixels + word_offs + (i << dbl);
1757 + if (currprefs.collision_level > 0 && collision_mask)
1758 + record_sprite_1 (buf, datab, num, dbl, mask, 1, collision_mask);
1760 + record_sprite_1 (buf, datab, num, dbl, mask, 0, collision_mask);
1765 + /* We have 8 bits per pixel in spixstate, two for every sprite pair. The
1766 + low order bit records whether the attach bit was set for this pair. */
1768 + if (ctl & (num << 7) & 0x80) {
1769 + uae_u32 state = 0x01010101 << (num - 1);
1770 + uae_u32 *stbuf = spixstate.words + (word_offs >> 2);
1771 + uae_u8 *stb1 = spixstate.bytes + word_offs;
1772 + for (i = 0; i < width; i += 8) {
1783 + e->has_attached = 1;
1787 +static void decide_sprites (int hpos)
1789 + int nrs[MAX_SPRITES], posns[MAX_SPRITES];
1791 + int point = hpos * 2;
1792 + int width = sprite_width;
1793 + int window_width = (width << lores_shift) >> sprres;
1795 + if (framecnt != 0 || hpos < 0x14 || nr_armed == 0 || point == last_sprite_point)
1798 + decide_diw (hpos);
1799 + decide_line (hpos);
1802 + /* This tries to detect whether the line is border, but that doesn't work, it's too early. */
1803 + if (thisline_decision.plfleft == -1)
1807 + for (i = 0; i < MAX_SPRITES; i++) {
1808 + int sprxp = spr[i].xpos;
1809 + int hw_xp = (sprxp >> sprite_buffer_res);
1810 + int window_xp = coord_hw_to_window_x (hw_xp) + (DIW_DDF_OFFSET << lores_shift);
1813 + if (! spr[i].armed || sprxp < 0 || hw_xp <= last_sprite_point || hw_xp > point)
1815 + if ((thisline_decision.diwfirstword >= 0 && window_xp + window_width < thisline_decision.diwfirstword)
1816 + || (thisline_decision.diwlastword >= 0 && window_xp > thisline_decision.diwlastword))
1819 + /* Sort the sprites in order of ascending X position before recording them. */
1820 + for (bestp = 0; bestp < count; bestp++) {
1821 + if (posns[bestp] > sprxp)
1823 + if (posns[bestp] == sprxp && nrs[bestp] < i)
1826 + for (j = count; j > bestp; j--) {
1827 + posns[j] = posns[j-1];
1828 + nrs[j] = nrs[j-1];
1834 + for (i = 0; i < count; i++) {
1836 + record_sprite (next_lineno, nr, spr[nr].xpos, sprdata[nr], sprdatb[nr], sprctl[nr]);
1838 + last_sprite_point = point;
1841 +STATIC_INLINE int sprites_differ (struct draw_info *dip, struct draw_info *dip_old)
1843 + struct sprite_entry *this_first = curr_sprite_entries + dip->first_sprite_entry;
1844 + struct sprite_entry *this_last = curr_sprite_entries + dip->last_sprite_entry;
1845 + struct sprite_entry *prev_first = prev_sprite_entries + dip_old->first_sprite_entry;
1849 + if (dip->nr_sprites != dip_old->nr_sprites)
1852 + if (dip->nr_sprites == 0)
1855 + for (i = 0; i < dip->nr_sprites; i++)
1856 + if (this_first[i].pos != prev_first[i].pos
1857 + || this_first[i].max != prev_first[i].max
1858 + || this_first[i].has_attached != prev_first[i].has_attached)
1861 + npixels = this_last->first_pixel + (this_last->max - this_last->pos) - this_first->first_pixel;
1862 + if (memcmp (spixels + this_first->first_pixel, spixels + prev_first->first_pixel,
1863 + npixels * sizeof (uae_u16)) != 0)
1865 + if (memcmp (spixstate.bytes + this_first->first_pixel, spixstate.bytes + prev_first->first_pixel, npixels) != 0)
1870 +STATIC_INLINE int color_changes_differ (struct draw_info *dip, struct draw_info *dip_old)
1872 + if (dip->nr_color_changes != dip_old->nr_color_changes)
1875 + if (dip->nr_color_changes == 0)
1877 + if (memcmp (curr_color_changes + dip->first_color_change,
1878 + prev_color_changes + dip_old->first_color_change,
1879 + dip->nr_color_changes * sizeof *curr_color_changes) != 0)
1884 +/* End of a horizontal scan line. Finish off all decisions that were not
1886 +static void finish_decisions (void)
1888 + struct draw_info *dip;
1889 + struct draw_info *dip_old;
1890 + struct decision *dp;
1892 + int hpos = current_hpos ();
1894 + if (framecnt != 0)
1897 + decide_diw (hpos);
1898 + decide_line (hpos);
1899 + decide_fetch (hpos);
1901 + if (thisline_decision.plfleft != -1 && thisline_decision.plflinelen == -1) {
1902 + if (fetch_state != fetch_not_started)
1904 + thisline_decision.plfright = thisline_decision.plfleft;
1905 + thisline_decision.plflinelen = 0;
1906 + thisline_decision.bplres = RES_LORES;
1909 + /* Large DIWSTOP values can cause the stop position never to be
1910 + * reached, so the state machine always stays in the same state and
1911 + * there's a more-or-less full-screen DIW. */
1912 + if (hdiwstate == DIW_waiting_stop || thisline_decision.diwlastword > max_diwlastword)
1913 + thisline_decision.diwlastword = max_diwlastword;
1915 + if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword)
1916 + MARK_LINE_CHANGED;
1917 + if (thisline_decision.diwlastword != line_decisions[next_lineno].diwlastword)
1918 + MARK_LINE_CHANGED;
1920 + dip = curr_drawinfo + next_lineno;
1921 + dip_old = prev_drawinfo + next_lineno;
1922 + dp = line_decisions + next_lineno;
1923 + changed = thisline_changed;
1925 + if (thisline_decision.plfleft != -1) {
1926 + record_diw_line (thisline_decision.diwfirstword, thisline_decision.diwlastword);
1928 + decide_sprites (hpos);
1931 + dip->last_sprite_entry = next_sprite_entry;
1932 + dip->last_color_change = next_color_change;
1934 + if (thisline_decision.ctable == -1) {
1935 + if (thisline_decision.plfleft == -1)
1936 + remember_ctable_for_border ();
1938 + remember_ctable ();
1941 + dip->nr_color_changes = next_color_change - dip->first_color_change;
1942 + dip->nr_sprites = next_sprite_entry - dip->first_sprite_entry;
1944 + if (thisline_decision.plfleft != line_decisions[next_lineno].plfleft)
1946 + if (! changed && color_changes_differ (dip, dip_old))
1948 + if (!changed && thisline_decision.plfleft != -1 && sprites_differ (dip, dip_old))
1952 + thisline_changed = 1;
1953 + *dp = thisline_decision;
1955 + /* The only one that may differ: */
1956 + dp->ctable = thisline_decision.ctable;
1959 +/* Set the state of all decisions to "undecided" for a new scanline. */
1960 +static void reset_decisions (void)
1962 + if (framecnt != 0)
1965 + thisline_decision.any_hires_sprites = 0;
1966 + thisline_decision.nr_planes = 0;
1968 + thisline_decision.plfleft = -1;
1969 + thisline_decision.plflinelen = -1;
1970 + thisline_decision.ham_seen = !! (bplcon0 & 0x800);
1971 + thisline_decision.ham_at_start = !! (bplcon0 & 0x800);
1973 + /* decided_res shouldn't be touched before it's initialized by decide_line(). */
1974 + thisline_decision.diwfirstword = -1;
1975 + thisline_decision.diwlastword = -2;
1976 + if (hdiwstate == DIW_waiting_stop) {
1977 + thisline_decision.diwfirstword = 0;
1978 + if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword)
1979 + MARK_LINE_CHANGED;
1981 + thisline_decision.ctable = -1;
1983 + thisline_changed = 0;
1984 + curr_drawinfo[next_lineno].first_color_change = next_color_change;
1985 + curr_drawinfo[next_lineno].first_sprite_entry = next_sprite_entry;
1986 + next_sprite_forced = 1;
1988 + /* memset(sprite_last_drawn_at, 0, sizeof sprite_last_drawn_at); */
1989 + last_sprite_point = 0;
1990 + fetch_state = fetch_not_started;
1991 + passed_plfstop = 0;
1993 + memset (todisplay, 0, sizeof todisplay);
1994 + memset (fetched, 0, sizeof fetched);
1995 + memset (fetched_aga0, 0, sizeof fetched_aga0);
1996 + memset (fetched_aga1, 0, sizeof fetched_aga1);
1997 + memset (outword, 0, sizeof outword);
1999 + last_decide_line_hpos = -1;
2000 + last_diw_pix_hpos = -1;
2001 + last_ddf_pix_hpos = -1;
2002 + last_sprite_hpos = -1;
2003 + last_fetch_hpos = -1;
2006 +void compute_vsynctime (void)
2008 + vsynctime = syncbase / vblank_hz;
2009 + if (currprefs.produce_sound > 1) {
2010 + vsynctime = vsynctime * 9 / 10;
2014 +/* set PAL or NTSC timing variables */
2016 +static void init_hz (void)
2020 + beamcon0 = new_beamcon0;
2022 + isntsc = beamcon0 & 0x20 ? 0 : 1;
2024 + maxvpos = MAXVPOS_PAL;
2025 + maxhpos = MAXHPOS_PAL;
2026 + minfirstline = MINFIRSTLINE_PAL;
2027 + vblank_endline = VBLANK_ENDLINE_PAL;
2028 + vblank_hz = VBLANK_HZ_PAL;
2030 + maxvpos = MAXVPOS_NTSC;
2031 + maxhpos = MAXHPOS_NTSC;
2032 + minfirstline = MINFIRSTLINE_NTSC;
2033 + vblank_endline = VBLANK_ENDLINE_NTSC;
2034 + vblank_hz = VBLANK_HZ_NTSC;
2036 + compute_vsynctime ();
2038 + write_log ("Using %s timing\n", isntsc ? "NTSC" : "PAL");
2041 +static void calcdiw (void)
2043 + int hstrt = diwstrt & 0xFF;
2044 + int hstop = diwstop & 0xFF;
2045 + int vstrt = diwstrt >> 8;
2046 + int vstop = diwstop >> 8;
2048 + if (diwhigh_written) {
2049 + hstrt |= ((diwhigh >> 5) & 1) << 8;
2050 + hstop |= ((diwhigh >> 13) & 1) << 8;
2051 + vstrt |= (diwhigh & 7) << 8;
2052 + vstop |= ((diwhigh >> 8) & 7) << 8;
2055 + if ((vstop & 0x80) == 0)
2059 + diwfirstword = coord_diw_to_window_x (hstrt);
2060 + diwlastword = coord_diw_to_window_x (hstop);
2061 + if (diwfirstword < 0)
2064 + plffirstline = vstrt;
2065 + plflastline = vstop;
2068 + /* This happens far too often. */
2069 + if (plffirstline < minfirstline) {
2070 + write_log ("Warning: Playfield begins before line %d!\n", minfirstline);
2071 + plffirstline = minfirstline;
2075 +#if 0 /* Turrican does this */
2076 + if (plflastline > 313) {
2077 + write_log ("Warning: Playfield out of range!\n");
2078 + plflastline = 313;
2081 + plfstrt = ddfstrt;
2082 + plfstop = ddfstop;
2083 + if (plfstrt < 0x18)
2087 +/* Mousehack stuff */
2089 +#define defstepx (1<<16)
2090 +#define defstepy (1<<16)
2094 +static const int docal = 60, xcaloff = 40, ycaloff = 20;
2095 +static const int calweight = 3;
2096 +static int lastsampledmx, lastsampledmy;
2097 +static int lastspr0x,lastspr0y,lastdiffx,lastdiffy,spr0pos,spr0ctl;
2098 +static int mstepx,mstepy,xoffs=defxoffs,yoffs=defyoffs;
2099 +static int sprvbfl;
2101 +int lastmx, lastmy;
2102 +int newmousecounters;
2103 +int ievent_alive = 0;
2105 +static enum { unknown_mouse, normal_mouse, dont_care_mouse, follow_mouse } mousestate;
2107 +static void mousehack_setdontcare (void)
2109 + if (mousestate == dont_care_mouse)
2112 + write_log ("Don't care mouse mode set\n");
2113 + mousestate = dont_care_mouse;
2114 + lastspr0x = lastmx; lastspr0y = lastmy;
2115 + mstepx = defstepx; mstepy = defstepy;
2118 +static void mousehack_setfollow (void)
2120 + if (mousestate == follow_mouse)
2123 + write_log ("Follow sprite mode set\n");
2124 + mousestate = follow_mouse;
2125 + lastdiffx = lastdiffy = 0;
2127 + spr0ctl = spr0pos = 0;
2128 + mstepx = defstepx; mstepy = defstepy;
2131 +static uae_u32 mousehack_helper (void)
2133 + int mousexpos, mouseypos;
2137 + picasso_clip_mouse (&lastmx, &lastmy);
2138 + mousexpos = lastmx;
2139 + mouseypos = lastmy;
2143 + /* @@@ This isn't completely right, it doesn't deal with virtual
2144 + screen sizes larger than physical very well. */
2145 + if (lastmy >= gfxvidinfo.height)
2146 + lastmy = gfxvidinfo.height - 1;
2151 + if (lastmx >= gfxvidinfo.width)
2152 + lastmx = gfxvidinfo.width - 1;
2153 + mouseypos = coord_native_to_amiga_y (lastmy) << 1;
2154 + mousexpos = coord_native_to_amiga_x (lastmx);
2157 + switch (m68k_dreg (regs, 0)) {
2159 + return ievent_alive ? -1 : needmousehack ();
2161 + ievent_alive = 10;
2169 +void togglemouse (void)
2171 + switch (mousestate) {
2172 + case dont_care_mouse: mousehack_setfollow (); break;
2173 + case follow_mouse: mousehack_setdontcare (); break;
2174 + default: break; /* Nnnnnghh! */
2178 +STATIC_INLINE int adjust (int val)
2182 + else if (val < -127)
2187 +static void do_mouse_hack (void)
2189 + int spr0x = ((spr0pos & 0xff) << 2) | ((spr0ctl & 1) << 1);
2190 + int spr0y = ((spr0pos >> 8) | ((spr0ctl & 4) << 6)) << 1;
2193 + if (ievent_alive > 0) {
2194 + mouse_x = mouse_y = 0;
2197 + switch (mousestate) {
2198 + case normal_mouse:
2199 + diffx = lastmx - lastsampledmx;
2200 + diffy = lastmy - lastsampledmy;
2201 + if (!newmousecounters) {
2202 + if (diffx > 127) diffx = 127;
2203 + if (diffx < -127) diffx = -127;
2205 + if (diffy > 127) diffy = 127;
2206 + if (diffy < -127) diffy = -127;
2209 + lastsampledmx += diffx; lastsampledmy += diffy;
2212 + case dont_care_mouse:
2213 + diffx = adjust (((lastmx - lastspr0x) * mstepx) >> 16);
2214 + diffy = adjust (((lastmy - lastspr0y) * mstepy) >> 16);
2215 + lastspr0x = lastmx; lastspr0y = lastmy;
2216 + mouse_x += diffx; mouse_y += diffy;
2219 + case follow_mouse:
2220 + if (sprvbfl && sprvbfl-- > 1) {
2221 + int mousexpos, mouseypos;
2223 + if ((lastdiffx > docal || lastdiffx < -docal)
2224 + && lastspr0x != spr0x
2225 + && spr0x > plfstrt*4 + 34 + xcaloff
2226 + && spr0x < plfstop*4 - xcaloff)
2228 + int val = (lastdiffx << 16) / (spr0x - lastspr0x);
2229 + if (val >= 0x8000)
2230 + mstepx = (mstepx * (calweight - 1) + val) / calweight;
2232 + if ((lastdiffy > docal || lastdiffy < -docal)
2233 + && lastspr0y != spr0y
2234 + && spr0y > plffirstline + ycaloff
2235 + && spr0y < plflastline - ycaloff)
2237 + int val = (lastdiffy << 16) / (spr0y - lastspr0y);
2238 + if (val >= 0x8000)
2239 + mstepy = (mstepy * (calweight - 1) + val) / calweight;
2241 + if (lastmy >= gfxvidinfo.height)
2242 + lastmy = gfxvidinfo.height-1;
2243 + mouseypos = coord_native_to_amiga_y (lastmy) << 1;
2244 + mousexpos = coord_native_to_amiga_x (lastmx);
2245 + diffx = adjust ((((mousexpos + xoffs - spr0x) & ~1) * mstepx) >> 16);
2246 + diffy = adjust ((((mouseypos + yoffs - spr0y) & ~1) * mstepy) >> 16);
2247 + lastspr0x = spr0x; lastspr0y = spr0y;
2248 + lastdiffx = diffx; lastdiffy = diffy;
2249 + mouse_x += diffx; mouse_y += diffy;
2258 +static void mousehack_handle (unsigned int ctl, unsigned int pos)
2260 + if (!sprvbfl && ((pos & 0xff) << 2) > 2 * DISPLAY_LEFT_SHIFT) {
2267 +static int timehack_alive = 0;
2269 +static uae_u32 timehack_helper (void)
2271 +#ifdef HAVE_GETTIMEOFDAY
2272 + struct timeval tv;
2273 + if (m68k_dreg (regs, 0) == 0)
2274 + return timehack_alive;
2276 + timehack_alive = 10;
2278 + gettimeofday (&tv, NULL);
2279 + put_long (m68k_areg (regs, 0), tv.tv_sec - (((365 * 8 + 2) * 24 - 2) * 60 * 60));
2280 + put_long (m68k_areg (regs, 0) + 4, tv.tv_usec);
2288 + * register functions
2290 +STATIC_INLINE uae_u16 DENISEID (void)
2292 + if (currprefs.chipset_mask & CSMASK_AGA)
2294 + if (currprefs.chipset_mask & CSMASK_ECS_DENISE)
2298 +STATIC_INLINE uae_u16 DMACONR (void)
2300 + return (dmacon | (bltstate==BLT_done ? 0 : 0x4000)
2301 + | (blt_info.blitzero ? 0x2000 : 0));
2303 +STATIC_INLINE uae_u16 INTENAR (void)
2307 +uae_u16 INTREQR (void)
2309 + return intreq /* | (currprefs.use_serial ? 0x0001 : 0) */;
2311 +STATIC_INLINE uae_u16 ADKCONR (void)
2315 +STATIC_INLINE uae_u16 VPOSR (void)
2317 + unsigned int csbit = currprefs.ntscmode ? 0x1000 : 0;
2318 + csbit |= (currprefs.chipset_mask & CSMASK_AGA) ? 0x2300 : 0;
2319 + csbit |= (currprefs.chipset_mask & CSMASK_ECS_AGNUS) ? 0x2000 : 0;
2320 + return (vpos >> 8) | lof | csbit;
2322 +static void VPOSW (uae_u16 v)
2324 + if (lof != (v & 0x8000))
2328 + * This register is much more fun on a real Amiga. You can program
2329 + * refresh rates with it ;) But I won't emulate this...
2333 +STATIC_INLINE uae_u16 VHPOSR (void)
2335 + return (vpos << 8) | current_hpos ();
2338 +STATIC_INLINE void COP1LCH (uae_u16 v) { cop1lc = (cop1lc & 0xffff) | ((uae_u32)v << 16); }
2339 +STATIC_INLINE void COP1LCL (uae_u16 v) { cop1lc = (cop1lc & ~0xffff) | (v & 0xfffe); }
2340 +STATIC_INLINE void COP2LCH (uae_u16 v) { cop2lc = (cop2lc & 0xffff) | ((uae_u32)v << 16); }
2341 +STATIC_INLINE void COP2LCL (uae_u16 v) { cop2lc = (cop2lc & ~0xffff) | (v & 0xfffe); }
2343 +static void start_copper (void)
2345 + int was_active = eventtab[ev_copper].active;
2346 + eventtab[ev_copper].active = 0;
2348 + events_schedule ();
2350 + cop_state.ignore_next = 0;
2351 + cop_state.state = COP_read1;
2352 + cop_state.vpos = vpos;
2353 + cop_state.hpos = current_hpos () & ~1;
2355 + if (dmaen (DMA_COPPER)) {
2356 + copper_enabled_thisline = 1;
2357 + set_special (SPCFLAG_COPPER);
2361 +static void COPJMP1 (uae_u16 a)
2363 + cop_state.ip = cop1lc;
2367 +static void COPJMP2 (uae_u16 a)
2369 + cop_state.ip = cop2lc;
2373 +STATIC_INLINE void COPCON (uae_u16 a)
2378 +static void DMACON (int hpos, uae_u16 v)
2382 + uae_u16 oldcon = dmacon;
2384 + decide_line (hpos);
2385 + decide_fetch (hpos);
2387 + setclr (&dmacon, v);
2390 + /* FIXME? Maybe we need to think a bit more about the master DMA enable
2391 + * bit in these cases. */
2392 + if ((dmacon & DMA_COPPER) != (oldcon & DMA_COPPER)) {
2393 + eventtab[ev_copper].active = 0;
2395 + if ((dmacon & DMA_COPPER) > (oldcon & DMA_COPPER)) {
2396 + cop_state.ip = cop1lc;
2397 + cop_state.ignore_next = 0;
2398 + cop_state.state = COP_read1;
2399 + cop_state.vpos = vpos;
2400 + cop_state.hpos = hpos & ~1;
2401 + copper_enabled_thisline = 1;
2402 + set_special (SPCFLAG_COPPER);
2404 + if (! (dmacon & DMA_COPPER)) {
2405 + copper_enabled_thisline = 0;
2406 + unset_special (SPCFLAG_COPPER);
2407 + cop_state.state = COP_stop;
2410 + if ((dmacon & DMA_BLITPRI) > (oldcon & DMA_BLITPRI) && bltstate != BLT_done) {
2411 + static int count = 0;
2414 + write_log ("warning: program is doing blitpri hacks.\n");
2416 + set_special (SPCFLAG_BLTNASTY);
2418 + if ((dmacon & (DMA_BLITPRI | DMA_BLITTER | DMA_MASTER)) != (DMA_BLITPRI | DMA_BLITTER | DMA_MASTER))
2419 + unset_special (SPCFLAG_BLTNASTY);
2421 + if (currprefs.produce_sound > 0) {
2424 + for (i = 0; i < 4; i++) {
2425 + struct audio_channel_data *cdp = audio_channel + i;
2426 + int chan_ena = (dmacon & 0x200) && (dmacon & (1<<i));
2427 + if (cdp->dmaen == chan_ena)
2429 + cdp->dmaen = chan_ena;
2431 + audio_channel_enable_dma (cdp);
2433 + audio_channel_disable_dma (cdp);
2435 + schedule_audio ();
2437 + events_schedule();
2440 +/*static int trace_intena = 0;*/
2442 +STATIC_INLINE void INTENA (uae_u16 v)
2444 +/* if (trace_intena)
2445 + write_log ("INTENA: %04x\n", v);*/
2446 + setclr (&intena,v);
2447 + /* There's stupid code out there that does
2448 + [some INTREQ bits at level 3 are set]
2449 + clear all INTREQ bits
2450 + Enable one INTREQ level 3 bit
2451 + Set level 3 handler
2453 + If we set SPCFLAG_INT for the clear, then by the time the enable happens,
2454 + we'll have SPCFLAG_DOINT set, and the interrupt happens immediately, but
2455 + it needs to happen one insn later, when the new L3 handler has been
2458 + set_special (SPCFLAG_INT);
2461 +void INTREQ_0 (uae_u16 v)
2463 + setclr (&intreq,v);
2464 + set_special (SPCFLAG_INT);
2467 +void INTREQ (uae_u16 v)
2470 + if ((v & 0x8800) == 0x0800)
2475 +static void update_adkmasks (void)
2479 + t = adkcon | (adkcon >> 4);
2480 + audio_channel[0].adk_mask = (((t >> 0) & 1) - 1);
2481 + audio_channel[1].adk_mask = (((t >> 1) & 1) - 1);
2482 + audio_channel[2].adk_mask = (((t >> 2) & 1) - 1);
2483 + audio_channel[3].adk_mask = (((t >> 3) & 1) - 1);
2486 +static void ADKCON (uae_u16 v)
2488 + if (currprefs.produce_sound > 0)
2491 + setclr (&adkcon,v);
2492 + update_adkmasks ();
2495 +static void BEAMCON0 (uae_u16 v)
2497 + if (currprefs.chipset_mask & CSMASK_ECS_AGNUS)
2498 + new_beamcon0 = v & 0x20;
2501 +static void BPLPTH (int hpos, uae_u16 v, int num)
2503 + decide_line (hpos);
2504 + decide_fetch (hpos);
2505 + bplpt[num] = (bplpt[num] & 0xffff) | ((uae_u32)v << 16);
2507 +static void BPLPTL (int hpos, uae_u16 v, int num)
2509 + decide_line (hpos);
2510 + decide_fetch (hpos);
2511 + bplpt[num] = (bplpt[num] & ~0xffff) | (v & 0xfffe);
2514 +static void BPLCON0 (int hpos, uae_u16 v)
2516 + if (! (currprefs.chipset_mask & CSMASK_ECS_DENISE))
2518 + else if (! (currprefs.chipset_mask & CSMASK_AGA))
2523 + decide_line (hpos);
2524 + decide_fetch (hpos);
2527 + if ((bplcon0 ^ v) & 0x800) {
2528 + record_color_change (hpos, -1, !! (v & 0x800));
2532 + curr_diagram = cycle_diagram_table[fetchmode][GET_RES(bplcon0)][GET_PLANES (v)];
2534 + if (currprefs.chipset_mask & CSMASK_AGA) {
2535 + decide_sprites (hpos);
2542 +STATIC_INLINE void BPLCON1 (int hpos, uae_u16 v)
2546 + decide_line (hpos);
2547 + decide_fetch (hpos);
2551 +STATIC_INLINE void BPLCON2 (int hpos, uae_u16 v)
2555 + decide_line (hpos);
2559 +STATIC_INLINE void BPLCON3 (int hpos, uae_u16 v)
2561 + if (! (currprefs.chipset_mask & CSMASK_AGA))
2565 + decide_line (hpos);
2566 + decide_sprites (hpos);
2571 +STATIC_INLINE void BPLCON4 (int hpos, uae_u16 v)
2573 + if (! (currprefs.chipset_mask & CSMASK_AGA))
2577 + decide_line (hpos);
2581 +static void BPL1MOD (int hpos, uae_u16 v)
2584 + if ((uae_s16)bpl1mod == (uae_s16)v)
2586 + decide_line (hpos);
2587 + decide_fetch (hpos);
2591 +static void BPL2MOD (int hpos, uae_u16 v)
2594 + if ((uae_s16)bpl2mod == (uae_s16)v)
2596 + decide_line (hpos);
2597 + decide_fetch (hpos);
2601 +STATIC_INLINE void BPL1DAT (int hpos, uae_u16 v)
2603 + decide_line (hpos);
2606 + maybe_first_bpl1dat (hpos);
2608 +/* We could do as well without those... */
2609 +STATIC_INLINE void BPL2DAT (uae_u16 v) { bpl2dat = v; }
2610 +STATIC_INLINE void BPL3DAT (uae_u16 v) { bpl3dat = v; }
2611 +STATIC_INLINE void BPL4DAT (uae_u16 v) { bpl4dat = v; }
2612 +STATIC_INLINE void BPL5DAT (uae_u16 v) { bpl5dat = v; }
2613 +STATIC_INLINE void BPL6DAT (uae_u16 v) { bpl6dat = v; }
2614 +STATIC_INLINE void BPL7DAT (uae_u16 v) { bpl7dat = v; }
2615 +STATIC_INLINE void BPL8DAT (uae_u16 v) { bpl8dat = v; }
2617 +static void DIWSTRT (int hpos, uae_u16 v)
2619 + if (diwstrt == v && ! diwhigh_written)
2621 + decide_line (hpos);
2622 + diwhigh_written = 0;
2627 +static void DIWSTOP (int hpos, uae_u16 v)
2629 + if (diwstop == v && ! diwhigh_written)
2631 + decide_line (hpos);
2632 + diwhigh_written = 0;
2637 +static void DIWHIGH (int hpos, uae_u16 v)
2639 + if (! (currprefs.chipset_mask & CSMASK_ECS_DENISE))
2641 + if (diwhigh_written && diwhigh == v)
2643 + decide_line (hpos);
2644 + diwhigh_written = 1;
2649 +static void DDFSTRT (int hpos, uae_u16 v)
2654 + decide_line (hpos);
2657 + if (ddfstop > 0xD4 && (ddfstrt & 4) == 4) {
2658 + static int last_warned;
2659 + last_warned = (last_warned + 1) & 4095;
2660 + if (last_warned == 0)
2661 + write_log ("WARNING! Very strange DDF values.\n");
2665 +static void DDFSTOP (int hpos, uae_u16 v)
2667 + /* ??? "Virtual Meltdown" sets this to 0xD2 and expects it to behave
2668 + differently from 0xD0. RSI Megademo sets it to 0xd1 and expects it
2669 + to behave like 0xd0. Some people also write the high 8 bits and
2670 + expect them to be ignored. So mask it with 0xFE. */
2674 + decide_line (hpos);
2675 + decide_fetch (hpos);
2678 + if (fetch_state != fetch_not_started)
2679 + estimate_last_fetch_cycle (hpos);
2680 + if (ddfstop > 0xD4 && (ddfstrt & 4) == 4) {
2681 + static int last_warned;
2682 + last_warned = (last_warned + 1) & 4095;
2683 + if (last_warned == 0)
2684 + write_log ("WARNING! Very strange DDF values.\n");
2685 + write_log ("WARNING! Very strange DDF values.\n");
2689 +static void FMODE (uae_u16 v)
2691 + if (! (currprefs.chipset_mask & CSMASK_AGA))
2695 + sprite_width = GET_SPRITEWIDTH (fmode);
2696 + switch (fmode & 3) {
2708 + curr_diagram = cycle_diagram_table[fetchmode][GET_RES (v)][GET_PLANES (bplcon0)];
2712 +static void BLTADAT (uae_u16 v)
2716 + blt_info.bltadat = v;
2719 + * "Loading data shifts it immediately" says the HRM. Well, that may
2720 + * be true for BLTBDAT, but not for BLTADAT - it appears the A data must be
2721 + * loaded for every word so that AFWM and ALWM can be applied.
2723 +static void BLTBDAT (uae_u16 v)
2728 + blt_info.bltbhold = v << (bltcon1 >> 12);
2730 + blt_info.bltbhold = v >> (bltcon1 >> 12);
2731 + blt_info.bltbdat = v;
2733 +static void BLTCDAT (uae_u16 v) { maybe_blit (0); blt_info.bltcdat = v; }
2735 +static void BLTAMOD (uae_u16 v) { maybe_blit (1); blt_info.bltamod = (uae_s16)(v & 0xFFFE); }
2736 +static void BLTBMOD (uae_u16 v) { maybe_blit (1); blt_info.bltbmod = (uae_s16)(v & 0xFFFE); }
2737 +static void BLTCMOD (uae_u16 v) { maybe_blit (1); blt_info.bltcmod = (uae_s16)(v & 0xFFFE); }
2738 +static void BLTDMOD (uae_u16 v) { maybe_blit (1); blt_info.bltdmod = (uae_s16)(v & 0xFFFE); }
2740 +static void BLTCON0 (uae_u16 v) { maybe_blit (0); bltcon0 = v; blinea_shift = v >> 12; }
2741 +/* The next category is "Most useless hardware register".
2742 + * And the winner is... */
2743 +static void BLTCON0L (uae_u16 v)
2745 + if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS))
2747 + maybe_blit (0); bltcon0 = (bltcon0 & 0xFF00) | (v & 0xFF);
2749 +static void BLTCON1 (uae_u16 v) { maybe_blit (0); bltcon1 = v; }
2751 +static void BLTAFWM (uae_u16 v) { maybe_blit (0); blt_info.bltafwm = v; }
2752 +static void BLTALWM (uae_u16 v) { maybe_blit (0); blt_info.bltalwm = v; }
2754 +static void BLTAPTH (uae_u16 v) { maybe_blit (0); bltapt = (bltapt & 0xffff) | ((uae_u32)v << 16); }
2755 +static void BLTAPTL (uae_u16 v) { maybe_blit (0); bltapt = (bltapt & ~0xffff) | (v & 0xFFFE); }
2756 +static void BLTBPTH (uae_u16 v) { maybe_blit (0); bltbpt = (bltbpt & 0xffff) | ((uae_u32)v << 16); }
2757 +static void BLTBPTL (uae_u16 v) { maybe_blit (0); bltbpt = (bltbpt & ~0xffff) | (v & 0xFFFE); }
2758 +static void BLTCPTH (uae_u16 v) { maybe_blit (0); bltcpt = (bltcpt & 0xffff) | ((uae_u32)v << 16); }
2759 +static void BLTCPTL (uae_u16 v) { maybe_blit (0); bltcpt = (bltcpt & ~0xffff) | (v & 0xFFFE); }
2760 +static void BLTDPTH (uae_u16 v) { maybe_blit (0); bltdpt = (bltdpt & 0xffff) | ((uae_u32)v << 16); }
2761 +static void BLTDPTL (uae_u16 v) { maybe_blit (0); bltdpt = (bltdpt & ~0xffff) | (v & 0xFFFE); }
2763 +static void BLTSIZE (uae_u16 v)
2767 + blt_info.vblitsize = v >> 6;
2768 + blt_info.hblitsize = v & 0x3F;
2769 + if (!blt_info.vblitsize) blt_info.vblitsize = 1024;
2770 + if (!blt_info.hblitsize) blt_info.hblitsize = 64;
2772 + bltstate = BLT_init;
2776 +static void BLTSIZV (uae_u16 v)
2778 + if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS))
2781 + oldvblts = v & 0x7FFF;
2784 +static void BLTSIZH (uae_u16 v)
2786 + if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS))
2789 + blt_info.hblitsize = v & 0x7FF;
2790 + blt_info.vblitsize = oldvblts;
2791 + if (!blt_info.vblitsize) blt_info.vblitsize = 32768;
2792 + if (!blt_info.hblitsize) blt_info.hblitsize = 0x800;
2793 + bltstate = BLT_init;
2797 +STATIC_INLINE void SPRxCTL_1 (uae_u16 v, int num, int hpos)
2800 + struct sprite *s = &spr[num];
2802 + nr_armed -= s->armed;
2804 + sprxp = (sprpos[num] & 0xFF) * 2 + (v & 1);
2806 + /* Quite a bit salad in this register... */
2807 + if (currprefs.chipset_mask & CSMASK_AGA) {
2808 + /* We ignore the SHRES 35ns increment for now; SHRES support doesn't
2809 + work anyway, so we may as well restrict AGA sprites to a 70ns
2812 + sprxp |= (v >> 4) & 1;
2815 + s->vstart = (sprpos[num] >> 8) | ((sprctl[num] << 6) & 0x100);
2816 + s->vstop = (sprctl[num] >> 8) | ((sprctl[num] << 7) & 0x100);
2817 + if (vpos == s->vstart)
2818 + s->state = SPR_waiting_stop;
2819 +#ifdef SPRITE_DEBUG
2820 + write_log ("%d:%d:SPR%dCTL V=%04.4X STATE=%d ARMED=%d\n", vpos, hpos, num, v, s->state, s->armed);
2823 +STATIC_INLINE void SPRxPOS_1 (uae_u16 v, int num, int hpos)
2826 + struct sprite *s = &spr[num];
2828 + sprxp = (v & 0xFF) * 2 + (sprctl[num] & 1);
2830 + if (currprefs.chipset_mask & CSMASK_AGA) {
2832 + sprxp |= (sprctl[num] >> 4) & 1;
2835 + s->vstart = (sprpos[num] >> 8) | ((sprctl[num] << 6) & 0x100);
2836 +#ifdef SPRITE_DEBUG
2837 + write_log ("%d:%d:SPR%dPOS %04.4X STATE=%d ARMED=%d\n", vpos, hpos, num, v, s->state, s->armed);
2840 +STATIC_INLINE void SPRxDATA_1 (uae_u16 v, int num)
2842 + sprdata[num][0] = v;
2843 + nr_armed += 1 - spr[num].armed;
2844 + spr[num].armed = 1;
2846 +STATIC_INLINE void SPRxDATB_1 (uae_u16 v, int num)
2848 + sprdatb[num][0] = v;
2850 +static void SPRxDATA (int hpos, uae_u16 v, int num) { decide_sprites (hpos); SPRxDATA_1 (v, num); }
2851 +static void SPRxDATB (int hpos, uae_u16 v, int num) { decide_sprites (hpos); SPRxDATB_1 (v, num); }
2852 +static void SPRxCTL (int hpos, uae_u16 v, int num) { decide_sprites (hpos); SPRxCTL_1 (v, num, hpos); }
2853 +static void SPRxPOS (int hpos, uae_u16 v, int num) { decide_sprites (hpos); SPRxPOS_1 (v, num, hpos); }
2854 +static void SPRxPTH (int hpos, uae_u16 v, int num)
2856 + decide_sprites (hpos);
2857 + spr[num].pt &= 0xffff;
2858 + spr[num].pt |= (uae_u32)v << 16;
2859 +#ifdef SPRITE_DEBUG
2860 + write_log ("%d:%d:SPR%dPTH %08.8X\n", vpos, hpos, num, spr[num].pt);
2863 +static void SPRxPTL (int hpos, uae_u16 v, int num)
2865 + decide_sprites (hpos);
2866 + spr[num].pt &= ~0xffff;
2868 +#ifdef SPRITE_DEBUG
2869 + write_log ("%d:%d:SPR%dPTL %08.8X\n", vpos, hpos, num, spr[num].pt);
2873 +static void CLXCON (uae_u16 v)
2876 + clxcon_bpl_enable = (v >> 6) & 63;
2877 + clxcon_bpl_match = v & 63;
2878 + clx_sprmask = ((((v >> 15) & 1) << 7) | (((v >> 14) & 1) << 5) | (((v >> 13) & 1) << 3) | (((v >> 12) & 1) << 1) | 0x55);
2880 +static void CLXCON2 (uae_u16 v)
2882 + if (!(currprefs.chipset_mask & CSMASK_AGA))
2885 + clxcon_bpl_enable |= v & (0x40|0x80);
2886 + clxcon_bpl_match |= (v & (0x01|0x02)) << 6;
2888 +static uae_u16 CLXDAT (void)
2890 + uae_u16 v = clxdat;
2895 +static uae_u16 COLOR_READ (int num)
2897 + int cr, cg, cb, colreg;
2900 + if (!(currprefs.chipset_mask & CSMASK_AGA) || !(bplcon2 & 0x0100))
2903 + colreg = ((bplcon3 >> 13) & 7) * 32 + num;
2904 + cr = current_colors.color_regs_aga[colreg] >> 16;
2905 + cg = (current_colors.color_regs_aga[colreg] >> 8) & 0xFF;
2906 + cb = current_colors.color_regs_aga[colreg] & 0xFF;
2907 + if (bplcon3 & 0x200)
2908 + cval = ((cr & 15) << 8) | ((cg & 15) << 4) | ((cb & 15) << 0);
2910 + cval = ((cr >> 4) << 8) | ((cg >> 4) << 4) | ((cb >> 4) << 0);
2914 +static void COLOR_WRITE (int hpos, uae_u16 v, int num)
2917 + if (currprefs.chipset_mask & CSMASK_AGA) {
2923 + /* writing is disabled when RDRAM=1 */
2924 + if (bplcon2 & 0x0100)
2927 + colreg = ((bplcon3 >> 13) & 7) * 32 + num;
2928 + r = (v & 0xF00) >> 8;
2929 + g = (v & 0xF0) >> 4;
2930 + b = (v & 0xF) >> 0;
2931 + cr = current_colors.color_regs_aga[colreg] >> 16;
2932 + cg = (current_colors.color_regs_aga[colreg] >> 8) & 0xFF;
2933 + cb = current_colors.color_regs_aga[colreg] & 0xFF;
2935 + if (bplcon3 & 0x200) {
2936 + cr &= 0xF0; cr |= r;
2937 + cg &= 0xF0; cg |= g;
2938 + cb &= 0xF0; cb |= b;
2940 + cr = r + (r << 4);
2941 + cg = g + (g << 4);
2942 + cb = b + (b << 4);
2944 + cval = (cr << 16) | (cg << 8) | cb;
2945 + if (cval == current_colors.color_regs_aga[colreg])
2948 + /* Call this with the old table still intact. */
2949 + record_color_change (hpos, colreg, cval);
2950 + remembered_color_entry = -1;
2951 + current_colors.color_regs_aga[colreg] = cval;
2952 + current_colors.acolors[colreg] = CONVERT_RGB (cval);
2954 + if (current_colors.color_regs_ecs[num] == v)
2956 + /* Call this with the old table still intact. */
2957 + record_color_change (hpos, num, v);
2958 + remembered_color_entry = -1;
2959 + current_colors.color_regs_ecs[num] = v;
2960 + current_colors.acolors[num] = xcolors[v];
2964 +static uae_u16 potgo_value;
2966 +static void POTGO (uae_u16 v)
2971 +static uae_u16 POTGOR (void)
2973 + uae_u16 v = (potgo_value | (potgo_value >> 1)) & 0x5500;
2975 + v |= (~potgo_value & 0xAA00) >> 1;
2977 + if (JSEM_ISMOUSE (0, &currprefs)) {
2978 + if (buttonstate[2])
2981 + if (buttonstate[1])
2983 + } else if (JSEM_ISJOY0 (0, &currprefs) || JSEM_ISJOY1 (0, &currprefs)) {
2984 + if (joy0button & 2) v &= 0xfbff;
2985 + if (joy0button & 4) v &= 0xfeff;
2988 + if (JSEM_ISJOY0 (1, &currprefs) || JSEM_ISJOY1 (1, &currprefs)) {
2989 + if (joy1button & 2) v &= 0xbfff;
2990 + if (joy1button & 4) v &= 0xefff;
2996 +static uae_u16 POT0DAT (void)
2998 + static uae_u16 cnt = 0;
2999 + if (JSEM_ISMOUSE (0, &currprefs)) {
3000 + if (buttonstate[2])
3001 + cnt = ((cnt + 1) & 0xFF) | (cnt & 0xFF00);
3002 + if (buttonstate[1])
3008 +static uae_u16 JOY0DAT (void)
3010 + if (JSEM_ISMOUSE (0, &currprefs)) {
3012 + return ((uae_u8)mouse_x) + ((uae_u16)mouse_y << 8);
3016 +static uae_u16 JOY1DAT (void)
3018 + if (JSEM_ISMOUSE (1, &currprefs)) {
3020 + return ((uae_u8)mouse_x) + ((uae_u16)mouse_y << 8);
3024 +static void JOYTEST (uae_u16 v)
3026 + if (JSEM_ISMOUSE (0, &currprefs)) {
3027 + mouse_x = v & 0xFC;
3028 + mouse_y = (v >> 8) & 0xFC;
3032 +/* The copper code. The biggest nightmare in the whole emulator.
3034 + Alright. The current theory:
3035 + 1. Copper moves happen 2 cycles after state READ2 is reached.
3036 + It can't happen immediately when we reach READ2, because the
3037 + data needs time to get back from the bus. An additional 2
3038 + cycles are needed for non-Agnus registers, to take into account
3039 + the delay for moving data from chip to chip.
3040 + 2. As stated in the HRM, a WAIT really does need an extra cycle
3041 + to wake up. This is implemented by _not_ falling through from
3042 + a successful wait to READ1, but by starting the next cycle.
3043 + (Note: the extra cycle for the WAIT apparently really needs a
3044 + free cycle; i.e. contention with the bitplane fetch can slow
3046 + 3. Apparently, to compensate for the extra wake up cycle, a WAIT
3047 + will use the _incremented_ horizontal position, so the WAIT
3048 + cycle normally finishes two clocks earlier than the position
3049 + it was waiting for. The extra cycle then takes us to the
3050 + position that was waited for.
3051 + If the earlier cycle is busy with a bitplane, things change a bit.
3052 + E.g., waiting for position 0x50 in a 6 plane display: In cycle
3053 + 0x4e, we fetch BPL5, so the wait wakes up in 0x50, the extra cycle
3054 + takes us to 0x54 (since 0x52 is busy), then we have READ1/READ2,
3055 + and the next register write is at 0x5c.
3056 + 4. The last cycle in a line is not usable for the copper.
3057 + 5. A 4 cycle delay also applies to the WAIT instruction. This means
3058 + that the second of two back-to-back WAITs (or a WAIT whose
3059 + condition is immediately true) takes 8 cycles.
3060 + 6. This also applies to a SKIP instruction. The copper does not
3061 + fetch the next instruction while waiting for the second word of
3062 + a WAIT or a SKIP to arrive.
3063 + 7. A SKIP also seems to need an unexplained additional two cycles
3064 + after its second word arrives; this is _not_ a memory cycle (I
3065 + think, the documentation is pretty clear on this).
3066 + 8. Two additional cycles are inserted when writing to COPJMP1/2. */
3068 +/* Determine which cycles are available for the copper in a display
3069 + * with a agiven number of planes. */
3071 +STATIC_INLINE int copper_cant_read (int hpos)
3075 + if (hpos + 1 >= maxhpos)
3078 + if (fetch_state == fetch_not_started || hpos < thisline_decision.plfleft)
3081 + if ((passed_plfstop == 3 && hpos >= thisline_decision.plfright)
3082 + || hpos >= estimated_last_fetch_cycle)
3085 + t = curr_diagram[(hpos + cycle_diagram_shift) & fetchstart_mask];
3093 +STATIC_INLINE int dangerous_reg (int reg)
3096 + * Bitplane pointers, control registers, modulos and data.
3097 + * Sprite pointers, control registers, and data.
3098 + * Color registers. */
3099 + if (reg >= 0xE0 && reg < 0x1C0)
3104 +#define FAST_COPPER 1
3106 +/* The future, Conan?
3107 + We try to look ahead in the copper list to avoid doing continuous calls
3108 + to updat_copper (which is what happens when SPCFLAG_COPPER is set). If
3109 + we find that the same effect can be achieved by setting a delayed event
3110 + and then doing multiple copper insns in one batch, we can get a massive
3113 + We don't try to be precise here. All copper reads take exactly 2 cycles,
3114 + the effect of bitplane contention is ignored. Trying to get it exactly
3115 + right would be much more complex and as such carry a huge risk of getting
3116 + it subtly wrong; and it would also be more expensive - we want this code
3118 +static void predict_copper (void)
3120 + uaecptr ip = cop_state.ip;
3121 + unsigned int c_hpos = cop_state.hpos;
3122 + enum copper_states state = cop_state.state;
3123 + unsigned int w1, w2, cycle_count;
3126 + case COP_read1_wr_in2:
3127 + case COP_read2_wr_in2:
3128 + case COP_read1_wr_in4:
3129 + if (dangerous_reg (cop_state.saved_i1))
3131 + state = state == COP_read2_wr_in2 ? COP_read2 : COP_read1;
3134 + case COP_read1_in2:
3136 + state = COP_read1;
3142 + case COP_skip_in4:
3143 + case COP_skip_in2:
3146 + case COP_wait_in4:
3149 + case COP_wait_in2:
3159 + /* Only needed for COP_wait, but let's shut up the compiler. */
3160 + w1 = cop_state.saved_i1;
3161 + w2 = cop_state.saved_i2;
3162 + cop_state.first_sync = c_hpos;
3163 + cop_state.regtypes_modified = REGTYPE_FORCE;
3165 + /* Get this case out of the way, so that the loop below only has to deal
3166 + with read1 and wait. */
3167 + if (state == COP_read2) {
3168 + w1 = cop_state.i1;
3170 + w2 = chipmem_wget (ip);
3175 + } else if (dangerous_reg (w1)) {
3179 + cop_state.regtypes_modified |= regtypes[w1 & 0x1FE];
3180 + state = COP_read1;
3186 + while (c_hpos + 1 < maxhpos) {
3187 + if (state == COP_read1) {
3188 + w1 = chipmem_wget (ip);
3190 + w2 = chipmem_wget (ip + 2);
3195 + } else if (dangerous_reg (w1)) {
3199 + cop_state.regtypes_modified |= regtypes[w1 & 0x1FE];
3203 + } else if (state == COP_wait) {
3204 + if ((w2 & 0xFE) != 0xFE)
3207 + unsigned int vcmp = (w1 & (w2 | 0x8000)) >> 8;
3208 + unsigned int hcmp = (w1 & 0xFE);
3210 + unsigned int vp = vpos & (((w2 >> 8) & 0x7F) | 0x80);
3212 + /* Whee. We can wait until the end of the line! */
3214 + } else if (vp > vcmp || hcmp <= c_hpos) {
3215 + state = COP_read1;
3216 + /* minimum wakeup time */
3219 + state = COP_read1;
3222 + /* If this is the current instruction, remember that we don't
3223 + need to sync CPU and copper anytime soon. */
3224 + if (cop_state.ip == ip) {
3225 + cop_state.first_sync = c_hpos;
3233 + cycle_count = c_hpos - cop_state.hpos;
3234 + if (cycle_count >= 8) {
3235 + unset_special (SPCFLAG_COPPER);
3236 + eventtab[ev_copper].active = 1;
3237 + eventtab[ev_copper].oldcycles = get_cycles ();
3238 + eventtab[ev_copper].evtime = get_cycles () + cycle_count * CYCLE_UNIT;
3239 + events_schedule ();
3243 +static void perform_copper_write (int old_hpos)
3245 + int vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80);
3246 + unsigned int address = cop_state.saved_i1 & 0x1FE;
3248 + record_copper (cop_state.saved_ip - 4, old_hpos, vpos);
3250 + if (address < (copcon & 2 ? ((currprefs.chipset_mask & CSMASK_AGA) ? 0 : 0x40u) : 0x80u)) {
3251 + cop_state.state = COP_stop;
3252 + copper_enabled_thisline = 0;
3253 + unset_special (SPCFLAG_COPPER);
3257 + if (address == 0x88) {
3258 + cop_state.ip = cop1lc;
3259 + cop_state.state = COP_read1_in2;
3260 + } else if (address == 0x8A) {
3261 + cop_state.ip = cop2lc;
3262 + cop_state.state = COP_read1_in2;
3264 + custom_wput_1 (old_hpos, address, cop_state.saved_i2);
3267 +static int isagnus[]= {
3268 + 1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,
3269 + 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,
3270 + 0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,
3271 + 1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,
3272 + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* BPLxPT */
3273 + 0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,
3274 + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* SPRxPT */
3275 + 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,
3276 + 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, /* colors */
3277 + 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
3280 +static void update_copper (int until_hpos)
3282 + int vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80);
3283 + int c_hpos = cop_state.hpos;
3285 + if (eventtab[ev_copper].active)
3288 + if (cop_state.state == COP_wait && vp < cop_state.vcmp)
3293 + if (until_hpos > (maxhpos & ~1))
3294 + until_hpos = maxhpos & ~1;
3298 + int old_hpos = c_hpos;
3301 + if (c_hpos >= until_hpos)
3304 + /* So we know about the fetch state. */
3305 + decide_line (c_hpos);
3307 + switch (cop_state.state) {
3308 + case COP_read1_in2:
3309 + cop_state.state = COP_read1;
3311 + case COP_read1_wr_in2:
3312 + cop_state.state = COP_read1;
3313 + perform_copper_write (old_hpos);
3314 + /* That could have turned off the copper. */
3315 + if (! copper_enabled_thisline)
3319 + case COP_read1_wr_in4:
3320 + cop_state.state = COP_read1_wr_in2;
3322 + case COP_read2_wr_in2:
3323 + cop_state.state = COP_read2;
3324 + perform_copper_write (old_hpos);
3325 + /* That could have turned off the copper. */
3326 + if (! copper_enabled_thisline)
3330 + case COP_wait_in2:
3331 + cop_state.state = COP_wait1;
3333 + case COP_wait_in4:
3334 + cop_state.state = COP_wait_in2;
3336 + case COP_skip_in2:
3338 + static int skipped_before;
3339 + unsigned int vcmp, hcmp, vp1, hp1;
3340 + cop_state.state = COP_read1_in2;
3342 + vcmp = (cop_state.saved_i1 & (cop_state.saved_i2 | 0x8000)) >> 8;
3343 + hcmp = (cop_state.saved_i1 & cop_state.saved_i2 & 0xFE);
3345 + if (! skipped_before) {
3346 + skipped_before = 1;
3347 + write_log ("Program uses Copper SKIP instruction.\n");
3350 + vp1 = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80);
3351 + hp1 = old_hpos & (cop_state.saved_i2 & 0xFE);
3353 + if ((vp1 > vcmp || (vp1 == vcmp && hp1 >= hcmp))
3354 + && ((cop_state.saved_i2 & 0x8000) != 0 || ! (DMACONR() & 0x4000)))
3355 + cop_state.ignore_next = 1;
3358 + case COP_skip_in4:
3359 + cop_state.state = COP_skip_in2;
3366 + if (copper_cant_read (old_hpos))
3369 + switch (cop_state.state) {
3370 + case COP_read1_wr_in4:
3373 + case COP_read1_wr_in2:
3375 + cop_state.i1 = chipmem_wget (cop_state.ip);
3376 + cop_state.ip += 2;
3377 + cop_state.state = cop_state.state == COP_read1 ? COP_read2 : COP_read2_wr_in2;
3380 + case COP_read2_wr_in2:
3384 + cop_state.i2 = chipmem_wget (cop_state.ip);
3385 + cop_state.ip += 2;
3386 + if (cop_state.ignore_next) {
3387 + cop_state.ignore_next = 0;
3388 + cop_state.state = COP_read1;
3392 + cop_state.saved_i1 = cop_state.i1;
3393 + cop_state.saved_i2 = cop_state.i2;
3394 + cop_state.saved_ip = cop_state.ip;
3396 + if (cop_state.i1 & 1) {
3397 + if (cop_state.i2 & 1)
3398 + cop_state.state = COP_skip_in4;
3400 + cop_state.state = COP_wait_in4;
3402 + unsigned int reg = cop_state.i1 & 0x1FE;
3403 + cop_state.state = isagnus[reg >> 1] ? COP_read1_wr_in2 : COP_read1_wr_in4;
3408 + /* There's a nasty case here. As stated in the "Theory" comment above, we
3409 + test against the incremented copper position. I believe this means that
3410 + we have to increment the _vertical_ position at the last cycle in the line,
3411 + and set the horizontal position to 0.
3412 + Normally, this isn't going to make a difference, since we consider these
3413 + last cycles unavailable for the copper, so waking up in the last cycle has
3414 + the same effect as waking up at the start of the line. However, there is
3415 + one possible problem: If we're at 0xFFE0, any wait for an earlier position
3416 + must _not_ complete (since, in effect, the current position will be back
3417 + at 0/0). This can be seen in the Superfrog copper list.
3418 + Things get monstrously complicated if we try to handle this "properly" by
3419 + incrementing vpos and setting c_hpos to 0. Especially the various speedup
3420 + hacks really assume that vpos remains constant during one line. Hence,
3421 + this hack: defer the entire decision until the next line if necessary. */
3422 + if (c_hpos >= (maxhpos & ~1))
3424 + cop_state.state = COP_wait;
3426 + cop_state.vcmp = (cop_state.saved_i1 & (cop_state.saved_i2 | 0x8000)) >> 8;
3427 + cop_state.hcmp = (cop_state.saved_i1 & cop_state.saved_i2 & 0xFE);
3429 + vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80);
3431 + if (cop_state.saved_i1 == 0xFFFF && cop_state.saved_i2 == 0xFFFE) {
3432 + cop_state.state = COP_stop;
3433 + copper_enabled_thisline = 0;
3434 + unset_special (SPCFLAG_COPPER);
3437 + if (vp < cop_state.vcmp) {
3438 + copper_enabled_thisline = 0;
3439 + unset_special (SPCFLAG_COPPER);
3443 + /* fall through */
3446 + if (vp < cop_state.vcmp)
3449 + hp = c_hpos & (cop_state.saved_i2 & 0xFE);
3450 + if (vp == cop_state.vcmp && hp < cop_state.hcmp) {
3451 + /* Position not reached yet. */
3452 + if (currprefs.fast_copper && (cop_state.saved_i2 & 0xFE) == 0xFE) {
3453 + int wait_finish = cop_state.hcmp - 2;
3454 + /* This will leave c_hpos untouched if it's equal to wait_finish. */
3455 + if (wait_finish < c_hpos)
3457 + else if (wait_finish <= until_hpos) {
3458 + c_hpos = wait_finish;
3460 + c_hpos = until_hpos;
3465 + /* Now we know that the comparisons were successful. We might still
3466 + have to wait for the blitter though. */
3467 + if ((cop_state.saved_i2 & 0x8000) == 0 && (DMACONR() & 0x4000)) {
3468 + /* We need to wait for the blitter. */
3469 + cop_state.state = COP_bltwait;
3470 + copper_enabled_thisline = 0;
3471 + unset_special (SPCFLAG_COPPER);
3475 + record_copper (cop_state.ip - 4, old_hpos, vpos);
3477 + cop_state.state = COP_read1;
3486 + cop_state.hpos = c_hpos;
3488 + /* The test against maxhpos also prevents us from calling predict_copper
3489 + when we are being called from hsync_handler, which would not only be
3490 + stupid, but actively harmful. */
3491 + if (currprefs.fast_copper && (regs.spcflags & SPCFLAG_COPPER) && c_hpos + 8 < maxhpos)
3492 + predict_copper ();
3495 +static void compute_spcflag_copper (void)
3497 + copper_enabled_thisline = 0;
3498 + unset_special (SPCFLAG_COPPER);
3499 + if (! dmaen (DMA_COPPER) || cop_state.state == COP_stop || cop_state.state == COP_bltwait)
3502 + if (cop_state.state == COP_wait) {
3503 + int vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80);
3505 + if (vp < cop_state.vcmp)
3508 + copper_enabled_thisline = 1;
3510 + if (currprefs.fast_copper)
3511 + predict_copper ();
3513 + if (! eventtab[ev_copper].active)
3514 + set_special (SPCFLAG_COPPER);
3517 +static void copper_handler (void)
3519 + /* This will take effect immediately, within the same cycle. */
3520 + set_special (SPCFLAG_COPPER);
3522 + if (! copper_enabled_thisline)
3525 + eventtab[ev_copper].active = 0;
3528 +void blitter_done_notify (void)
3530 + if (cop_state.state != COP_bltwait)
3533 + cop_state.hpos = current_hpos () & ~1;
3534 + cop_state.vpos = vpos;
3535 + cop_state.state = COP_wait;
3536 + compute_spcflag_copper ();
3539 +void do_copper (void)
3541 + int hpos = current_hpos ();
3542 + update_copper (hpos);
3545 +/* ADDR is the address that is going to be read/written; this access is
3546 + the reason why we want to update the copper. This function is also
3547 + used from hsync_handler to finish up the line; for this case, we check
3548 + hpos against maxhpos. */
3549 +STATIC_INLINE void sync_copper_with_cpu (int hpos, int do_schedule, unsigned int addr)
3551 + /* Need to let the copper advance to the current position. */
3552 + if (eventtab[ev_copper].active) {
3553 + if (hpos != maxhpos) {
3554 + /* There might be reasons why we don't actually need to bother
3555 + updating the copper. */
3556 + if (hpos < cop_state.first_sync)
3559 + if ((cop_state.regtypes_modified & regtypes[addr & 0x1FE]) == 0)
3563 + eventtab[ev_copper].active = 0;
3565 + events_schedule ();
3566 + set_special (SPCFLAG_COPPER);
3568 + if (copper_enabled_thisline)
3569 + update_copper (hpos);
3572 +STATIC_INLINE uae_u16 sprite_fetch (struct sprite *s, int dma)
3574 + uae_u16 data = last_custom_value;
3576 + data = last_custom_value = chipmem_wget (s->pt);
3581 +STATIC_INLINE void do_sprites_1 (int num, int cycle, int hpos)
3583 + struct sprite *s = &spr[num];
3587 + if (vpos == s->vstart)
3588 + s->state = SPR_waiting_stop;
3589 + if (vpos == s->vstop)
3590 + s->state = SPR_restart;
3592 + if (!dmaen (DMA_SPRITE))
3594 + dma = hpos < ddfstrt || diwstate != DIW_waiting_stop || !dmaen (DMA_BITPLANE);
3595 + if (s->state == SPR_restart || vpos == sprite_vblank_endline) {
3596 + uae_u16 data = sprite_fetch (s, dma);
3597 + s->pt += (sprite_width >> 3) - 2;
3598 +#ifdef SPRITE_DEBUG
3599 + write_log ("dma:");
3602 + SPRxPOS_1 (dma ? data : sprpos[num], num, hpos);
3604 + s->state = SPR_waiting_start;
3605 + SPRxCTL_1 (dma ? data : sprctl[num], num, hpos);
3607 + } else if (s->state == SPR_waiting_stop) {
3608 + uae_u16 data = sprite_fetch (s, dma);
3609 + /* Hack for X mouse auto-calibration */
3610 + if (num == 0 && cycle == 0)
3611 + mousehack_handle (sprctl[0], sprpos[0]);
3614 + SPRxDATA_1 (dma ? data : sprdata[num][0], num);
3616 + SPRxDATB_1 (dma ? data : sprdatb[num][0], num);
3617 + switch (sprite_width)
3621 + uae_u32 data32 = sprite_fetch (s, dma);
3622 + uae_u32 data641 = sprite_fetch (s, dma);
3623 + uae_u32 data642 = sprite_fetch (s, dma);
3626 + sprdata[num][3] = data642;
3627 + sprdata[num][2] = data641;
3628 + sprdata[num][1] = data32;
3630 + sprdatb[num][3] = data642;
3631 + sprdatb[num][2] = data641;
3632 + sprdatb[num][1] = data32;
3639 + uae_u32 data32 = sprite_fetch (s, dma);
3642 + sprdata[num][1] = data32;
3644 + sprdatb[num][1] = data32;
3652 +#define SPR0_HPOS 0x15
3653 +static void do_sprites (int hpos)
3655 + int maxspr, minspr;
3658 + /* I don't know whether this is right. Some programs write the sprite pointers
3659 + * directly at the start of the copper list. With the test against currvp, the
3660 + * first two words of data are read on the second line in the frame. The problem
3661 + * occurs when the program jumps to another copperlist a few lines further down
3662 + * which _also_ writes the sprite pointer registers. This means that a) writing
3663 + * to the sprite pointers sets the state to SPR_restart; or b) that sprite DMA
3664 + * is disabled until the end of the vertical blanking interval. The HRM
3665 + * isn't clear - it says that the vertical sprite position can be set to any
3666 + * value, but this wouldn't be the first mistake... */
3667 + /* Update: I modified one of the programs to write the sprite pointers the
3668 + * second time only _after_ the VBlank interval, and it showed the same behaviour
3669 + * as it did unmodified under UAE with the above check. This indicates that the
3670 + * solution below is correct. */
3671 + /* Another update: seems like we have to use the NTSC value here (see Sanity Turmoil
3673 + /* Maximum for Sanity Turmoil: 27.
3674 + Minimum for Sanity Arte: 22. */
3675 + if (vpos < sprite_vblank_endline)
3679 + minspr = last_sprite_hpos;
3681 + if (minspr >= SPR0_HPOS + MAX_SPRITES * 4 || maxspr < SPR0_HPOS)
3684 + if (maxspr > SPR0_HPOS + MAX_SPRITES * 4)
3685 + maxspr = SPR0_HPOS + MAX_SPRITES * 4;
3686 + if (minspr < SPR0_HPOS)
3687 + minspr = SPR0_HPOS;
3689 + for (i = minspr; i < maxspr; i++) {
3691 + switch ((i - SPR0_HPOS) & 3)
3701 + do_sprites_1 ((i - SPR0_HPOS) / 4, cycle, i);
3703 + last_sprite_hpos = hpos;
3706 +static void init_sprites (void)
3710 + for (i = 0; i < MAX_SPRITES; i++)
3711 + spr[i].state = SPR_restart;
3712 + memset (sprpos, 0, sizeof sprpos);
3713 + memset (sprctl, 0, sizeof sprctl);
3716 +static void adjust_array_sizes (void)
3718 +#ifdef OS_WITHOUT_MEMORY_MANAGEMENT
3719 + if (delta_sprite_entry) {
3721 + int mcc = max_sprite_entry + 50 + delta_sprite_entry;
3722 + delta_sprite_entry = 0;
3723 + p1 = realloc (sprite_entries[0], mcc * sizeof (struct sprite_entry));
3724 + p2 = realloc (sprite_entries[1], mcc * sizeof (struct sprite_entry));
3725 + if (p1) sprite_entries[0] = p1;
3726 + if (p2) sprite_entries[1] = p2;
3728 + write_log ("new max_sprite_entry=%d\n",mcc);
3729 + max_sprite_entry = mcc;
3732 + if (delta_color_change) {
3734 + int mcc = max_color_change + 200 + delta_color_change;
3735 + delta_color_change = 0;
3736 + p1 = realloc (color_changes[0], mcc * sizeof (struct color_change));
3737 + p2 = realloc (color_changes[1], mcc * sizeof (struct color_change));
3738 + if (p1) color_changes[0] = p1;
3739 + if (p2) color_changes[1] = p2;
3741 + write_log ("new max_color_change=%d\n",mcc);
3742 + max_color_change = mcc;
3748 +static void init_hardware_frame (void)
3751 + nextline_how = nln_normal;
3752 + diwstate = DIW_waiting_start;
3753 + hdiwstate = DIW_waiting_start;
3756 +void init_hardware_for_drawing_frame (void)
3758 + adjust_array_sizes ();
3760 + /* Avoid this code in the first frame after a customreset. */
3761 + if (prev_sprite_entries) {
3762 + int first_pixel = prev_sprite_entries[0].first_pixel;
3763 + int npixels = prev_sprite_entries[prev_next_sprite_entry].first_pixel - first_pixel;
3764 + memset (spixels + first_pixel, 0, npixels * sizeof *spixels);
3765 + memset (spixstate.bytes + first_pixel, 0, npixels * sizeof *spixstate.bytes);
3767 + prev_next_sprite_entry = next_sprite_entry;
3769 + next_color_change = 0;
3770 + next_sprite_entry = 0;
3771 + next_color_entry = 0;
3772 + remembered_color_entry = -1;
3774 + prev_sprite_entries = sprite_entries[current_change_set];
3775 + curr_sprite_entries = sprite_entries[current_change_set ^ 1];
3776 + prev_color_changes = color_changes[current_change_set];
3777 + curr_color_changes = color_changes[current_change_set ^ 1];
3778 + prev_color_tables = color_tables[current_change_set];
3779 + curr_color_tables = color_tables[current_change_set ^ 1];
3781 + prev_drawinfo = line_drawinfo[current_change_set];
3782 + curr_drawinfo = line_drawinfo[current_change_set ^ 1];
3783 + current_change_set ^= 1;
3785 + color_src_match = color_dest_match = -1;
3787 + /* Use both halves of the array in alternating fashion. */
3788 + curr_sprite_entries[0].first_pixel = current_change_set * MAX_SPR_PIXELS;
3789 + next_sprite_forced = 1;
3792 +static void do_savestate(void);
3794 +static void vsync_handler (void)
3797 + for (i = 0; i < MAX_SPRITES; i++)
3798 + spr[i].state = SPR_waiting_start;
3802 + if (currprefs.m68k_speed == -1) {
3803 + frame_time_t curr_time = read_processor_time ();
3804 + vsyncmintime += vsynctime;
3805 + /* @@@ Mathias? How do you think we should do this? */
3806 + /* If we are too far behind, or we just did a reset, adjust the
3808 + if ((long int)(curr_time - vsyncmintime) > 0 || rpt_did_reset)
3809 + vsyncmintime = curr_time + vsynctime;
3810 + rpt_did_reset = 0;
3812 +#ifdef RPT_WORKS_OK
3813 + if (RPT_WORKS_OK) {
3814 + frame_time_t curr_time;
3816 + curr_time = read_processor_time ();
3817 + while ((long int)(read_processor_time () - vsyncmintime) < 0);
3818 + vsyncmintime = curr_time + vsynctime;
3825 + getjoystate (0, &joy0dir, &joy0button);
3826 + getjoystate (1, &joy1dir, &joy1button);
3834 + picasso_handle_vsync ();
3836 + vsync_handle_redraw (lof, lof_changed);
3838 + if (quit_program > 0)
3842 + static int cnt = 0;
3844 + /* resolution_check_change (); */
3845 + DISK_check_change ();
3851 + /* Start a new set of copper records. */
3852 + curr_cop_set ^= 1;
3853 + nr_cop_records[curr_cop_set] = 0;
3855 + /* For now, let's only allow this to change at vsync time. It gets too
3856 + * hairy otherwise. */
3857 + if (beamcon0 != new_beamcon0)
3862 + cop_state.ip = cop1lc;
3863 + cop_state.state = COP_read1;
3864 + cop_state.vpos = 0;
3865 + cop_state.hpos = 0;
3866 + cop_state.ignore_next = 0;
3868 + init_hardware_frame ();
3870 +#ifdef HAVE_GETTIMEOFDAY
3872 + struct timeval tv;
3873 + unsigned long int newtime;
3875 + gettimeofday (&tv,NULL);
3876 + newtime = (tv.tv_sec-seconds_base) * 1000 + tv.tv_usec / 1000;
3878 + if (!bogusframe) {
3879 + lastframetime = newtime - msecs;
3881 +#if 0 /* This doesn't appear to work too well yet... later. */
3882 + if (n_consecutive_skipped > currprefs.sound_pri_cutoff
3883 + || lastframetime < currprefs.sound_pri_time)
3885 + n_consecutive_skipped = 0;
3886 + clear_inhibit_frame (IHF_SOUNDADJUST);
3888 + n_consecutive_skipped++;
3889 + set_inhibit_frame (IHF_SOUNDADJUST);
3894 + frametime += lastframetime;
3897 + if ((timeframes & 127) == 0)
3898 + gui_fps (1000 * timeframes / frametime);
3904 + if (ievent_alive > 0)
3906 + if (timehack_alive > 0)
3908 + CIA_vsync_handler ();
3911 +static void hsync_handler (void)
3913 + /* Using 0x8A makes sure that we don't accidentally trip over the
3914 + modified_regtypes check. */
3915 + sync_copper_with_cpu (maxhpos, 0, 0x8A);
3917 + finish_decisions ();
3918 + if (thisline_decision.plfleft != -1) {
3919 + if (currprefs.collision_level > 1)
3920 + do_sprite_collisions ();
3921 + if (currprefs.collision_level > 2)
3922 + do_playfield_collisions ();
3924 + hsync_record_line_state (next_lineno, nextline_how, thisline_changed);
3926 + eventtab[ev_hsync].evtime += get_cycles () - eventtab[ev_hsync].oldcycles;
3927 + eventtab[ev_hsync].oldcycles = get_cycles ();
3928 + CIA_hsync_handler ();
3930 + if (currprefs.produce_sound > 0) {
3935 + /* Sound data is fetched at the beginning of each line */
3936 + for (nr = 0; nr < 4; nr++) {
3937 + struct audio_channel_data *cdp = audio_channel + nr;
3939 + if (cdp->data_written == 2) {
3940 + cdp->data_written = 0;
3941 + cdp->nextdat = chipmem_wget (cdp->pt);
3943 + if (cdp->state == 2 || cdp->state == 3) {
3944 + if (cdp->wlen == 1) {
3945 + cdp->pt = cdp->lc;
3946 + cdp->wlen = cdp->len;
3949 + cdp->wlen = (cdp->wlen - 1) & 0xFFFF;
3955 + hardware_line_completed (next_lineno);
3957 + /* In theory only an equality test is needed here - but if a program
3958 + goes haywire with the VPOSW register, it can cause us to miss this,
3959 + with vpos going into the thousands (and all the nasty consequences
3962 + if (++vpos >= (maxvpos + (lof != 0))) {
3969 + is_lastline = vpos + 1 == maxvpos + (lof != 0) && currprefs.m68k_speed == -1 && ! rpt_did_reset;
3971 + if ((bplcon0 & 4) && currprefs.gfx_linedbl)
3972 + notice_interlace_seen ();
3974 + if (framecnt == 0) {
3975 + int lineno = vpos;
3976 + nextline_how = nln_normal;
3977 + if (currprefs.gfx_linedbl) {
3979 + nextline_how = currprefs.gfx_linedbl == 1 ? nln_doubled : nln_nblack;
3980 + if (bplcon0 & 4) {
3983 + nextline_how = nln_lower;
3985 + nextline_how = nln_upper;
3989 + next_lineno = lineno;
3990 + reset_decisions ();
3992 + if (uae_int_requested) {
3993 + set_uae_int_flag ();
3996 + /* See if there's a chance of a copper wait ending this line. */
3997 + cop_state.hpos = 0;
3998 + compute_spcflag_copper ();
4001 +static void init_regtypes (void)
4004 + for (i = 0; i < 512; i += 2) {
4005 + regtypes[i] = REGTYPE_ALL;
4006 + if ((i >= 0x20 && i < 0x28) || i == 0x08 || i == 0x7E)
4007 + regtypes[i] = REGTYPE_DISK;
4008 + else if (i >= 0x68 && i < 0x70)
4009 + regtypes[i] = REGTYPE_NONE;
4010 + else if (i >= 0x40 && i < 0x78)
4011 + regtypes[i] = REGTYPE_BLITTER;
4012 + else if (i >= 0xA0 && i < 0xE0 && (i & 0xF) < 0xE)
4013 + regtypes[i] = REGTYPE_AUDIO;
4014 + else if (i >= 0xA0 && i < 0xE0)
4015 + regtypes[i] = REGTYPE_NONE;
4016 + else if (i >= 0xE0 && i < 0x100)
4017 + regtypes[i] = REGTYPE_PLANE;
4018 + else if (i >= 0x120 && i < 0x180)
4019 + regtypes[i] = REGTYPE_SPRITE;
4020 + else if (i >= 0x180 && i < 0x1C0)
4021 + regtypes[i] = REGTYPE_COLOR;
4024 + /* DMACONR - setting this to REGTYPE_BLITTER will cause it to
4025 + conflict with DMACON (since that is REGTYPE_ALL), and the
4026 + blitter registers (for the BBUSY bit), but nothing else,
4027 + which is (I think) what we want. */
4028 + regtypes[i] = REGTYPE_BLITTER;
4030 + case 0x04: case 0x06: case 0x2A: case 0x2C:
4031 + regtypes[i] = REGTYPE_POS;
4033 + case 0x0A: case 0x0C:
4034 + case 0x12: case 0x14: case 0x16:
4036 + regtypes[i] = REGTYPE_JOYPORT;
4040 + regtypes[i] = REGTYPE_PLANE;
4042 + case 0x88: case 0x8A:
4043 + case 0x8E: case 0x90: case 0x92: case 0x94:
4046 + regtypes[i] |= REGTYPE_FORCE;
4052 +void init_eventtab (void)
4057 + for (i = 0; i < ev_max; i++) {
4058 + eventtab[i].active = 0;
4059 + eventtab[i].oldcycles = 0;
4062 + eventtab[ev_cia].handler = CIA_handler;
4063 + eventtab[ev_hsync].handler = hsync_handler;
4064 + eventtab[ev_hsync].evtime = maxhpos * CYCLE_UNIT + get_cycles ();
4065 + eventtab[ev_hsync].active = 1;
4067 + eventtab[ev_copper].handler = copper_handler;
4068 + eventtab[ev_copper].active = 0;
4069 + eventtab[ev_blitter].handler = blitter_handler;
4070 + eventtab[ev_blitter].active = 0;
4071 + eventtab[ev_disk].handler = DISK_handler;
4072 + eventtab[ev_disk].active = 0;
4073 + eventtab[ev_audio].handler = audio_evhandler;
4074 + eventtab[ev_audio].active = 0;
4075 + events_schedule ();
4078 +void customreset (void)
4082 +#ifdef HAVE_GETTIMEOFDAY
4083 + struct timeval tv;
4086 + if (! savestate_state) {
4087 + currprefs.chipset_mask = changed_prefs.chipset_mask;
4088 + if ((currprefs.chipset_mask & CSMASK_AGA) == 0) {
4089 + for (i = 0; i < 32; i++) {
4090 + current_colors.color_regs_ecs[i] = 0;
4091 + current_colors.acolors[i] = xcolors[0];
4094 + for (i = 0; i < 256; i++) {
4095 + current_colors.color_regs_aga[i] = 0;
4096 + current_colors.acolors[i] = CONVERT_RGB (zero);
4100 + clx_sprmask = 0xFF;
4103 + /* Clear the armed flags of all sprites. */
4104 + memset (spr, 0, sizeof spr);
4107 + dmacon = intena = 0;
4113 + bplcon4 = 0x11; /* Get AGA chipset into ECS compatibility mode */
4128 + unset_special (~(SPCFLAG_BRK | SPCFLAG_MODE_CHANGE));
4132 + if (needmousehack ()) {
4134 + mousehack_setfollow();
4136 + mousehack_setdontcare();
4139 + mousestate = normal_mouse;
4142 + timehack_alive = 0;
4144 + curr_sprite_entries = 0;
4145 + prev_sprite_entries = 0;
4146 + sprite_entries[0][0].first_pixel = 0;
4147 + sprite_entries[1][0].first_pixel = MAX_SPR_PIXELS;
4148 + sprite_entries[0][1].first_pixel = 0;
4149 + sprite_entries[1][1].first_pixel = MAX_SPR_PIXELS;
4150 + memset (spixels, 0, sizeof spixels);
4151 + memset (&spixstate, 0, sizeof spixstate);
4153 + bltstate = BLT_done;
4154 + cop_state.state = COP_stop;
4155 + diwstate = DIW_waiting_start;
4156 + hdiwstate = DIW_waiting_start;
4159 + new_beamcon0 = currprefs.ntscmode ? 0x00 : 0x20;
4166 + init_hardware_frame ();
4169 + reset_decisions ();
4171 +#ifdef HAVE_GETTIMEOFDAY
4172 + gettimeofday (&tv, NULL);
4173 + seconds_base = tv.tv_sec;
4179 + sprite_buffer_res = currprefs.chipset_mask & CSMASK_AGA ? RES_HIRES : RES_LORES;
4180 + if (savestate_state == STATE_RESTORE) {
4184 + update_adkmasks ();
4192 + diwhigh_written = 1;
4197 + if (!(currprefs.chipset_mask & CSMASK_AGA)) {
4198 + for(i = 0 ; i < 32 ; i++) {
4199 + vv = current_colors.color_regs_ecs[i];
4200 + current_colors.color_regs_ecs[i] = -1;
4201 + record_color_change (0, i, vv);
4202 + remembered_color_entry = -1;
4203 + current_colors.color_regs_ecs[i] = vv;
4204 + current_colors.acolors[i] = xcolors[vv];
4207 + for(i = 0 ; i < 256 ; i++) {
4208 + vv = current_colors.color_regs_aga[i];
4209 + current_colors.color_regs_aga[i] = -1;
4210 + record_color_change (0, i, vv);
4211 + remembered_color_entry = -1;
4212 + current_colors.color_regs_aga[i] = vv;
4213 + current_colors.acolors[i] = CONVERT_RGB(vv);
4217 + CLXCON2 (clxcon2);
4219 + write_log ("State restored\n");
4221 + for (i = 0; i < 8; i++)
4222 + nr_armed += spr[i].armed != 0;
4227 +void dumpcustom (void)
4229 + write_log ("DMACON: %x INTENA: %x INTREQ: %x VPOS: %x HPOS: %x\n", DMACONR(),
4230 + (unsigned int)intena, (unsigned int)intreq, (unsigned int)vpos, (unsigned int)current_hpos());
4231 + write_log ("COP1LC: %08lx, COP2LC: %08lx\n", (unsigned long)cop1lc, (unsigned long)cop2lc);
4232 + write_log ("DIWSTRT: %04x DIWSTOP: %04x DDFSTRT: %04x DDFSTOP: %04x\n",
4233 + (unsigned int)diwstrt, (unsigned int)diwstop, (unsigned int)ddfstrt, (unsigned int)ddfstop);
4235 + write_log ("Average frame time: %d ms [frames: %d time: %d]\n",
4236 + frametime / timeframes, timeframes, frametime);
4237 + if (total_skipped)
4238 + write_log ("Skipped frames: %d\n", total_skipped);
4240 + /*for (i=0; i<256; i++) if (blitcount[i]) write_log ("minterm %x = %d\n",i,blitcount[i]); blitter debug */
4245 + uae_u16 imask = intreq & intena;
4246 + if (imask && (intena & 0x4000)){
4247 + if (imask & 0x2000) return 6;
4248 + if (imask & 0x1800) return 5;
4249 + if (imask & 0x0780) return 4;
4250 + if (imask & 0x0070) return 3;
4251 + if (imask & 0x0008) return 2;
4252 + if (imask & 0x0007) return 1;
4257 +static void gen_custom_tables (void)
4260 + for (i = 0; i < 256; i++) {
4262 + sprtaba[i] = ((((i >> 7) & 1) << 0)
4263 + | (((i >> 6) & 1) << 2)
4264 + | (((i >> 5) & 1) << 4)
4265 + | (((i >> 4) & 1) << 6)
4266 + | (((i >> 3) & 1) << 8)
4267 + | (((i >> 2) & 1) << 10)
4268 + | (((i >> 1) & 1) << 12)
4269 + | (((i >> 0) & 1) << 14));
4270 + sprtabb[i] = sprtaba[i] * 2;
4271 + sprite_ab_merge[i] = (((i & 15) ? 1 : 0)
4272 + | ((i & 240) ? 2 : 0));
4274 + for (i = 0; i < 16; i++) {
4275 + clxmask[i] = (((i & 1) ? 0xF : 0x3)
4276 + | ((i & 2) ? 0xF0 : 0x30)
4277 + | ((i & 4) ? 0xF00 : 0x300)
4278 + | ((i & 8) ? 0xF000 : 0x3000));
4279 + sprclx[i] = (((i & 0x3) == 0x3 ? 1 : 0)
4280 + | ((i & 0x5) == 0x5 ? 2 : 0)
4281 + | ((i & 0x9) == 0x9 ? 4 : 0)
4282 + | ((i & 0x6) == 0x6 ? 8 : 0)
4283 + | ((i & 0xA) == 0xA ? 16 : 0)
4284 + | ((i & 0xC) == 0xC ? 32 : 0)) << 9;
4288 +void custom_init (void)
4292 +#ifdef OS_WITHOUT_MEMORY_MANAGEMENT
4295 + for (num = 0; num < 2; num++) {
4296 + sprite_entries[num] = xmalloc (max_sprite_entry * sizeof (struct sprite_entry));
4297 + color_changes[num] = xmalloc (max_color_change * sizeof (struct color_change));
4303 + org (RTAREA_BASE+0xFF70);
4304 + calltrap (deftrap (mousehack_helper));
4307 + org (RTAREA_BASE+0xFFA0);
4308 + calltrap (deftrap (timehack_helper));
4313 + gen_custom_tables ();
4314 + build_blitfilltable ();
4318 + mousestate = unknown_mouse;
4320 + if (needmousehack ())
4321 + mousehack_setfollow ();
4323 + create_cycle_diagram_table ();
4326 +/* Custom chip memory bank */
4328 +static uae_u32 custom_lget (uaecptr) REGPARAM;
4329 +static uae_u32 custom_wget (uaecptr) REGPARAM;
4330 +static uae_u32 custom_bget (uaecptr) REGPARAM;
4331 +static void custom_lput (uaecptr, uae_u32) REGPARAM;
4332 +static void custom_wput (uaecptr, uae_u32) REGPARAM;
4333 +static void custom_bput (uaecptr, uae_u32) REGPARAM;
4335 +addrbank custom_bank = {
4336 + custom_lget, custom_wget, custom_bget,
4337 + custom_lput, custom_wput, custom_bput,
4338 + default_xlate, default_check, NULL
4341 +STATIC_INLINE uae_u32 REGPARAM2 custom_wget_1 (uaecptr addr)
4344 + special_mem |= S_READ;
4345 + switch (addr & 0x1FE) {
4346 + case 0x002: v = DMACONR (); break;
4347 + case 0x004: v = VPOSR (); break;
4348 + case 0x006: v = VHPOSR (); break;
4350 + case 0x008: v = DSKDATR (current_hpos ()); break;
4352 + case 0x00A: v = JOY0DAT (); break;
4353 + case 0x00C: v = JOY1DAT (); break;
4354 + case 0x00E: v = CLXDAT (); break;
4355 + case 0x010: v = ADKCONR (); break;
4357 + case 0x012: v = POT0DAT (); break;
4358 + case 0x016: v = POTGOR (); break;
4359 + case 0x018: v = SERDATR (); break;
4360 + case 0x01A: v = DSKBYTR (current_hpos ()); break;
4361 + case 0x01C: v = INTENAR (); break;
4362 + case 0x01E: v = INTREQR (); break;
4363 + case 0x07C: v = DENISEID (); break;
4365 + case 0x180: case 0x182: case 0x184: case 0x186: case 0x188: case 0x18A:
4366 + case 0x18C: case 0x18E: case 0x190: case 0x192: case 0x194: case 0x196:
4367 + case 0x198: case 0x19A: case 0x19C: case 0x19E: case 0x1A0: case 0x1A2:
4368 + case 0x1A4: case 0x1A6: case 0x1A8: case 0x1AA: case 0x1AC: case 0x1AE:
4369 + case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA:
4370 + case 0x1BC: case 0x1BE:
4371 + v = COLOR_READ ((addr & 0x3E) / 2);
4375 + v = last_custom_value;
4376 + custom_wput (addr, v);
4377 + last_custom_value = 0xffff;
4380 + last_custom_value = v;
4384 +uae_u32 REGPARAM2 custom_wget (uaecptr addr)
4386 + sync_copper_with_cpu (current_hpos (), 1, addr);
4387 + return custom_wget_1 (addr);
4390 +uae_u32 REGPARAM2 custom_bget (uaecptr addr)
4392 + special_mem |= S_READ;
4393 + return custom_wget (addr & 0xfffe) >> (addr & 1 ? 0 : 8);
4396 +uae_u32 REGPARAM2 custom_lget (uaecptr addr)
4398 + special_mem |= S_READ;
4399 + return ((uae_u32)custom_wget (addr & 0xfffe) << 16) | custom_wget ((addr + 2) & 0xfffe);
4402 +void REGPARAM2 custom_wput_1 (int hpos, uaecptr addr, uae_u32 value)
4405 + last_custom_value = value;
4407 + case 0x020: DSKPTH (value); break;
4408 + case 0x022: DSKPTL (value); break;
4409 + case 0x024: DSKLEN (value, hpos); break;
4410 + case 0x026: DSKDAT (value); break;
4412 + case 0x02A: VPOSW (value); break;
4413 + case 0x02E: COPCON (value); break;
4414 + case 0x030: SERDAT (value); break;
4415 + case 0x032: SERPER (value); break;
4416 + case 0x034: POTGO (value); break;
4417 + case 0x040: BLTCON0 (value); break;
4418 + case 0x042: BLTCON1 (value); break;
4420 + case 0x044: BLTAFWM (value); break;
4421 + case 0x046: BLTALWM (value); break;
4423 + case 0x050: BLTAPTH (value); break;
4424 + case 0x052: BLTAPTL (value); break;
4425 + case 0x04C: BLTBPTH (value); break;
4426 + case 0x04E: BLTBPTL (value); break;
4427 + case 0x048: BLTCPTH (value); break;
4428 + case 0x04A: BLTCPTL (value); break;
4429 + case 0x054: BLTDPTH (value); break;
4430 + case 0x056: BLTDPTL (value); break;
4432 + case 0x058: BLTSIZE (value); break;
4434 + case 0x064: BLTAMOD (value); break;
4435 + case 0x062: BLTBMOD (value); break;
4436 + case 0x060: BLTCMOD (value); break;
4437 + case 0x066: BLTDMOD (value); break;
4439 + case 0x070: BLTCDAT (value); break;
4440 + case 0x072: BLTBDAT (value); break;
4441 + case 0x074: BLTADAT (value); break;
4443 + case 0x07E: DSKSYNC (value); break;
4445 + case 0x080: COP1LCH (value); break;
4446 + case 0x082: COP1LCL (value); break;
4447 + case 0x084: COP2LCH (value); break;
4448 + case 0x086: COP2LCL (value); break;
4450 + case 0x088: COPJMP1 (value); break;
4451 + case 0x08A: COPJMP2 (value); break;
4453 + case 0x08E: DIWSTRT (hpos, value); break;
4454 + case 0x090: DIWSTOP (hpos, value); break;
4455 + case 0x092: DDFSTRT (hpos, value); break;
4456 + case 0x094: DDFSTOP (hpos, value); break;
4458 + case 0x096: DMACON (hpos, value); break;
4459 + case 0x098: CLXCON (value); break;
4460 + case 0x09A: INTENA (value); break;
4461 + case 0x09C: INTREQ (value); break;
4462 + case 0x09E: ADKCON (value); break;
4464 + case 0x0A0: AUDxLCH (0, value); break;
4465 + case 0x0A2: AUDxLCL (0, value); break;
4466 + case 0x0A4: AUDxLEN (0, value); break;
4467 + case 0x0A6: AUDxPER (0, value); break;
4468 + case 0x0A8: AUDxVOL (0, value); break;
4469 + case 0x0AA: AUDxDAT (0, value); break;
4471 + case 0x0B0: AUDxLCH (1, value); break;
4472 + case 0x0B2: AUDxLCL (1, value); break;
4473 + case 0x0B4: AUDxLEN (1, value); break;
4474 + case 0x0B6: AUDxPER (1, value); break;
4475 + case 0x0B8: AUDxVOL (1, value); break;
4476 + case 0x0BA: AUDxDAT (1, value); break;
4478 + case 0x0C0: AUDxLCH (2, value); break;
4479 + case 0x0C2: AUDxLCL (2, value); break;
4480 + case 0x0C4: AUDxLEN (2, value); break;
4481 + case 0x0C6: AUDxPER (2, value); break;
4482 + case 0x0C8: AUDxVOL (2, value); break;
4483 + case 0x0CA: AUDxDAT (2, value); break;
4485 + case 0x0D0: AUDxLCH (3, value); break;
4486 + case 0x0D2: AUDxLCL (3, value); break;
4487 + case 0x0D4: AUDxLEN (3, value); break;
4488 + case 0x0D6: AUDxPER (3, value); break;
4489 + case 0x0D8: AUDxVOL (3, value); break;
4490 + case 0x0DA: AUDxDAT (3, value); break;
4492 + case 0x0E0: BPLPTH (hpos, value, 0); break;
4493 + case 0x0E2: BPLPTL (hpos, value, 0); break;
4494 + case 0x0E4: BPLPTH (hpos, value, 1); break;
4495 + case 0x0E6: BPLPTL (hpos, value, 1); break;
4496 + case 0x0E8: BPLPTH (hpos, value, 2); break;
4497 + case 0x0EA: BPLPTL (hpos, value, 2); break;
4498 + case 0x0EC: BPLPTH (hpos, value, 3); break;
4499 + case 0x0EE: BPLPTL (hpos, value, 3); break;
4500 + case 0x0F0: BPLPTH (hpos, value, 4); break;
4501 + case 0x0F2: BPLPTL (hpos, value, 4); break;
4502 + case 0x0F4: BPLPTH (hpos, value, 5); break;
4503 + case 0x0F6: BPLPTL (hpos, value, 5); break;
4504 + case 0x0F8: BPLPTH (hpos, value, 6); break;
4505 + case 0x0FA: BPLPTL (hpos, value, 6); break;
4506 + case 0x0FC: BPLPTH (hpos, value, 7); break;
4507 + case 0x0FE: BPLPTL (hpos, value, 7); break;
4509 + case 0x100: BPLCON0 (hpos, value); break;
4510 + case 0x102: BPLCON1 (hpos, value); break;
4511 + case 0x104: BPLCON2 (hpos, value); break;
4512 + case 0x106: BPLCON3 (hpos, value); break;
4514 + case 0x108: BPL1MOD (hpos, value); break;
4515 + case 0x10A: BPL2MOD (hpos, value); break;
4516 + case 0x10E: CLXCON2 (value); break;
4518 + case 0x110: BPL1DAT (hpos, value); break;
4519 + case 0x112: BPL2DAT (value); break;
4520 + case 0x114: BPL3DAT (value); break;
4521 + case 0x116: BPL4DAT (value); break;
4522 + case 0x118: BPL5DAT (value); break;
4523 + case 0x11A: BPL6DAT (value); break;
4524 + case 0x11C: BPL7DAT (value); break;
4525 + case 0x11E: BPL8DAT (value); break;
4527 + case 0x180: case 0x182: case 0x184: case 0x186: case 0x188: case 0x18A:
4528 + case 0x18C: case 0x18E: case 0x190: case 0x192: case 0x194: case 0x196:
4529 + case 0x198: case 0x19A: case 0x19C: case 0x19E: case 0x1A0: case 0x1A2:
4530 + case 0x1A4: case 0x1A6: case 0x1A8: case 0x1AA: case 0x1AC: case 0x1AE:
4531 + case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA:
4532 + case 0x1BC: case 0x1BE:
4533 + COLOR_WRITE (hpos, value & 0xFFF, (addr & 0x3E) / 2);
4535 + case 0x120: case 0x124: case 0x128: case 0x12C:
4536 + case 0x130: case 0x134: case 0x138: case 0x13C:
4537 + SPRxPTH (hpos, value, (addr - 0x120) / 4);
4539 + case 0x122: case 0x126: case 0x12A: case 0x12E:
4540 + case 0x132: case 0x136: case 0x13A: case 0x13E:
4541 + SPRxPTL (hpos, value, (addr - 0x122) / 4);
4543 + case 0x140: case 0x148: case 0x150: case 0x158:
4544 + case 0x160: case 0x168: case 0x170: case 0x178:
4545 + SPRxPOS (hpos, value, (addr - 0x140) / 8);
4547 + case 0x142: case 0x14A: case 0x152: case 0x15A:
4548 + case 0x162: case 0x16A: case 0x172: case 0x17A:
4549 + SPRxCTL (hpos, value, (addr - 0x142) / 8);
4551 + case 0x144: case 0x14C: case 0x154: case 0x15C:
4552 + case 0x164: case 0x16C: case 0x174: case 0x17C:
4553 + SPRxDATA (hpos, value, (addr - 0x144) / 8);
4555 + case 0x146: case 0x14E: case 0x156: case 0x15E:
4556 + case 0x166: case 0x16E: case 0x176: case 0x17E:
4557 + SPRxDATB (hpos, value, (addr - 0x146) / 8);
4560 + case 0x36: JOYTEST (value); break;
4561 + case 0x5A: BLTCON0L (value); break;
4562 + case 0x5C: BLTSIZV (value); break;
4563 + case 0x5E: BLTSIZH (value); break;
4564 + case 0x1E4: DIWHIGH (hpos, value); break;
4565 + case 0x10C: BPLCON4 (hpos, value); break;
4566 + case 0x1FC: FMODE (value); break;
4570 +void REGPARAM2 custom_wput (uaecptr addr, uae_u32 value)
4572 + int hpos = current_hpos ();
4573 + special_mem |= S_WRITE;
4575 + sync_copper_with_cpu (hpos, 1, addr);
4576 + custom_wput_1 (hpos, addr, value);
4579 +void REGPARAM2 custom_bput (uaecptr addr, uae_u32 value)
4581 + static int warned = 0;
4582 + /* Is this correct now? (There are people who bput things to the upper byte of AUDxVOL). */
4583 + uae_u16 rval = (value << 8) | (value & 0xFF);
4584 + special_mem |= S_WRITE;
4585 + custom_wput (addr, rval);
4586 + if (!warned || ((addr & 0xff0000) == 0xda0000)) {
4587 + write_log ("Byte put to custom register (addr=%lx val=%lx)\n", addr, value);
4592 +void REGPARAM2 custom_lput(uaecptr addr, uae_u32 value)
4594 + special_mem |= S_WRITE;
4595 + custom_wput (addr & 0xfffe, value >> 16);
4596 + custom_wput ((addr + 2) & 0xfffe, (uae_u16)value);
4599 +void custom_prepare_savestate (void)
4601 + /* force blitter to finish, no support for saving full blitter state yet */
4602 + if (eventtab[ev_blitter].active) {
4603 + unsigned int olddmacon = dmacon;
4604 + dmacon |= DMA_BLITTER; /* ugh.. */
4605 + blitter_handler ();
4606 + dmacon = olddmacon;
4610 +#define RB restore_u8 ()
4611 +#define RW restore_u16 ()
4612 +#define RL restore_u32 ()
4614 +uae_u8 *restore_custom (uae_u8 *src)
4616 + uae_u16 dsklen, dskbytr, dskdatr;
4622 + currprefs.chipset_mask = RL;
4624 + RW; /* 002 DMACONR */
4625 + RW; /* 004 VPOSR */
4626 + RW; /* 006 VHPOSR */
4627 + dskdatr = RW; /* 008 DSKDATR */
4628 + RW; /* 00A JOY0DAT */
4629 + RW; /* 00C JOY1DAT */
4630 + clxdat = RW; /* 00E CLXDAT */
4631 + RW; /* 010 ADKCONR */
4632 + RW; /* 012 POT0DAT* */
4633 + RW; /* 014 POT1DAT* */
4634 + RW; /* 016 POTINP* */
4635 + RW; /* 018 SERDATR* */
4636 + dskbytr = RW; /* 01A DSKBYTR */
4637 + RW; /* 01C INTENAR */
4638 + RW; /* 01E INTREQR */
4639 + dskpt = RL; /* 020-022 DSKPT */
4640 + dsklen = RW; /* 024 DSKLEN */
4641 + RW; /* 026 DSKDAT */
4642 + RW; /* 028 REFPTR */
4643 + lof = RW; /* 02A VPOSW */
4644 + RW; /* 02C VHPOSW */
4645 + COPCON(RW); /* 02E COPCON */
4646 + RW; /* 030 SERDAT* */
4647 + RW; /* 032 SERPER* */
4648 + POTGO(RW); /* 034 POTGO */
4649 + RW; /* 036 JOYTEST* */
4650 + RW; /* 038 STREQU */
4651 + RW; /* 03A STRVHBL */
4652 + RW; /* 03C STRHOR */
4653 + RW; /* 03E STRLONG */
4654 + BLTCON0(RW); /* 040 BLTCON0 */
4655 + BLTCON1(RW); /* 042 BLTCON1 */
4656 + BLTAFWM(RW); /* 044 BLTAFWM */
4657 + BLTALWM(RW); /* 046 BLTALWM */
4658 + BLTCPTH(RL); /* 048-04B BLTCPT */
4659 + BLTBPTH(RL); /* 04C-04F BLTBPT */
4660 + BLTAPTH(RL); /* 050-053 BLTAPT */
4661 + BLTDPTH(RL); /* 054-057 BLTDPT */
4662 + RW; /* 058 BLTSIZE */
4663 + RW; /* 05A BLTCON0L */
4664 + oldvblts = RW; /* 05C BLTSIZV */
4665 + RW; /* 05E BLTSIZH */
4666 + BLTCMOD(RW); /* 060 BLTCMOD */
4667 + BLTBMOD(RW); /* 062 BLTBMOD */
4668 + BLTAMOD(RW); /* 064 BLTAMOD */
4669 + BLTDMOD(RW); /* 066 BLTDMOD */
4674 + BLTCDAT(RW); /* 070 BLTCDAT */
4675 + BLTBDAT(RW); /* 072 BLTBDAT */
4676 + BLTADAT(RW); /* 074 BLTADAT */
4680 + RW; /* 07C LISAID */
4681 + DSKSYNC(RW); /* 07E DSKSYNC */
4682 + cop1lc = RL; /* 080/082 COP1LC */
4683 + cop2lc = RL; /* 084/086 COP2LC */
4687 + diwstrt = RW; /* 08E DIWSTRT */
4688 + diwstop = RW; /* 090 DIWSTOP */
4689 + ddfstrt = RW; /* 092 DDFSTRT */
4690 + ddfstop = RW; /* 094 DDFSTOP */
4691 + dmacon = RW & ~(0x2000|0x4000); /* 096 DMACON */
4692 + CLXCON(RW); /* 098 CLXCON */
4693 + intena = RW; /* 09A INTENA */
4694 + intreq = RW; /* 09C INTREQ */
4695 + adkcon = RW; /* 09E ADKCON */
4696 + for (i = 0; i < 8; i++)
4698 + bplcon0 = RW; /* 100 BPLCON0 */
4699 + bplcon1 = RW; /* 102 BPLCON1 */
4700 + bplcon2 = RW; /* 104 BPLCON2 */
4701 + bplcon3 = RW; /* 106 BPLCON3 */
4702 + bpl1mod = RW; /* 108 BPL1MOD */
4703 + bpl2mod = RW; /* 10A BPL2MOD */
4704 + bplcon4 = RW; /* 10C BPLCON4 */
4705 + clxcon2 = RW; /* 10E CLXCON2* */
4706 + for(i = 0; i < 8; i++)
4708 + for(i = 0; i < 32; i++)
4709 + current_colors.color_regs_ecs[i] = RW; /* 180 COLORxx */
4724 + new_beamcon0 = RW; /* 1DC BEAMCON0 */
4740 + fmode = RW; /* 1FC FMODE */
4743 + DISK_restore_custom (dskpt, dsklen, dskdatr, dskbytr);
4750 +#define SW save_u16
4751 +#define SL save_u32
4753 +extern uae_u16 serper;
4755 +uae_u8 *save_custom (int *len)
4757 + uae_u8 *dstbak, *dst;
4760 + uae_u16 dsklen, dsksync, dskdatr, dskbytr;
4762 + DISK_save_custom (&dskpt, &dsklen, &dsksync, &dskdatr, &dskbytr);
4763 + dstbak = dst = malloc (8+256*2);
4764 + SL (currprefs.chipset_mask);
4765 + SW (0); /* 000 ? */
4766 + SW (dmacon); /* 002 DMACONR */
4767 + SW (VPOSR()); /* 004 VPOSR */
4768 + SW (VHPOSR()); /* 006 VHPOSR */
4769 + SW (dskdatr); /* 008 DSKDATR */
4770 + SW (JOY0DAT()); /* 00A JOY0DAT */
4771 + SW (JOY1DAT()); /* 00C JOY1DAT */
4772 + SW (clxdat); /* 00E CLXDAT */
4773 + SW (ADKCONR()); /* 010 ADKCONR */
4774 + SW (POT0DAT()); /* 012 POT0DAT */
4775 + SW (POT0DAT()); /* 014 POT1DAT */
4776 + SW (0) ; /* 016 POTINP * */
4777 + SW (0); /* 018 SERDATR * */
4778 + SW (dskbytr); /* 01A DSKBYTR */
4779 + SW (INTENAR()); /* 01C INTENAR */
4780 + SW (INTREQR()); /* 01E INTREQR */
4781 + SL (dskpt); /* 020-023 DSKPT */
4782 + SW (dsklen); /* 024 DSKLEN */
4783 + SW (0); /* 026 DSKDAT */
4784 + SW (0); /* 028 REFPTR */
4785 + SW (lof); /* 02A VPOSW */
4786 + SW (0); /* 02C VHPOSW */
4787 + SW (copcon); /* 02E COPCON */
4788 + SW (serper); /* 030 SERDAT * */
4789 + SW (serdat); /* 032 SERPER * */
4790 + SW (potgo_value); /* 034 POTGO */
4791 + SW (0); /* 036 JOYTEST * */
4792 + SW (0); /* 038 STREQU */
4793 + SW (0); /* 03A STRVBL */
4794 + SW (0); /* 03C STRHOR */
4795 + SW (0); /* 03E STRLONG */
4796 + SW (bltcon0); /* 040 BLTCON0 */
4797 + SW (bltcon1); /* 042 BLTCON1 */
4798 + SW (blt_info.bltafwm); /* 044 BLTAFWM */
4799 + SW (blt_info.bltalwm); /* 046 BLTALWM */
4800 + SL (bltcpt); /* 048-04B BLTCPT */
4801 + SL (bltbpt); /* 04C-04F BLTCPT */
4802 + SL (bltapt); /* 050-043 BLTCPT */
4803 + SL (bltdpt); /* 054-057 BLTCPT */
4804 + SW (0); /* 058 BLTSIZE */
4805 + SW (0); /* 05A BLTCON0L (use BLTCON0 instead) */
4806 + SW (oldvblts); /* 05C BLTSIZV */
4807 + SW (blt_info.hblitsize); /* 05E BLTSIZH */
4808 + SW (blt_info.bltcmod); /* 060 BLTCMOD */
4809 + SW (blt_info.bltbmod); /* 062 BLTBMOD */
4810 + SW (blt_info.bltamod); /* 064 BLTAMOD */
4811 + SW (blt_info.bltdmod); /* 066 BLTDMOD */
4812 + SW (0); /* 068 ? */
4813 + SW (0); /* 06A ? */
4814 + SW (0); /* 06C ? */
4815 + SW (0); /* 06E ? */
4816 + SW (blt_info.bltcdat); /* 070 BLTCDAT */
4817 + SW (blt_info.bltbdat); /* 072 BLTBDAT */
4818 + SW (blt_info.bltadat); /* 074 BLTADAT */
4819 + SW (0); /* 076 ? */
4820 + SW (0); /* 078 ? */
4821 + SW (0); /* 07A ? */
4822 + SW (DENISEID()); /* 07C DENISEID/LISAID */
4823 + SW (dsksync); /* 07E DSKSYNC */
4824 + SL (cop1lc); /* 080-083 COP1LC */
4825 + SL (cop2lc); /* 084-087 COP2LC */
4826 + SW (0); /* 088 ? */
4827 + SW (0); /* 08A ? */
4828 + SW (0); /* 08C ? */
4829 + SW (diwstrt); /* 08E DIWSTRT */
4830 + SW (diwstop); /* 090 DIWSTOP */
4831 + SW (ddfstrt); /* 092 DDFSTRT */
4832 + SW (ddfstop); /* 094 DDFSTOP */
4833 + SW (dmacon); /* 096 DMACON */
4834 + SW (clxcon); /* 098 CLXCON */
4835 + SW (intena); /* 09A INTENA */
4836 + SW (intreq); /* 09C INTREQ */
4837 + SW (adkcon); /* 09E ADKCON */
4838 + for (i = 0; i < 8; i++)
4839 + SL (bplpt[i]); /* 0E0-0FE BPLxPT */
4840 + SW (bplcon0); /* 100 BPLCON0 */
4841 + SW (bplcon1); /* 102 BPLCON1 */
4842 + SW (bplcon2); /* 104 BPLCON2 */
4843 + SW (bplcon3); /* 106 BPLCON3 */
4844 + SW (bpl1mod); /* 108 BPL1MOD */
4845 + SW (bpl2mod); /* 10A BPL2MOD */
4846 + SW (bplcon4); /* 10C BPLCON4 */
4847 + SW (clxcon2); /* 10E CLXCON2 */
4848 + for (i = 0;i < 8; i++)
4849 + SW (0); /* 110 BPLxDAT */
4850 + for ( i = 0; i < 32; i++)
4851 + SW (current_colors.color_regs_ecs[i]); /* 180-1BE COLORxx */
4866 + SW (beamcon0); /* 1DC BEAMCON0 */
4882 + SW (fmode); /* 1FC FMODE */
4883 + SW (0xffff); /* 1FE */
4885 + *len = dst - dstbak;
4889 +uae_u8 *restore_custom_agacolors (uae_u8 *src)
4893 + for (i = 0; i < 256; i++)
4894 + current_colors.color_regs_aga[i] = RL;
4898 +uae_u8 *save_custom_agacolors (int *len)
4900 + uae_u8 *dstbak, *dst;
4903 + dstbak = dst = malloc (256*4);
4904 + for (i = 0; i < 256; i++)
4905 + SL (current_colors.color_regs_aga[i]);
4906 + *len = dst - dstbak;
4910 +uae_u8 *restore_custom_sprite (uae_u8 *src, int num)
4912 + spr[num].pt = RL; /* 120-13E SPRxPT */
4913 + sprpos[num] = RW; /* 1x0 SPRxPOS */
4914 + sprctl[num] = RW; /* 1x2 SPRxPOS */
4915 + sprdata[num][0] = RW; /* 1x4 SPRxDATA */
4916 + sprdatb[num][0] = RW; /* 1x6 SPRxDATB */
4917 + sprdata[num][1] = RW;
4918 + sprdatb[num][1] = RW;
4919 + sprdata[num][2] = RW;
4920 + sprdatb[num][2] = RW;
4921 + sprdata[num][3] = RW;
4922 + sprdatb[num][3] = RW;
4923 + spr[num].armed = RB;
4927 +uae_u8 *save_custom_sprite(int *len, int num)
4929 + uae_u8 *dstbak, *dst;
4931 + dstbak = dst = malloc (25);
4932 + SL (spr[num].pt); /* 120-13E SPRxPT */
4933 + SW (sprpos[num]); /* 1x0 SPRxPOS */
4934 + SW (sprctl[num]); /* 1x2 SPRxPOS */
4935 + SW (sprdata[num][0]); /* 1x4 SPRxDATA */
4936 + SW (sprdatb[num][0]); /* 1x6 SPRxDATB */
4937 + SW (sprdata[num][1]);
4938 + SW (sprdatb[num][1]);
4939 + SW (sprdata[num][2]);
4940 + SW (sprdatb[num][2]);
4941 + SW (sprdata[num][3]);
4942 + SW (sprdatb[num][3]);
4943 + SB (spr[num].armed ? 1 : 0);
4944 + *len = dst - dstbak;
4947 diff -urN src-0.8.22/src/debug.c src-0.8.22-mmu/src/debug.c
4948 --- src-0.8.22/src/debug.c 2001-10-24 12:59:20.000000000 +0200
4949 +++ src-0.8.22-mmu/src/debug.c 2003-07-25 12:13:43.000000000 +0200
4951 printf ("Plane %d offset %d\n", i, bpl_off[i]);
4955 + mmu_dump_tables();
4961 printf (" W <address> <value>: Write into Amiga memory\n");
4962 printf (" S <file> <addr> <n>: Save a block of Amiga memory\n");
4963 printf (" T: Show exec tasks and their PCs\n");
4964 + printf (" u: Dump the MMU translation tables and state\n");
4965 printf (" h,?: Show this help page\n");
4966 printf (" q: Quit the emulator. You don't want to use this command.\n\n");
4968 diff -urN src-0.8.22/src/debug.c~ src-0.8.22-mmu/src/debug.c~
4969 --- src-0.8.22/src/debug.c~ 1970-01-01 01:00:00.000000000 +0100
4970 +++ src-0.8.22-mmu/src/debug.c~ 2003-07-25 12:11:11.000000000 +0200
4973 + * UAE - The Un*x Amiga Emulator
4977 + * (c) 1995 Bernd Schmidt
4981 +#include "sysconfig.h"
4982 +#include "sysdeps.h"
4985 +#include <signal.h>
4987 +#include "config.h"
4988 +#include "options.h"
4989 +#include "threaddep/thread.h"
4991 +#include "memory.h"
4992 +#include "custom.h"
4993 +#include "newcpu.h"
4998 +#include "identify.h"
5000 +static int debugger_active = 0;
5001 +static uaecptr skipaddr;
5002 +static int do_skip;
5005 +static FILE *logfile;
5007 +void activate_debugger (void)
5013 + if (debugger_active)
5015 + debugger_active = 1;
5016 + set_special (SPCFLAG_BRK);
5018 + /* use_debugger = 1; */
5023 +#ifdef NEED_TO_DEBUG_BADLY
5024 +struct regstruct history[MAX_HIST];
5025 +union flagu historyf[MAX_HIST];
5027 +uaecptr history[MAX_HIST];
5030 +static void ignore_ws (char **c)
5032 + while (**c && isspace(**c)) (*c)++;
5035 +static uae_u32 readhex (char **c)
5042 + while (isxdigit(nc = **c)) {
5046 + if (isdigit(nc)) {
5049 + val += nc - 'A' + 10;
5055 +static uae_u32 readint (char **c)
5064 + negative = 1, (*c)++;
5065 + while (isdigit(nc = **c)) {
5070 + return val * (negative ? -1 : 1);
5073 +static char next_char( char **c)
5079 +static int more_params (char **c)
5082 + return (**c) != 0;
5085 +static void dumpmem (uaecptr addr, uaecptr *nxmem, int lines)
5088 + for (;lines-- && !broken_in;) {
5090 + printf ("%08lx ", addr);
5091 + for (i = 0; i < 16; i++) {
5092 + printf ("%04x ", get_word(addr)); addr += 2;
5099 +static void foundmod (uae_u32 ptr, char *type)
5102 + uae_u8 *ptr2 = chipmemory + ptr;
5105 + printf ("Found possible %s module at 0x%lx.\n", type, ptr);
5106 + memcpy (name, ptr2, 20);
5109 + /* Browse playlist */
5111 + for (i = 0x3b8; i < 0x438; i++)
5112 + if (ptr2[i] > length)
5115 + length = (length+1)*1024 + 0x43c;
5117 + /* Add sample lengths */
5119 + for (i = 0; i < 31; i++, ptr2 += 30)
5120 + length += 2*((ptr2[0]<<8)+ptr2[1]);
5122 + printf ("Name \"%s\", Length 0x%lx bytes.\n", name, length);
5125 +static void modulesearch (void)
5127 + uae_u8 *p = get_real_address (0);
5130 + for (ptr = 0; ptr < allocated_chipmem - 40; ptr += 2, p += 2) {
5131 + /* Check for Mahoney & Kaktus */
5132 + /* Anyone got the format of old 15 Sample (SoundTracker)modules? */
5133 + if (ptr >= 0x438 && p[0] == 'M' && p[1] == '.' && p[2] == 'K' && p[3] == '.')
5134 + foundmod (ptr - 0x438, "ProTracker (31 samples)");
5136 + if (ptr >= 0x438 && p[0] == 'F' && p[1] == 'L' && p[2] == 'T' && p[3] == '4')
5137 + foundmod (ptr - 0x438, "Startrekker");
5139 + if (strncmp ((char *)p, "SMOD", 4) == 0) {
5140 + printf ("Found possible FutureComposer 1.3 module at 0x%lx, length unknown.\n", ptr);
5142 + if (strncmp ((char *)p, "FC14", 4) == 0) {
5143 + printf ("Found possible FutureComposer 1.4 module at 0x%lx, length unknown.\n", ptr);
5145 + if (p[0] == 0x48 && p[1] == 0xe7 && p[4] == 0x61 && p[5] == 0
5146 + && p[8] == 0x4c && p[9] == 0xdf && p[12] == 0x4e && p[13] == 0x75
5147 + && p[14] == 0x48 && p[15] == 0xe7 && p[18] == 0x61 && p[19] == 0
5148 + && p[22] == 0x4c && p[23] == 0xdf && p[26] == 0x4e && p[27] == 0x75) {
5149 + printf ("Found possible Whittaker module at 0x%lx, length unknown.\n", ptr);
5151 + if (p[4] == 0x41 && p[5] == 0xFA) {
5154 + for (i = 0; i < 0x240; i += 2)
5155 + if (p[i] == 0xE7 && p[i + 1] == 0x42 && p[i + 2] == 0x41 && p[i + 3] == 0xFA)
5158 + uae_u8 *p2 = p + i + 4;
5159 + for (i = 0; i < 0x30; i += 2)
5160 + if (p2[i] == 0xD1 && p2[i + 1] == 0xFA) {
5161 + printf ("Found possible MarkII module at %lx, length unknown.\n", ptr);
5168 +static void dump_traps (void)
5171 + for (i = 0; trap_labels[i].name; i++) {
5172 + printf("$%02x: %s\t $%08x\n", trap_labels[i].adr,
5173 + trap_labels[i].name, get_long (trap_labels[i].adr));
5177 +static void dump_ints (void)
5180 + for (i = 0; int_labels[i].name; i++) {
5181 + printf ("$%02x: %s\t $%08x\n", int_labels[i].adr,
5182 + int_labels[i].name, get_long (int_labels[i].adr));
5186 +static void disassemble_wait (FILE *file, unsigned long insn)
5188 + uae_u8 vp,hp,ve,he,bfd,v_mask,h_mask;
5190 + vp = (insn & 0xff000000) >> 24;
5191 + hp = (insn & 0x00fe0000) >> 16;
5192 + ve = (insn & 0x00007f00) >> 8;
5193 + he = (insn & 0x000000fe);
5194 + bfd = insn & 0x00008000 >> 15;
5196 + /* bit15 can never be masked out*/
5197 + v_mask = vp & (ve | 0x80);
5200 + fprintf (file, "vpos ");
5202 + fprintf (file, "& 0x%02x ", ve);
5204 + fprintf (file, ">= 0x%02x", v_mask);
5208 + fprintf (file," and");
5210 + fprintf (file, " hpos ");
5212 + fprintf (file, "& 0x%02x ", he);
5214 + fprintf (file, ">= 0x%02x", h_mask);
5216 + fprintf (file, ", ignore horizontal");
5219 + fprintf (file, ".\n \t; VP %02x, VE %02x; HP %02x, HE %02x; BFD %d\n",
5220 + vp, ve, hp, he, bfd);
5223 +/* simple decode copper by Mark Cox */
5224 +static void decode_copper_insn (FILE* file, unsigned long insn, unsigned long addr)
5226 + uae_u32 insn_type = insn & 0x00010001;
5228 + char record[] = " ";
5229 + if (find_copper_record (addr, &hpos, &vpos)) {
5230 + sprintf (record, " [%03x %03x]", vpos, hpos);
5233 + fprintf (file, "%08lx: %04lx %04lx%s\t; ", addr, insn >> 16, insn & 0xFFFF, record);
5235 + switch (insn_type) {
5236 + case 0x00010000: /* WAIT insn */
5237 + fprintf (file, "Wait for ");
5238 + disassemble_wait (file, insn);
5240 + if (insn == 0xfffffffe)
5241 + fprintf (file, " \t; End of Copperlist\n");
5245 + case 0x00010001: /* SKIP insn */
5246 + fprintf (file, "Skip if ");
5247 + disassemble_wait (file, insn);
5251 + case 0x00000001: /* MOVE insn */
5252 + fprintf (file, "%s := 0x%04lx\n",
5253 + custd[(insn & 0x01fe0000) >> 17].name,
5254 + insn & 0x0000ffff);
5256 + if ((insn & 0xfe000000) != 0) {
5257 + fprintf (file, " \t;OCS Compatibility warning: bits 15-9 should be 0 for compatibility with OCS\n");
5259 + /* 01fe0000 register destination address
5260 + fe000000 should be 0 for compatibility (at least in ocs
5261 + 0000ffff data to be put in register destination */
5271 +static uaecptr decode_copperlist (FILE* file, uaecptr address, int nolines)
5274 + while (nolines-- > 0) {
5275 + insn = get_long (address);
5276 + decode_copper_insn (file, insn, address);
5280 + /* You may wonder why I don't stop this at the end of the copperlist?
5281 + * Well, often nice things are hidden at the end and it is debatable the actual
5282 + * values that mean the end of the copperlist */
5286 +/* cheat-search by Holger Jakob */
5287 +static void cheatsearch (char **c)
5289 + uae_u8 *p = get_real_address (0);
5290 + static uae_u32 *vlist = NULL;
5293 + uae_u32 type = 0; /* not yet */
5294 + uae_u32 count = 0;
5295 + uae_u32 fcount = 0;
5301 + while (isxdigit (nc = **c)) {
5304 + nc = toupper (nc);
5305 + if (isdigit (nc)) {
5309 + if (vlist == NULL) {
5310 + vlist = malloc (256*4);
5312 + for (count = 0; count<255; count++)
5315 + for (ptr = 0; ptr < allocated_chipmem - 40; ptr += 2, p += 2) {
5316 + if (ptr >= 0x438 && p[3] == (val & 0xff)
5317 + && p[2] == (val >> 8 & 0xff)
5318 + && p[1] == (val >> 16 & 0xff)
5319 + && p[0] == (val >> 24 & 0xff))
5321 + if (count < 255) {
5322 + vlist[count++]=ptr;
5323 + printf ("%08x: %x%x%x%x\n",ptr,p[0],p[1],p[2],p[3]);
5328 + printf ("Found %d possible addresses with %d\n",count,val);
5329 + printf ("Now continue with 'g' and use 'C' with a different value\n");
5332 + for (count = 0; count<255; count++) {
5333 + if (p[vlist[count]+3] == (val & 0xff)
5334 + && p[vlist[count]+2] == (val>>8 & 0xff)
5335 + && p[vlist[count]+1] == (val>>16 & 0xff)
5336 + && p[vlist[count]] == (val>>24 & 0xff))
5339 + printf ("%08x: %x%x%x%x\n", vlist[count], p[vlist[count]],
5340 + p[vlist[count]+1], p[vlist[count]+2], p[vlist[count]+3]);
5343 + printf ("%d hits of %d found\n",fcount,val);
5349 +static void writeintomem (char **c)
5351 + uae_u8 *p = get_real_address (0);
5357 + while (isxdigit(nc = **c)) {
5361 + if (isdigit(nc)) {
5364 + addr += nc - 'A' + 10;
5368 + while (isxdigit(nc = **c)) {
5372 + if (isdigit(nc)) {
5377 + if (addr < allocated_chipmem) {
5378 + p[addr] = val>>24 & 0xff;
5379 + p[addr+1] = val>>16 & 0xff;
5380 + p[addr+2] = val>>8 & 0xff;
5381 + p[addr+3] = val & 0xff;
5382 + printf ("Wrote %d at %08x\n",val,addr);
5384 + printf ("Invalid address %08x\n",addr);
5387 +static void show_exec_tasks (void)
5389 + uaecptr execbase = get_long (4);
5390 + uaecptr taskready = get_long (execbase + 406);
5391 + uaecptr taskwait = get_long (execbase + 420);
5392 + uaecptr node, end;
5393 + printf ("execbase at 0x%08lx\n", (unsigned long) execbase);
5394 + printf ("Current:\n");
5395 + node = get_long (execbase + 276);
5396 + printf ("%08lx: %08lx %s\n", node, 0, get_real_address (get_long (node + 10)));
5397 + printf ("Ready:\n");
5398 + node = get_long (taskready);
5399 + end = get_long (taskready + 4);
5401 + printf ("%08lx: %08lx %s\n", node, 0, get_real_address (get_long (node + 10)));
5402 + node = get_long (node);
5404 + printf ("Waiting:\n");
5405 + node = get_long (taskwait);
5406 + end = get_long (taskwait + 4);
5408 + printf ("%08lx: %08lx %s\n", node, 0, get_real_address (get_long (node + 10)));
5409 + node = get_long (node);
5413 +static int trace_same_insn_count;
5414 +static uae_u8 trace_insn_copy[10];
5415 +static struct regstruct trace_prev_regs;
5419 + uaecptr nextpc,nxdis,nxmem,nxcopper;
5423 + if (do_skip && skipaddr == 0xC0DEDBAD) {
5425 + if (trace_same_insn_count > 0) {
5426 + if (memcmp (trace_insn_copy, regs.pc_p, 10) == 0
5427 + && memcmp (trace_prev_regs.regs, regs.regs, sizeof regs.regs) == 0)
5429 + trace_same_insn_count++;
5433 + if (trace_same_insn_count > 1)
5434 + fprintf (logfile, "[ repeated %d times ]\n", trace_same_insn_count);
5436 + m68k_dumpstate (logfile, &nextpc);
5437 + trace_same_insn_count = 1;
5438 + memcpy (trace_insn_copy, regs.pc_p, 10);
5439 + memcpy (&trace_prev_regs, ®s, sizeof regs);
5442 + if (do_skip && (m68k_getpc() != skipaddr/* || regs.a[0] != 0x1e558*/)) {
5443 + set_special (SPCFLAG_BRK);
5448 +#ifdef NEED_TO_DEBUG_BADLY
5449 + history[lasthist] = regs;
5450 + historyf[lasthist] = regflags;
5452 + history[lasthist] = m68k_getpc();
5454 + if (++lasthist == MAX_HIST) lasthist = 0;
5455 + if (lasthist == firsthist) {
5456 + if (++firsthist == MAX_HIST) firsthist = 0;
5459 + m68k_dumpstate (stdout, &nextpc);
5460 + nxdis = nextpc; nxmem = nxcopper = 0;
5467 + if (fgets (input, 80, stdin) == 0)
5470 + cmd = next_char (&inptr);
5472 + case 'c': dumpcia (); dumpdisk (); dumpcustom (); break;
5473 + case 'i': dump_ints (); break;
5474 + case 'e': dump_traps (); break;
5475 + case 'r': m68k_dumpstate (stdout, &nextpc); break;
5476 + case 'M': modulesearch (); break;
5477 + case 'C': cheatsearch (&inptr); break;
5478 + case 'W': writeintomem (&inptr); break;
5486 + if (!more_params (&inptr))
5490 + while (*inptr != '\0' && !isspace (*inptr))
5492 + if (!isspace (*inptr))
5497 + if (!more_params (&inptr))
5499 + src = readhex (&inptr);
5500 + if (!more_params (&inptr))
5502 + len = readhex (&inptr);
5503 + if (! valid_address (src, len)) {
5504 + printf ("Invalid memory block\n");
5507 + memp = get_real_address (src);
5508 + fp = fopen (name, "w");
5510 + printf ("Couldn't open file\n");
5513 + if (fwrite (memp, 1, len, fp) != len) {
5514 + printf ("Error writing file\n");
5520 + printf ("S command needs more arguments!\n");
5528 + if (more_params(&inptr))
5529 + daddr = readhex(&inptr);
5532 + if (more_params(&inptr))
5533 + count = readhex(&inptr);
5536 + m68k_disasm (stdout, daddr, &nxdis, count);
5539 + case 'T': show_exec_tasks (); break;
5540 + case 't': set_special (SPCFLAG_BRK); return;
5542 + skipaddr = nextpc;
5544 + set_special (SPCFLAG_BRK);
5548 + skipaddr = readhex (&inptr);
5550 + set_special (SPCFLAG_BRK);
5551 + if (skipaddr == 0xC0DEDBAD) {
5552 + trace_same_insn_count = 0;
5553 + logfile = fopen ("uae.trace", "w");
5554 + memcpy (trace_insn_copy, regs.pc_p, 10);
5555 + memcpy (&trace_prev_regs, ®s, sizeof regs);
5559 + case 'q': uae_quit();
5560 + debugger_active = 0;
5565 + if (more_params (&inptr))
5566 + m68k_setpc (readhex (&inptr));
5567 + fill_prefetch_0 ();
5568 + debugger_active = 0;
5576 +#ifdef NEED_TO_DEBUG_BADLY
5577 + struct regstruct save_regs = regs;
5578 + union flagu save_flags = regflags;
5581 + if (more_params(&inptr))
5582 + count = readhex(&inptr);
5588 + while (count-- > 0 && temp != firsthist) {
5589 + if (temp == 0) temp = MAX_HIST-1; else temp--;
5591 + while (temp != lasthist) {
5592 +#ifdef NEED_TO_DEBUG_BADLY
5593 + regs = history[temp];
5594 + regflags = historyf[temp];
5595 + m68k_dumpstate (NULL);
5597 + m68k_disasm (stdout, history[temp], NULL, 1);
5599 + if (++temp == MAX_HIST) temp = 0;
5601 +#ifdef NEED_TO_DEBUG_BADLY
5603 + regflags = save_flags;
5609 + uae_u32 maddr; int lines;
5610 + if (more_params(&inptr))
5611 + maddr = readhex(&inptr);
5614 + if (more_params(&inptr))
5615 + lines = readhex(&inptr);
5618 + dumpmem(maddr, &nxmem, lines);
5626 + if (more_params(&inptr)) {
5627 + maddr = readhex(&inptr);
5628 + if (maddr == 1 || maddr == 2)
5629 + maddr = get_copper_address (maddr);
5634 + if (more_params (&inptr))
5635 + lines = readhex (&inptr);
5639 + nxcopper = decode_copperlist (stdout, maddr, lines);
5643 + if (more_params (&inptr)) {
5644 + int plane = readint (&inptr);
5645 + int offs = readint (&inptr);
5646 + if (plane >= 0 && plane < 8)
5647 + bpl_off[plane] = offs;
5650 + for (i = 0; i < 8; i++)
5651 + printf ("Plane %d offset %d\n", i, bpl_off[i]);
5655 + mmu_dump_tables();
5660 + printf (" HELP for UAE Debugger\n");
5661 + printf (" -----------------------\n\n");
5662 + printf (" g: <address> Start execution at the current address or <address>\n");
5663 + printf (" c: Dump state of the CIA and custom chips\n");
5664 + printf (" r: Dump state of the CPU\n");
5665 + printf (" m <address> <lines>: Memory dump starting at <address>\n");
5666 + printf (" d <address> <lines>: Disassembly starting at <address>\n");
5667 + printf (" t: Step one instruction\n");
5668 + printf (" z: Step through one instruction - useful for JSR, DBRA etc\n");
5669 + printf (" f <address>: Step forward until PC == <address>\n");
5670 + printf (" i: Dump contents of interrupt registers\n");
5671 + printf (" e: Dump contents of trap vectors\n");
5672 + printf (" o <1|2|addr> <lines>: View memory as Copper Instructions\n");
5673 + printf (" O: Display bitplane offsets\n");
5674 + printf (" O <plane> <offset>: Offset a bitplane\n");
5675 + printf (" H <count>: Show PC history <count> instructions\n");
5676 + printf (" M: Search for *Tracker sound modules\n");
5677 + printf (" C <value>: Search for values like energy or lifes in games\n");
5678 + printf (" W <address> <value>: Write into Amiga memory\n");
5679 + printf (" S <file> <addr> <n>: Save a block of Amiga memory\n");
5680 + printf (" T: Show exec tasks and their PCs\n");
5681 + printf (" u: Dump the MMU translation tables and state\n");
5682 + printf (" h,?: Show this help page\n");
5683 + printf (" q: Quit the emulator. You don't want to use this command.\n\n");
5689 diff -urN src-0.8.22/src/ersatz.c src-0.8.22-mmu/src/ersatz.c
5690 --- src-0.8.22/src/ersatz.c 2001-12-17 19:38:37.000000000 +0100
5691 +++ src-0.8.22-mmu/src/ersatz.c 2003-07-25 12:11:11.000000000 +0200
5692 @@ -109,55 +109,55 @@
5694 /* Set some interrupt vectors */
5695 for (a = 8; a < 0xC0; a += 4) {
5696 - put_long (a, 0xF8001A);
5697 + phys_put_long (a, 0xF8001A);
5699 regs.isp = regs.msp = regs.usp = 0x800;
5700 m68k_areg(regs, 7) = 0x80000;
5703 /* Build a dummy execbase */
5704 - put_long (4, m68k_areg(regs, 6) = 0x676);
5705 - put_byte (0x676 + 0x129, 0);
5706 + phys_put_long (4, m68k_areg(regs, 6) = 0x676);
5707 + phys_put_byte (0x676 + 0x129, 0);
5708 for (f = 1; f < 105; f++) {
5709 - put_word (0x676 - 6*f, 0x4EF9);
5710 - put_long (0x676 - 6*f + 2, 0xF8000C);
5711 + phys_put_word (0x676 - 6*f, 0x4EF9);
5712 + phys_put_long (0x676 - 6*f + 2, 0xF8000C);
5714 /* Some "supported" functions */
5715 - put_long (0x676 - 456 + 2, 0xF80014);
5716 - put_long (0x676 - 216 + 2, 0xF80020);
5717 - put_long (0x676 - 198 + 2, 0xF80026);
5718 + phys_put_long (0x676 - 456 + 2, 0xF80014);
5719 + phys_put_long (0x676 - 216 + 2, 0xF80020);
5720 + phys_put_long (0x676 - 198 + 2, 0xF80026);
5721 put_long (0x676 - 204 + 2, 0xF8002c);
5722 - put_long (0x676 - 210 + 2, 0xF8002a);
5723 + phys_put_long (0x676 - 210 + 2, 0xF8002a);
5725 /* Build an IORequest */
5727 - put_word (request + 0x1C, 2);
5728 - put_long (request + 0x28, 0x4000);
5729 - put_long (request + 0x2C, 0);
5730 - put_long (request + 0x24, 0x200 * 4);
5731 + phys_put_word (request + 0x1C, 2);
5732 + phys_put_long (request + 0x28, 0x4000);
5733 + phys_put_long (request + 0x2C, 0);
5734 + phys_put_long (request + 0x24, 0x200 * 4);
5735 m68k_areg(regs, 1) = request;
5737 /* kickstart disk loader */
5738 - if (get_long(0x4000) == 0x4b49434b) {
5739 + if (phys_get_long(0x4000) == 0x4b49434b) {
5740 /* a kickstart disk was found in drive 0! */
5741 write_log ("Loading Kickstart rom image from Kickstart disk\n");
5742 /* print some notes... */
5743 write_log ("NOTE: if UAE crashes set CPU to 68000 and/or chipmem size to 512KB!\n");
5745 /* read rom image from kickstart disk */
5746 - put_word (request + 0x1C, 2);
5747 - put_long (request + 0x28, 0xF80000);
5748 - put_long (request + 0x2C, 0x200);
5749 - put_long (request + 0x24, 0x200 * 512);
5750 + phys_put_word (request + 0x1C, 2);
5751 + phys_put_long (request + 0x28, 0xF80000);
5752 + phys_put_long (request + 0x2C, 0x200);
5753 + phys_put_long (request + 0x24, 0x200 * 512);
5754 m68k_areg(regs, 1) = request;
5757 /* read rom image once again to mirror address space.
5758 not elegant, but it works... */
5759 - put_word (request + 0x1C, 2);
5760 - put_long (request + 0x28, 0xFC0000);
5761 - put_long (request + 0x2C, 0x200);
5762 - put_long (request + 0x24, 0x200 * 512);
5763 + phys_put_word (request + 0x1C, 2);
5764 + phys_put_long (request + 0x28, 0xFC0000);
5765 + phys_put_long (request + 0x2C, 0x200);
5766 + phys_put_long (request + 0x24, 0x200 * 512);
5767 m68k_areg(regs, 1) = request;
5770 @@ -174,25 +174,25 @@
5773 /* Init the hardware */
5774 - put_long (0x3000, 0xFFFFFFFEul);
5775 - put_long (0xDFF080, 0x3000);
5776 - put_word (0xDFF088, 0);
5777 - put_word (0xDFF096, 0xE390);
5778 - put_word (0xDFF09A, 0xE02C);
5779 - put_word (0xDFF09E, 0x0000);
5780 - put_word (0xDFF092, 0x0038);
5781 - put_word (0xDFF094, 0x00D0);
5782 - put_word (0xDFF08E, 0x2C81);
5783 - put_word (0xDFF090, 0xF4C1);
5784 - put_word (0xDFF02A, 0x8000);
5786 - put_byte (0xBFD100, 0xF7);
5787 - put_byte (0xBFEE01, 0);
5788 - put_byte (0xBFEF01, 0x08);
5789 - put_byte (0xBFDE00, 0x04);
5790 - put_byte (0xBFDF00, 0x84);
5791 - put_byte (0xBFDD00, 0x9F);
5792 - put_byte (0xBFED01, 0x9F);
5793 + phys_put_long (0x3000, 0xFFFFFFFEul);
5794 + phys_put_long (0xDFF080, 0x3000);
5795 + phys_put_word (0xDFF088, 0);
5796 + phys_put_word (0xDFF096, 0xE390);
5797 + phys_put_word (0xDFF09A, 0xE02C);
5798 + phys_put_word (0xDFF09E, 0x0000);
5799 + phys_put_word (0xDFF092, 0x0038);
5800 + phys_put_word (0xDFF094, 0x00D0);
5801 + phys_put_word (0xDFF08E, 0x2C81);
5802 + phys_put_word (0xDFF090, 0xF4C1);
5803 + phys_put_word (0xDFF02A, 0x8000);
5805 + phys_put_byte (0xBFD100, 0xF7);
5806 + phys_put_byte (0xBFEE01, 0);
5807 + phys_put_byte (0xBFEF01, 0x08);
5808 + phys_put_byte (0xBFDE00, 0x04);
5809 + phys_put_byte (0xBFDF00, 0x84);
5810 + phys_put_byte (0xBFDD00, 0x9F);
5811 + phys_put_byte (0xBFED01, 0x9F);
5814 void ersatz_perform (uae_u16 what)
5818 /* Just reset all the interrupt request bits */
5819 - put_word (0xDFF09C, get_word (0xDFF01E) & 0x3FFF);
5820 + phys_put_word (0xDFF09C, phys_get_word (0xDFF01E) & 0x3FFF);
5824 diff -urN src-0.8.22/src/expansion.c src-0.8.22-mmu/src/expansion.c
5825 --- src-0.8.22/src/expansion.c 2001-12-30 16:31:03.000000000 +0100
5826 +++ src-0.8.22-mmu/src/expansion.c 2003-07-25 12:11:11.000000000 +0200
5828 #include "autoconf.h"
5829 #include "picasso96.h"
5830 #include "savestate.h"
5831 +#include "custom.h"
5832 +#include "newcpu.h"
5834 #define MAX_EXPANSION_BOARDS 8
5837 /* check if Kickstart version is below 1.3 */
5838 if (! ersatzkickfile
5839 && (/* Kickstart 1.0 & 1.1! */
5840 - get_word (0xF8000C) == 0xFFFF
5841 + phys_get_word (0xF8000C) == 0xFFFF
5842 /* Kickstart < 1.3 */
5843 - || get_word (0xF8000C) < 34))
5844 + || phys_get_word (0xF8000C) < 34))
5847 write_log ("Kickstart version is below 1.3! Disabling autoconfig devices.\n");
5848 diff -urN src-0.8.22/src/gencpu.c src-0.8.22-mmu/src/gencpu.c
5849 --- src-0.8.22/src/gencpu.c 2001-12-17 19:38:37.000000000 +0100
5850 +++ src-0.8.22-mmu/src/gencpu.c 2003-07-25 12:24:59.000000000 +0200
5852 * The source for the insn timings is Markt & Technik's Amiga Magazin 8/1992.
5854 * Copyright 1995, 1996, 1997, 1998, 1999, 2000 Bernd Schmidt
5858 #include "sysconfig.h"
5860 #include "readcpu.h"
5862 #define BOOL_TYPE "int"
5863 +#define VERIFY_MMU_GENAMODE 0
5865 static FILE *headerfile;
5866 static FILE *stblfile;
5868 static int using_prefetch;
5869 static int using_exception_3;
5870 +static int using_mmu;
5871 static int cpu_level;
5873 /* For the current opcode, the next lower level that will have different code.
5875 static int *opcode_last_postfix;
5876 static unsigned long *counts;
5879 +#define GENA_GETV_NO_FETCH 0
5880 +#define GENA_GETV_FETCH 1
5881 +#define GENA_GETV_FETCH_ALIGN 2
5882 +#define GENA_MOVEM_DO_INC 0
5883 +#define GENA_MOVEM_NO_INC 1
5884 +#define GENA_MOVEM_MOVE16 2
5886 +#define XLATE_LOG 0
5887 +#define XLATE_PHYS 1
5888 +#define XLATE_SFC 2
5889 +#define XLATE_DFC 3
5890 +static char * mem_prefix[4] = { "", "phys_", "sfc_", "dfc_" };
5892 static void read_counts (void)
5895 @@ -133,11 +150,16 @@
5899 +int nexti_no_inc = 0;
5902 static const char *gen_nextilong (void)
5904 static char buffer[80];
5905 int r = m68k_pc_offset;
5906 - m68k_pc_offset += 4;
5908 + if (!nexti_no_inc)
5909 + m68k_pc_offset += 4;
5915 static char buffer[80];
5916 int r = m68k_pc_offset;
5917 - m68k_pc_offset += 2;
5919 + if (!nexti_no_inc)
5920 + m68k_pc_offset += 2;
5924 @@ -212,14 +236,19 @@
5925 /* getv == 1: fetch data; getv != 0: check for odd address. If movem != 0,
5926 * the calling routine handles Apdi and Aipi modes.
5927 * gb-- movem == 2 means the same thing but for a MOVE16 instruction */
5928 -static void genamode (amodes mode, char *reg, wordsizes size, char *name, int getv, int movem)
5929 +static void genamode (amodes mode, char *reg, wordsizes size, char *name, int getv, int movem, int xlateflag)
5934 + xlateflag = XLATE_PHYS;
5942 + if (getv == GENA_GETV_FETCH)
5945 #if defined(AMIGA) && !defined(WARPUP)
5951 + if (getv == GENA_GETV_FETCH)
5954 printf ("\tuae_s16 %s = m68k_areg(regs, %s);\n", name, reg);
5956 printf ("\tuaecptr %sa = %s;\n", name, gen_nextilong ());
5960 + if (getv != GENA_GETV_FETCH)
5964 @@ -346,22 +375,22 @@
5969 + if (getv != GENA_GETV_FETCH)
5971 printf ("\tuae_s8 %s = %s;\n", name, gen_nextibyte ());
5975 + if (getv != GENA_GETV_FETCH)
5977 printf ("\tuae_s16 %s = %s;\n", name, gen_nextiword ());
5981 + if (getv != GENA_GETV_FETCH)
5983 printf ("\tuae_s32 %s = %s;\n", name, gen_nextilong ());
5987 + if (getv != GENA_GETV_FETCH)
5989 printf ("\tuae_u32 %s = %s;\n", name, reg);
5992 /* We get here for all non-reg non-immediate addressing modes to
5993 * actually fetch the value. */
5995 - if (using_exception_3 && getv != 0 && size != sz_byte) {
5996 + if (using_exception_3 && getv != GENA_GETV_NO_FETCH && size != sz_byte) {
5997 printf ("\tif ((%sa & 1) != 0) {\n", name);
5998 printf ("\t\tlast_fault_for_exception_3 = %sa;\n", name);
5999 printf ("\t\tlast_op_for_exception_3 = opcode;\n");
6005 + if (getv == GENA_GETV_FETCH) {
6007 case sz_byte: insn_n_cycles += 4; break;
6008 case sz_word: insn_n_cycles += 4; break;
6013 - case sz_byte: printf ("\tuae_s8 %s = get_byte(%sa);\n", name, name); break;
6014 - case sz_word: printf ("\tuae_s16 %s = get_word(%sa);\n", name, name); break;
6015 - case sz_long: printf ("\tuae_s32 %s = get_long(%sa);\n", name, name); break;
6016 + case sz_byte: printf ("\tuae_s8 %s = %sget_byte(%sa);\n", name, mem_prefix[xlateflag], name); break;
6017 + case sz_word: printf ("\tuae_s16 %s = %sget_word(%sa);\n", name, mem_prefix[xlateflag], name); break;
6018 + case sz_long: printf ("\tuae_s32 %s = %sget_long(%sa);\n", name, mem_prefix[xlateflag], name); break;
6026 -static void genastore (char *from, amodes mode, char *reg, wordsizes size, char *to)
6027 +static void genastore (char *from, amodes mode, char *reg, wordsizes size, char *to, int xlateflag)
6031 @@ -472,19 +501,19 @@
6035 - printf ("\tput_byte(%sa,%s);\n", to, from);
6036 + printf ("\t%sput_byte(%sa,%s);\n", mem_prefix[xlateflag], to, from);
6040 if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
6042 - printf ("\tput_word(%sa,%s);\n", to, from);
6043 + printf ("\t%sput_word(%sa,%s);\n", mem_prefix[xlateflag], to, from);
6047 if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
6049 - printf ("\tput_long(%sa,%s);\n", to, from);
6050 + printf ("\t%sput_long(%sa,%s);\n", mem_prefix[xlateflag], to, from);
6054 @@ -506,16 +535,20 @@
6057 int size = table68k[opcode].size == sz_long ? 4 : 2;
6058 + int xlateflag = using_mmu ? XLATE_LOG : XLATE_PHYS;
6060 if (table68k[opcode].size == sz_long) {
6061 - strcpy (getcode, "get_long(srca)");
6062 + strcpy (getcode, mem_prefix[xlateflag]);
6063 + strcat (getcode, "get_long(srca)");
6065 - strcpy (getcode, "(uae_s32)(uae_s16)get_word(srca)");
6066 + strcpy (getcode, "(uae_s32)(uae_s16)");
6067 + strcat (getcode, mem_prefix[xlateflag]);
6068 + strcat (getcode, "get_word(srca)");
6071 printf ("\tuae_u16 mask = %s;\n", gen_nextiword ());
6072 printf ("\tunsigned int dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n");
6073 - genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1);
6074 + genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_NO_INC, xlateflag);
6076 printf ("\twhile (dmask) { m68k_dreg(regs, movem_index1[dmask]) = %s; srca += %d; dmask = movem_next[dmask]; }\n",
6078 @@ -530,14 +563,19 @@
6081 int size = table68k[opcode].size == sz_long ? 4 : 2;
6082 + int noxlate = using_mmu ? XLATE_LOG : XLATE_PHYS;
6084 + strcpy(putcode, mem_prefix[noxlate]);
6086 if (table68k[opcode].size == sz_long) {
6087 - strcpy (putcode, "put_long(srca,");
6088 + strcat (putcode, "put_long(srca,");
6090 - strcpy (putcode, "put_word(srca,");
6091 + strcat (putcode, "put_word(srca,");
6094 printf ("\tuae_u16 mask = %s;\n", gen_nextiword ());
6095 - genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1);
6096 + genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src",
6097 + GENA_GETV_FETCH_ALIGN, GENA_MOVEM_NO_INC, XLATE_LOG);
6102 static void gen_opcode (unsigned long int opcode)
6104 struct instr *curi = table68k + opcode;
6105 + int xlateflag = using_mmu ? XLATE_LOG : XLATE_PHYS;
6109 @@ -859,16 +898,16 @@
6113 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6114 - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
6115 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6116 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6117 printf ("\tsrc %c= dst;\n", curi->mnemo == i_OR ? '|' : curi->mnemo == i_AND ? '&' : '^');
6118 genflags (flag_logical, curi->size, "src", "", "");
6119 - genastore ("src", curi->dmode, "dstreg", curi->size, "dst");
6120 + genastore ("src", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
6124 printf ("\tMakeSR();\n");
6125 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6126 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6127 if (curi->size == sz_byte) {
6128 printf ("\tsrc &= 0xFF;\n");
6133 printf ("\tMakeSR();\n");
6134 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6135 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6136 if (curi->size == sz_byte) {
6137 printf ("\tsrc |= 0xFF00;\n");
6139 @@ -885,31 +924,31 @@
6140 printf ("\tMakeFromSR();\n");
6143 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6144 - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
6145 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6146 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6148 genflags (flag_sub, curi->size, "newv", "src", "dst");
6149 - genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
6150 + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
6153 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6154 - genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0);
6155 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6156 + genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6158 printf ("\tuae_u32 newv = dst - src;\n");
6159 - genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
6160 + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", xlateflag);
6163 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6164 - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
6165 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6166 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6168 printf ("\tuae_u32 newv = dst - src - (GET_XFLG ? 1 : 0);\n");
6169 genflags (flag_subx, curi->size, "newv", "src", "dst");
6170 genflags (flag_zn, curi->size, "newv", "", "");
6171 - genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
6172 + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
6175 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6176 - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
6177 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6178 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6180 printf ("\tuae_u16 newv_lo = (dst & 0xF) - (src & 0xF) - (GET_XFLG ? 1 : 0);\n");
6181 printf ("\tuae_u16 newv_hi = (dst & 0xF0) - (src & 0xF0);\n");
6182 @@ -922,34 +961,34 @@
6184 genflags (flag_zn, curi->size, "newv", "", "");
6185 printf ("\tSET_VFLG ((tmp_newv & 0x80) != 0 && (newv & 0x80) == 0);\n");
6186 - genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
6187 + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
6190 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6191 - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
6192 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6193 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6195 genflags (flag_add, curi->size, "newv", "src", "dst");
6196 - genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
6197 + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
6200 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6201 - genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0);
6202 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6203 + genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6205 printf ("\tuae_u32 newv = dst + src;\n");
6206 - genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
6207 + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", xlateflag);
6210 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6211 - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
6212 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6213 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6215 printf ("\tuae_u32 newv = dst + src + (GET_XFLG ? 1 : 0);\n");
6216 genflags (flag_addx, curi->size, "newv", "src", "dst");
6217 genflags (flag_zn, curi->size, "newv", "", "");
6218 - genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
6219 + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
6222 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6223 - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
6224 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6225 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6227 printf ("\tuae_u16 newv_lo = (src & 0xF) + (dst & 0xF) + (GET_XFLG ? 1 : 0);\n");
6228 printf ("\tuae_u16 newv_hi = (src & 0xF0) + (dst & 0xF0);\n");
6229 @@ -963,24 +1002,24 @@
6231 genflags (flag_zn, curi->size, "newv", "", "");
6232 printf ("\tSET_VFLG ((tmp_newv & 0x80) == 0 && (newv & 0x80) != 0);\n");
6233 - genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
6234 + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
6237 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6238 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6240 genflags (flag_sub, curi->size, "dst", "src", "0");
6241 - genastore ("dst", curi->smode, "srcreg", curi->size, "src");
6242 + genastore ("dst", curi->smode, "srcreg", curi->size, "src", xlateflag);
6245 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6246 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6248 printf ("\tuae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);\n");
6249 genflags (flag_subx, curi->size, "newv", "src", "0");
6250 genflags (flag_zn, curi->size, "newv", "", "");
6251 - genastore ("newv", curi->smode, "srcreg", curi->size, "src");
6252 + genastore ("newv", curi->smode, "srcreg", curi->size, "src", xlateflag);
6255 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6256 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6258 printf ("\tuae_u16 newv_lo = - (src & 0xF) - (GET_XFLG ? 1 : 0);\n");
6259 printf ("\tuae_u16 newv_hi = - (src & 0xF0);\n");
6260 @@ -993,27 +1032,27 @@
6261 printf ("\tSET_CFLG (cflg);\n");
6263 genflags (flag_zn, curi->size, "newv", "", "");
6264 - genastore ("newv", curi->smode, "srcreg", curi->size, "src");
6265 + genastore ("newv", curi->smode, "srcreg", curi->size, "src", xlateflag);
6268 - genamode (curi->smode, "srcreg", curi->size, "src", 2, 0);
6269 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG);
6270 genflags (flag_logical, curi->size, "0", "", "");
6271 - genastore ("0", curi->smode, "srcreg", curi->size, "src");
6272 + genastore ("0", curi->smode, "srcreg", curi->size, "src", xlateflag);
6275 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6276 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6278 printf ("\tuae_u32 dst = ~src;\n");
6279 genflags (flag_logical, curi->size, "dst", "", "");
6280 - genastore ("dst", curi->smode, "srcreg", curi->size, "src");
6281 + genastore ("dst", curi->smode, "srcreg", curi->size, "src", xlateflag);
6284 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6285 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6286 genflags (flag_logical, curi->size, "src", "", "");
6289 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6290 - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
6291 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6292 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6293 if (curi->size == sz_byte)
6294 printf ("\tsrc &= 7;\n");
6296 @@ -1021,55 +1060,55 @@
6297 printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n");
6300 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6301 - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
6302 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6303 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6304 if (curi->size == sz_byte)
6305 printf ("\tsrc &= 7;\n");
6307 printf ("\tsrc &= 31;\n");
6308 printf ("\tdst ^= (1 << src);\n");
6309 printf ("\tSET_ZFLG (((uae_u32)dst & (1 << src)) >> src);\n");
6310 - genastore ("dst", curi->dmode, "dstreg", curi->size, "dst");
6311 + genastore ("dst", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
6314 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6315 - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
6316 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6317 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6318 if (curi->size == sz_byte)
6319 printf ("\tsrc &= 7;\n");
6321 printf ("\tsrc &= 31;\n");
6322 printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n");
6323 printf ("\tdst &= ~(1 << src);\n");
6324 - genastore ("dst", curi->dmode, "dstreg", curi->size, "dst");
6325 + genastore ("dst", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
6328 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6329 - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
6330 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6331 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6332 if (curi->size == sz_byte)
6333 printf ("\tsrc &= 7;\n");
6335 printf ("\tsrc &= 31;\n");
6336 printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n");
6337 printf ("\tdst |= (1 << src);\n");
6338 - genastore ("dst", curi->dmode, "dstreg", curi->size, "dst");
6339 + genastore ("dst", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
6343 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6344 - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
6345 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6346 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6348 genflags (flag_cmp, curi->size, "newv", "src", "dst");
6351 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6352 - genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0);
6353 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6354 + genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6356 genflags (flag_cmp, sz_long, "newv", "src", "dst");
6358 /* The next two are coded a little unconventional, but they are doing
6359 * weird things... */
6361 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6362 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6364 printf ("\tuaecptr memp = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword ());
6365 if (curi->size == sz_word) {
6366 @@ -1081,41 +1120,41 @@
6369 printf ("\tuaecptr memp = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword ());
6370 - genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
6371 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG);
6372 if (curi->size == sz_word) {
6373 printf ("\tuae_u16 val = (get_byte(memp) << 8) + get_byte(memp + 2);\n");
6375 printf ("\tuae_u32 val = (get_byte(memp) << 24) + (get_byte(memp + 2) << 16)\n");
6376 printf (" + (get_byte(memp + 4) << 8) + get_byte(memp + 6);\n");
6378 - genastore ("val", curi->dmode, "dstreg", curi->size, "dst");
6379 + genastore ("val", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
6382 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6383 - genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
6384 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6385 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG);
6386 genflags (flag_logical, curi->size, "src", "", "");
6387 - genastore ("src", curi->dmode, "dstreg", curi->size, "dst");
6388 + genastore ("src", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
6391 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6392 - genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
6393 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6394 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG);
6395 if (curi->size == sz_word) {
6396 printf ("\tuae_u32 val = (uae_s32)(uae_s16)src;\n");
6398 printf ("\tuae_u32 val = src;\n");
6400 - genastore ("val", curi->dmode, "dstreg", sz_long, "dst");
6401 + genastore ("val", curi->dmode, "dstreg", sz_long, "dst", xlateflag);
6404 - genamode (curi->smode, "srcreg", sz_word, "src", 2, 0);
6405 + genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG);
6406 printf ("\tMakeSR();\n");
6407 if (curi->size == sz_byte)
6408 - genastore ("regs.sr & 0xff", curi->smode, "srcreg", sz_word, "src");
6409 + genastore ("regs.sr & 0xff", curi->smode, "srcreg", sz_word, "src", xlateflag);
6411 - genastore ("regs.sr", curi->smode, "srcreg", sz_word, "src");
6412 + genastore ("regs.sr", curi->smode, "srcreg", sz_word, "src", xlateflag);
6415 - genamode (curi->smode, "srcreg", sz_word, "src", 1, 0);
6416 + genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6417 if (curi->size == sz_byte)
6418 printf ("\tMakeSR();\n\tregs.sr &= 0xFF00;\n\tregs.sr |= src & 0xFF;\n");
6420 @@ -1124,20 +1163,20 @@
6421 printf ("\tMakeFromSR();\n");
6424 - genamode (curi->smode, "srcreg", sz_long, "src", 1, 0);
6425 + genamode (curi->smode, "srcreg", sz_long, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6427 printf ("\tuae_u32 dst = ((src >> 16)&0xFFFF) | ((src&0xFFFF)<<16);\n");
6428 genflags (flag_logical, sz_long, "dst", "", "");
6429 - genastore ("dst", curi->smode, "srcreg", sz_long, "src");
6430 + genastore ("dst", curi->smode, "srcreg", sz_long, "src", xlateflag);
6433 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6434 - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
6435 - genastore ("dst", curi->smode, "srcreg", curi->size, "src");
6436 - genastore ("src", curi->dmode, "dstreg", curi->size, "dst");
6437 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6438 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6439 + genastore ("dst", curi->smode, "srcreg", curi->size, "src", xlateflag);
6440 + genastore ("src", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
6443 - genamode (curi->smode, "srcreg", sz_long, "src", 1, 0);
6444 + genamode (curi->smode, "srcreg", sz_long, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6446 switch (curi->size) {
6447 case sz_byte: printf ("\tuae_u32 dst = (uae_s32)(uae_s8)src;\n"); break;
6448 @@ -1148,7 +1187,7 @@
6449 genflags (flag_logical,
6450 curi->size == sz_word ? sz_word : sz_long, "dst", "", "");
6451 genastore ("dst", curi->smode, "srcreg",
6452 - curi->size == sz_word ? sz_word : sz_long, "src");
6453 + curi->size == sz_word ? sz_word : sz_long, "src", xlateflag);
6456 genmovemel (opcode);
6457 @@ -1157,18 +1196,18 @@
6458 genmovemle (opcode);
6461 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6462 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6464 printf ("\tException(src+32,0);\n");
6468 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6469 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6470 printf ("\tregs.usp = src;\n");
6473 - genamode (curi->smode, "srcreg", curi->size, "src", 2, 0);
6474 - genastore ("regs.usp", curi->smode, "srcreg", curi->size, "src");
6475 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG);
6476 + genastore ("regs.usp", curi->smode, "srcreg", curi->size, "src", xlateflag);
6479 printf ("\tcustomreset();\n");
6480 @@ -1176,15 +1215,15 @@
6484 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6485 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6486 printf ("\tregs.sr = src;\n");
6487 printf ("\tMakeFromSR();\n");
6488 printf ("\tm68k_setstopped(1);\n");
6491 if (cpu_level == 0) {
6492 - genamode (Aipi, "7", sz_word, "sr", 1, 0);
6493 - genamode (Aipi, "7", sz_long, "pc", 1, 0);
6494 + genamode (Aipi, "7", sz_word, "sr", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6495 + genamode (Aipi, "7", sz_long, "pc", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6496 printf ("\tregs.sr = sr; m68k_setpc_rte(pc);\n");
6498 printf ("\tMakeFromSR();\n");
6499 @@ -1193,13 +1232,14 @@
6500 if (next_cpu_level < 0)
6502 printf ("\tuae_u16 newsr; uae_u32 newpc; for (;;) {\n");
6503 - genamode (Aipi, "7", sz_word, "sr", 1, 0);
6504 - genamode (Aipi, "7", sz_long, "pc", 1, 0);
6505 - genamode (Aipi, "7", sz_word, "format", 1, 0);
6506 + genamode (Aipi, "7", sz_word, "sr", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6507 + genamode (Aipi, "7", sz_long, "pc", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6508 + genamode (Aipi, "7", sz_word, "format", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6509 printf ("\tnewsr = sr; newpc = pc;\n");
6510 printf ("\tif ((format & 0xF000) == 0x0000) { break; }\n");
6511 printf ("\telse if ((format & 0xF000) == 0x1000) { ; }\n");
6512 printf ("\telse if ((format & 0xF000) == 0x2000) { m68k_areg(regs, 7) += 4; break; }\n");
6513 + printf ("\telse if ((format & 0xF000) == 0x7000) { in_exception_2--; write_log(\"RTE: 2\\n\"); m68k_areg(regs, 7) += 60; break; }\n");
6514 printf ("\telse if ((format & 0xF000) == 0x8000) { m68k_areg(regs, 7) += 50; break; }\n");
6515 printf ("\telse if ((format & 0xF000) == 0x9000) { m68k_areg(regs, 7) += 12; break; }\n");
6516 printf ("\telse if ((format & 0xF000) == 0xa000) { m68k_areg(regs, 7) += 24; break; }\n");
6517 @@ -1217,8 +1257,8 @@
6520 printf ("\tcompiler_flush_jsr_stack();\n");
6521 - genamode (Aipi, "7", sz_long, "pc", 1, 0);
6522 - genamode (curi->smode, "srcreg", curi->size, "offs", 1, 0);
6523 + genamode (Aipi, "7", sz_long, "pc", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6524 + genamode (curi->smode, "srcreg", curi->size, "offs", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6525 printf ("\tm68k_areg(regs, 7) += offs;\n");
6526 printf ("\tm68k_setpc_rte(pc);\n");
6528 @@ -1226,18 +1266,18 @@
6532 - genamode (Apdi, "7", sz_long, "old", 2, 0);
6533 - genamode (curi->smode, "srcreg", sz_long, "src", 1, 0);
6534 - genastore ("src", Apdi, "7", sz_long, "old");
6535 - genastore ("m68k_areg(regs, 7)", curi->smode, "srcreg", sz_long, "src");
6536 - genamode (curi->dmode, "dstreg", curi->size, "offs", 1, 0);
6537 + genamode (Apdi, "7", sz_long, "old", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG);
6538 + genamode (curi->smode, "srcreg", sz_long, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6539 + genastore ("src", Apdi, "7", sz_long, "old", xlateflag);
6540 + genastore ("m68k_areg(regs, 7)", curi->smode, "srcreg", sz_long, "src", xlateflag);
6541 + genamode (curi->dmode, "dstreg", curi->size, "offs", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6542 printf ("\tm68k_areg(regs, 7) += offs;\n");
6545 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6546 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6547 printf ("\tm68k_areg(regs, 7) = src;\n");
6548 - genamode (Aipi, "7", sz_long, "old", 1, 0);
6549 - genastore ("old", curi->smode, "srcreg", curi->size, "src");
6550 + genamode (Aipi, "7", sz_long, "old", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6551 + genastore ("old", curi->smode, "srcreg", curi->size, "src", xlateflag);
6554 printf ("\tm68k_do_rts();\n");
6555 @@ -1252,8 +1292,8 @@
6557 printf ("\tcompiler_flush_jsr_stack();\n");
6558 printf ("\tMakeSR();\n");
6559 - genamode (Aipi, "7", sz_word, "sr", 1, 0);
6560 - genamode (Aipi, "7", sz_long, "pc", 1, 0);
6561 + genamode (Aipi, "7", sz_word, "sr", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6562 + genamode (Aipi, "7", sz_long, "pc", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6563 printf ("\tregs.sr &= 0xFF00; sr &= 0xFF;\n");
6564 printf ("\tregs.sr |= sr; m68k_setpc(pc);\n");
6566 @@ -1261,19 +1301,19 @@
6570 - genamode (curi->smode, "srcreg", curi->size, "src", 0, 0);
6571 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_NO_FETCH, GENA_MOVEM_DO_INC, XLATE_PHYS);
6572 printf ("\tm68k_do_jsr(m68k_getpc() + %d, srca);\n", m68k_pc_offset);
6577 - genamode (curi->smode, "srcreg", curi->size, "src", 0, 0);
6578 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_NO_FETCH, GENA_MOVEM_DO_INC, XLATE_PHYS);
6579 printf ("\tm68k_setpc(srca);\n");
6584 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6585 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_PHYS);
6586 printf ("\tuae_s32 s = (uae_s32)src + 2;\n");
6587 if (using_exception_3) {
6588 printf ("\tif (src & 1) {\n");
6589 @@ -1301,7 +1341,7 @@
6593 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6594 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_PHYS);
6595 printf ("\tif (!cctrue(%d)) goto didnt_jump;\n", curi->cc);
6596 if (using_exception_3) {
6597 printf ("\tif (src & 1) {\n");
6598 @@ -1323,21 +1363,21 @@
6599 insn_n_cycles = curi->size == sz_byte ? 8 : 12;
6602 - genamode (curi->smode, "srcreg", curi->size, "src", 0, 0);
6603 - genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
6604 - genastore ("srca", curi->dmode, "dstreg", curi->size, "dst");
6605 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_NO_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6606 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG);
6607 + genastore ("srca", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
6610 - genamode (curi->smode, "srcreg", curi->size, "src", 0, 0);
6611 - genamode (Apdi, "7", sz_long, "dst", 2, 0);
6612 - genastore ("srca", Apdi, "7", sz_long, "dst");
6613 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_NO_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6614 + genamode (Apdi, "7", sz_long, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG);
6615 + genastore ("srca", Apdi, "7", sz_long, "dst", xlateflag);
6618 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6619 - genamode (curi->dmode, "dstreg", curi->size, "offs", 1, 0);
6620 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6621 + genamode (curi->dmode, "dstreg", curi->size, "offs", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6623 printf ("\tif (!cctrue(%d)) {\n", curi->cc);
6624 - genastore ("(src-1)", curi->smode, "srcreg", curi->size, "src");
6625 + genastore ("(src-1)", curi->smode, "srcreg", curi->size, "src", xlateflag);
6627 printf ("\t\tif (src) {\n");
6628 if (using_exception_3) {
6629 @@ -1362,15 +1402,15 @@
6633 - genamode (curi->smode, "srcreg", curi->size, "src", 2, 0);
6634 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG);
6636 printf ("\tint val = cctrue(%d) ? 0xff : 0;\n", curi->cc);
6637 - genastore ("val", curi->smode, "srcreg", curi->size, "src");
6638 + genastore ("val", curi->smode, "srcreg", curi->size, "src", xlateflag);
6641 printf ("\tuaecptr oldpc = m68k_getpc();\n");
6642 - genamode (curi->smode, "srcreg", sz_word, "src", 1, 0);
6643 - genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0);
6644 + genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6645 + genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6647 /* Clear V flag when dividing by zero - Alcatraz Odyssey demo depends
6648 * on this (actually, it's doing a DIVS). */
6649 @@ -1382,7 +1422,7 @@
6650 printf ("\tif (newv > 0xffff) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else\n\t{\n");
6651 genflags (flag_logical, sz_word, "newv", "", "");
6652 printf ("\tnewv = (newv & 0xffff) | ((uae_u32)rem << 16);\n");
6653 - genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
6654 + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", xlateflag);
6657 insn_n_cycles += 136;
6658 @@ -1390,8 +1430,8 @@
6661 printf ("\tuaecptr oldpc = m68k_getpc();\n");
6662 - genamode (curi->smode, "srcreg", sz_word, "src", 1, 0);
6663 - genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0);
6664 + genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6665 + genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6667 printf ("\tif (src == 0) { SET_VFLG (0); Exception(5,oldpc); goto %s; } else {\n", endlabelstr);
6668 printf ("\tuae_s32 newv = (uae_s32)dst / (uae_s32)(uae_s16)src;\n");
6669 @@ -1400,34 +1440,34 @@
6670 printf ("\tif (((uae_s16)rem < 0) != ((uae_s32)dst < 0)) rem = -rem;\n");
6671 genflags (flag_logical, sz_word, "newv", "", "");
6672 printf ("\tnewv = (newv & 0xffff) | ((uae_u32)rem << 16);\n");
6673 - genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
6674 + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", xlateflag);
6677 insn_n_cycles += 154;
6681 - genamode (curi->smode, "srcreg", sz_word, "src", 1, 0);
6682 - genamode (curi->dmode, "dstreg", sz_word, "dst", 1, 0);
6683 + genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6684 + genamode (curi->dmode, "dstreg", sz_word, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6686 printf ("\tuae_u32 newv = (uae_u32)(uae_u16)dst * (uae_u32)(uae_u16)src;\n");
6687 genflags (flag_logical, sz_long, "newv", "", "");
6688 - genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
6689 + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", xlateflag);
6690 insn_n_cycles += 66;
6693 - genamode (curi->smode, "srcreg", sz_word, "src", 1, 0);
6694 - genamode (curi->dmode, "dstreg", sz_word, "dst", 1, 0);
6695 + genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6696 + genamode (curi->dmode, "dstreg", sz_word, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6698 printf ("\tuae_u32 newv = (uae_s32)(uae_s16)dst * (uae_s32)(uae_s16)src;\n");
6699 genflags (flag_logical, sz_long, "newv", "", "");
6700 - genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
6701 + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", xlateflag);
6702 insn_n_cycles += 66;
6705 printf ("\tuaecptr oldpc = m68k_getpc();\n");
6706 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6707 - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
6708 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6709 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6710 printf ("\tif ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc); goto %s; }\n", endlabelstr);
6711 printf ("\telse if (dst > src) { SET_NFLG (0); Exception(6,oldpc); goto %s; }\n", endlabelstr);
6713 @@ -1435,8 +1475,8 @@
6716 printf ("\tuaecptr oldpc = m68k_getpc();\n");
6717 - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
6718 - genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
6719 + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6720 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG);
6721 printf ("\t{uae_s32 upper,lower,reg = regs.regs[(extra >> 12) & 15];\n");
6722 switch (curi->size) {
6724 @@ -1460,8 +1500,8 @@
6728 - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
6729 - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
6730 + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6731 + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6733 switch (curi->size) {
6734 case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
6735 @@ -1490,11 +1530,11 @@
6736 printf ("\t\tval &= %s;\n", bit_mask (curi->size));
6738 genflags (flag_logical_noclobber, curi->size, "val", "", "");
6739 - genastore ("val", curi->dmode, "dstreg", curi->size, "data");
6740 + genastore ("val", curi->dmode, "dstreg", curi->size, "data", xlateflag);
6743 - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
6744 - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
6745 + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6746 + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6748 switch (curi->size) {
6749 case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
6750 @@ -1526,11 +1566,11 @@
6751 printf ("\t\tval &= %s;\n", bit_mask (curi->size));
6753 genflags (flag_logical_noclobber, curi->size, "val", "", "");
6754 - genastore ("val", curi->dmode, "dstreg", curi->size, "data");
6755 + genastore ("val", curi->dmode, "dstreg", curi->size, "data", xlateflag);
6758 - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
6759 - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
6760 + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6761 + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6763 switch (curi->size) {
6764 case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
6765 @@ -1555,11 +1595,11 @@
6766 printf ("\t\tval >>= 1;\n");
6768 genflags (flag_logical_noclobber, curi->size, "val", "", "");
6769 - genastore ("val", curi->dmode, "dstreg", curi->size, "data");
6770 + genastore ("val", curi->dmode, "dstreg", curi->size, "data", xlateflag);
6773 - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
6774 - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
6775 + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6776 + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6778 switch (curi->size) {
6779 case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
6780 @@ -1585,11 +1625,11 @@
6781 printf ("\tval &= %s;\n", bit_mask (curi->size));
6783 genflags (flag_logical_noclobber, curi->size, "val", "", "");
6784 - genastore ("val", curi->dmode, "dstreg", curi->size, "data");
6785 + genastore ("val", curi->dmode, "dstreg", curi->size, "data", xlateflag);
6788 - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
6789 - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
6790 + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6791 + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6793 switch (curi->size) {
6794 case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
6795 @@ -1612,11 +1652,11 @@
6796 printf ("\tSET_CFLG (val & 1);\n");
6798 genflags (flag_logical_noclobber, curi->size, "val", "", "");
6799 - genastore ("val", curi->dmode, "dstreg", curi->size, "data");
6800 + genastore ("val", curi->dmode, "dstreg", curi->size, "data", xlateflag);
6803 - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
6804 - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
6805 + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6806 + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6808 switch (curi->size) {
6809 case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
6810 @@ -1639,11 +1679,11 @@
6811 printf ("\tSET_CFLG ((val & %s) >> %d);\n", cmask (curi->size), bit_size (curi->size) - 1);
6813 genflags (flag_logical_noclobber, curi->size, "val", "", "");
6814 - genastore ("val", curi->dmode, "dstreg", curi->size, "data");
6815 + genastore ("val", curi->dmode, "dstreg", curi->size, "data", xlateflag);
6818 - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
6819 - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
6820 + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6821 + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6823 switch (curi->size) {
6824 case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
6825 @@ -1669,11 +1709,11 @@
6827 printf ("\tSET_CFLG (GET_XFLG);\n");
6828 genflags (flag_logical_noclobber, curi->size, "val", "", "");
6829 - genastore ("val", curi->dmode, "dstreg", curi->size, "data");
6830 + genastore ("val", curi->dmode, "dstreg", curi->size, "data", xlateflag);
6833 - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
6834 - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
6835 + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6836 + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6838 switch (curi->size) {
6839 case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
6840 @@ -1702,10 +1742,10 @@
6842 printf ("\tSET_CFLG (GET_XFLG);\n");
6843 genflags (flag_logical_noclobber, curi->size, "val", "", "");
6844 - genastore ("val", curi->dmode, "dstreg", curi->size, "data");
6845 + genastore ("val", curi->dmode, "dstreg", curi->size, "data", xlateflag);
6848 - genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
6849 + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6851 switch (curi->size) {
6852 case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
6853 @@ -1719,10 +1759,10 @@
6854 genflags (flag_logical, curi->size, "val", "", "");
6855 printf ("\tSET_CFLG (cflg);\n");
6857 - genastore ("val", curi->smode, "srcreg", curi->size, "data");
6858 + genastore ("val", curi->smode, "srcreg", curi->size, "data", xlateflag);
6861 - genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
6862 + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6864 switch (curi->size) {
6865 case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
6866 @@ -1739,10 +1779,10 @@
6869 printf ("\tSET_VFLG (GET_VFLG | (sign2 != sign));\n");
6870 - genastore ("val", curi->smode, "srcreg", curi->size, "data");
6871 + genastore ("val", curi->smode, "srcreg", curi->size, "data", xlateflag);
6874 - genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
6875 + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6877 switch (curi->size) {
6878 case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
6879 @@ -1755,10 +1795,10 @@
6880 genflags (flag_logical, curi->size, "val", "", "");
6881 printf ("SET_CFLG (carry);\n");
6883 - genastore ("val", curi->smode, "srcreg", curi->size, "data");
6884 + genastore ("val", curi->smode, "srcreg", curi->size, "data", xlateflag);
6887 - genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
6888 + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6890 switch (curi->size) {
6891 case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
6892 @@ -1771,10 +1811,10 @@
6893 genflags (flag_logical, curi->size, "val", "", "");
6894 printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1);
6896 - genastore ("val", curi->smode, "srcreg", curi->size, "data");
6897 + genastore ("val", curi->smode, "srcreg", curi->size, "data", xlateflag);
6900 - genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
6901 + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6903 switch (curi->size) {
6904 case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
6905 @@ -1787,10 +1827,10 @@
6906 printf ("\tif (carry) val |= 1;\n");
6907 genflags (flag_logical, curi->size, "val", "", "");
6908 printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1);
6909 - genastore ("val", curi->smode, "srcreg", curi->size, "data");
6910 + genastore ("val", curi->smode, "srcreg", curi->size, "data", xlateflag);
6913 - genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
6914 + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6916 switch (curi->size) {
6917 case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
6918 @@ -1803,10 +1843,10 @@
6919 printf ("\tif (carry) val |= %s;\n", cmask (curi->size));
6920 genflags (flag_logical, curi->size, "val", "", "");
6921 printf ("SET_CFLG (carry);\n");
6922 - genastore ("val", curi->smode, "srcreg", curi->size, "data");
6923 + genastore ("val", curi->smode, "srcreg", curi->size, "data", xlateflag);
6926 - genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
6927 + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6929 switch (curi->size) {
6930 case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
6931 @@ -1820,10 +1860,10 @@
6932 genflags (flag_logical, curi->size, "val", "", "");
6933 printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1);
6935 - genastore ("val", curi->smode, "srcreg", curi->size, "data");
6936 + genastore ("val", curi->smode, "srcreg", curi->size, "data", xlateflag);
6939 - genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
6940 + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6942 switch (curi->size) {
6943 case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
6944 @@ -1837,17 +1877,17 @@
6945 genflags (flag_logical, curi->size, "val", "", "");
6946 printf ("SET_CFLG (carry);\n");
6948 - genastore ("val", curi->smode, "srcreg", curi->size, "data");
6949 + genastore ("val", curi->smode, "srcreg", curi->size, "data", xlateflag);
6952 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6953 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6955 printf ("\tint regno = (src >> 12) & 15;\n");
6956 printf ("\tuae_u32 *regp = regs.regs + regno;\n");
6957 printf ("\tif (! m68k_movec2(src & 0xFFF, regp)) goto %s;\n", endlabelstr);
6960 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6961 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6963 printf ("\tint regno = (src >> 12) & 15;\n");
6964 printf ("\tuae_u32 *regp = regs.regs + regno;\n");
6965 @@ -1856,8 +1896,8 @@
6968 int old_brace_level;
6969 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
6970 - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
6971 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6972 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6974 printf ("\tint ru = (src >> 6) & 7;\n");
6975 printf ("\tint rc = src & 7;\n");
6976 @@ -1865,7 +1905,7 @@
6977 printf ("\tif (GET_ZFLG)");
6978 old_brace_level = n_braces;
6980 - genastore ("(m68k_dreg(regs, ru))", curi->dmode, "dstreg", curi->size, "dst");
6981 + genastore ("(m68k_dreg(regs, ru))", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
6982 pop_braces (old_brace_level);
6985 @@ -1874,7 +1914,7 @@
6989 - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
6990 + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
6991 printf ("\tuae_u32 rn1 = regs.regs[(extra >> 28) & 15];\n");
6992 printf ("\tuae_u32 rn2 = regs.regs[(extra >> 12) & 15];\n");
6993 if (curi->size == sz_word) {
6994 @@ -1909,31 +1949,41 @@
6998 - case i_MOVES: /* ignore DFC and SFC because we have no MMU */
7001 - int old_brace_level;
7002 - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
7003 - printf ("\tif (extra & 0x800)\n");
7004 - old_brace_level = n_braces;
7006 - printf ("\tuae_u32 src = regs.regs[(extra >> 12) & 15];\n");
7007 - genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
7008 - genastore ("src", curi->dmode, "dstreg", curi->size, "dst");
7009 - pop_braces (old_brace_level);
7012 - genamode (curi->dmode, "dstreg", curi->size, "src", 1, 0);
7013 - printf ("\tif (extra & 0x8000) {\n");
7014 - switch (curi->size) {
7015 - case sz_byte: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = (uae_s32)(uae_s8)src;\n"); break;
7016 - case sz_word: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = (uae_s32)(uae_s16)src;\n"); break;
7017 - case sz_long: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = src;\n"); break;
7018 - default: abort ();
7019 + int old_brace_level;
7021 + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
7023 + printf ("\tif (extra & 0x0800)\n"); /* from reg to ea */
7026 + old_brace_level = n_braces;
7028 + printf ("\tuae_u32 src = regs.regs[(extra >> 12) & 15];\n");
7029 + nexti_no_inc = 1; /* prevent strange problems with misaligned insns */
7030 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_DFC);
7032 + genastore ("src", curi->dmode, "dstreg", curi->size, "dst", XLATE_DFC);
7033 + pop_braces (old_brace_level);
7035 + printf ("else"); /* from ea to reg */
7039 + genamode (curi->dmode, "dstreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_SFC);
7040 + printf ("\tif (extra & 0x8000) {\n"); /* address/data */
7041 + switch (curi->size) {
7042 + case sz_byte: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = (uae_s32)(uae_s8)src;\n"); break;
7043 + case sz_word: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = (uae_s32)(uae_s16)src;\n"); break;
7044 + case sz_long: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = src;\n"); break;
7045 + default: abort ();
7047 + printf ("\t} else {\n");
7048 + genastore ("src", Dreg, "(extra >> 12) & 7", curi->size, "", XLATE_LOG);
7050 + pop_braces (old_brace_level);
7052 - printf ("\t} else {\n");
7053 - genastore ("src", Dreg, "(extra >> 12) & 7", curi->size, "");
7055 - pop_braces (old_brace_level);
7058 case i_BKPT: /* only needed for hardware emulators */
7059 @@ -1950,7 +2000,7 @@
7062 if (curi->smode != am_unknown && curi->smode != am_illg)
7063 - genamode (curi->smode, "srcreg", curi->size, "dummy", 1, 0);
7064 + genamode (curi->smode, "srcreg", curi->size, "dummy", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
7065 printf ("\tif (cctrue(%d)) { Exception(7,m68k_getpc()); goto %s; }\n", curi->cc, endlabelstr);
7068 @@ -1958,14 +2008,14 @@
7071 printf ("\tuaecptr oldpc = m68k_getpc();\n");
7072 - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
7073 - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
7074 + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
7075 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
7077 printf ("\tm68k_divl(opcode, dst, extra, oldpc);\n");
7080 - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
7081 - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
7082 + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
7083 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
7085 printf ("\tm68k_mull(opcode, dst, extra);\n");
7087 @@ -1977,8 +2027,8 @@
7091 - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
7092 - genamode (curi->dmode, "dstreg", sz_long, "dst", 2, 0);
7093 + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
7094 + genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG);
7096 printf ("\tuae_s32 offset = extra & 0x800 ? m68k_dreg(regs, (extra >> 6) & 7) : (extra >> 6) & 0x1f;\n");
7097 printf ("\tint width = (((extra & 0x20 ? m68k_dreg(regs, extra & 7) : extra) -1) & 0x1f) +1;\n");
7098 @@ -2082,23 +2132,23 @@
7102 - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
7103 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
7104 genflags (flag_logical, curi->size, "src", "", "");
7105 printf ("\tsrc |= 0x80;\n");
7106 - genastore ("src", curi->smode, "srcreg", curi->size, "src");
7107 + genastore ("src", curi->smode, "srcreg", curi->size, "src", xlateflag);
7110 - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
7111 + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
7113 printf ("\tfpp_opp(opcode,extra);\n");
7116 - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
7117 + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
7119 printf ("\tfdbcc_opp(opcode,extra);\n");
7122 - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
7123 + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
7125 printf ("\tfscc_opp(opcode,extra);\n");
7127 @@ -2107,7 +2157,7 @@
7129 printf ("\tuaecptr oldpc = m68k_getpc();\n");
7130 if (curi->smode != am_unknown && curi->smode != am_illg)
7131 - genamode (curi->smode, "srcreg", curi->size, "dummy", 1, 0);
7132 + genamode (curi->smode, "srcreg", curi->size, "dummy", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
7134 printf ("\tftrapcc_opp(opcode,oldpc);\n");
7136 @@ -2115,7 +2165,7 @@
7139 printf ("\tuaecptr pc = m68k_getpc();\n");
7140 - genamode (curi->dmode, "srcreg", curi->size, "extra", 1, 0);
7141 + genamode (curi->dmode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
7143 printf ("\tfbcc_opp(opcode,pc,extra);\n");
7145 @@ -2150,8 +2200,8 @@
7146 printf ("\tm68k_areg(regs, dstreg) += 16;\n");
7148 /* Other variants */
7149 - genamode (curi->smode, "srcreg", curi->size, "mems", 0, 2);
7150 - genamode (curi->dmode, "dstreg", curi->size, "memd", 0, 2);
7151 + genamode (curi->smode, "srcreg", curi->size, "mems", GENA_GETV_NO_FETCH, GENA_MOVEM_MOVE16, XLATE_LOG);
7152 + genamode (curi->dmode, "dstreg", curi->size, "memd", GENA_GETV_NO_FETCH, GENA_MOVEM_MOVE16, XLATE_LOG);
7153 printf ("\tmemsa &= ~15;\n");
7154 printf ("\tmemda &= ~15;\n");
7155 printf ("\tput_long(memda, get_long(memsa));\n");
7156 @@ -2166,7 +2216,7 @@
7160 - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
7161 + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
7163 printf ("\tmmu_op(opcode,extra);\n");
7165 @@ -2310,8 +2360,11 @@
7168 using_exception_3 = 0;
7171 for (i = 0; i < 6; i++) {
7173 + using_mmu = cpu_level == 4;
7177 diff -urN src-0.8.22/src/gencpu.c~ src-0.8.22-mmu/src/gencpu.c~
7178 --- src-0.8.22/src/gencpu.c~ 1970-01-01 01:00:00.000000000 +0100
7179 +++ src-0.8.22-mmu/src/gencpu.c~ 2003-07-25 12:11:11.000000000 +0200
7182 + * UAE - The Un*x Amiga Emulator
7184 + * MC68000 emulation generator
7186 + * This is a fairly stupid program that generates a lot of case labels that
7187 + * can be #included in a switch statement.
7188 + * As an alternative, it can generate functions that handle specific
7189 + * MC68000 instructions, plus a prototype header file and a function pointer
7190 + * array to look up the function for an opcode.
7191 + * Error checking is bad, an illegal table68k file will cause the program to
7193 + * The generated code is sometimes sub-optimal, an optimizing compiler should
7194 + * take care of this.
7196 + * The source for the insn timings is Markt & Technik's Amiga Magazin 8/1992.
7198 + * Copyright 1995, 1996, 1997, 1998, 1999, 2000 Bernd Schmidt
7202 +#include "sysconfig.h"
7203 +#include "sysdeps.h"
7206 +#include "readcpu.h"
7208 +#define BOOL_TYPE "int"
7209 +#define VERIFY_MMU_GENAMODE 0
7211 +static FILE *headerfile;
7212 +static FILE *stblfile;
7214 +static int using_prefetch;
7215 +static int using_exception_3;
7216 +static int using_mmu;
7217 +static int cpu_level;
7219 +/* For the current opcode, the next lower level that will have different code.
7220 + * Initialized to -1 for each opcode. If it remains unchanged, indicates we
7221 + * are done with that opcode. */
7222 +static int next_cpu_level;
7224 +static int *opcode_map;
7225 +static int *opcode_next_clev;
7226 +static int *opcode_last_postfix;
7227 +static unsigned long *counts;
7230 +#define GENA_GETV_NO_FETCH 0
7231 +#define GENA_GETV_FETCH 1
7232 +#define GENA_GETV_FETCH_ALIGN 2
7233 +#define GENA_MOVEM_DO_INC 0
7234 +#define GENA_MOVEM_NO_INC 1
7235 +#define GENA_MOVEM_MOVE16 2
7237 +#define XLATE_LOG 0
7238 +#define XLATE_PHYS 1
7239 +#define XLATE_SFC 2
7240 +#define XLATE_DFC 3
7241 +static char * mem_prefix[4] = { "", "phys_", "sfc_", "dfc_" };
7243 +static void read_counts (void)
7246 + unsigned long opcode, count, total;
7249 + memset (counts, 0, 65536 * sizeof *counts);
7251 + file = fopen ("frequent.68k", "r");
7253 + fscanf (file, "Total: %lu\n", &total);
7254 + while (fscanf (file, "%lx: %lu %s\n", &opcode, &count, name) == 3) {
7255 + opcode_next_clev[nr] = 4;
7256 + opcode_last_postfix[nr] = -1;
7257 + opcode_map[nr++] = opcode;
7258 + counts[opcode] = count;
7262 + if (nr == nr_cpuop_funcs)
7264 + for (opcode = 0; opcode < 0x10000; opcode++) {
7265 + if (table68k[opcode].handler == -1 && table68k[opcode].mnemo != i_ILLG
7266 + && counts[opcode] == 0)
7268 + opcode_next_clev[nr] = 4;
7269 + opcode_last_postfix[nr] = -1;
7270 + opcode_map[nr++] = opcode;
7271 + counts[opcode] = count;
7274 + if (nr != nr_cpuop_funcs)
7278 +static char endlabelstr[80];
7279 +static int endlabelno = 0;
7280 +static int need_endlabel;
7282 +static int n_braces = 0;
7283 +static int m68k_pc_offset = 0;
7284 +static int insn_n_cycles;
7286 +static void start_brace (void)
7292 +static void close_brace (void)
7294 + assert (n_braces > 0);
7299 +static void finish_braces (void)
7301 + while (n_braces > 0)
7305 +static void pop_braces (int to)
7307 + while (n_braces > to)
7311 +static int bit_size (int size)
7314 + case sz_byte: return 8;
7315 + case sz_word: return 16;
7316 + case sz_long: return 32;
7317 + default: abort ();
7322 +static const char *bit_mask (int size)
7325 + case sz_byte: return "0xff";
7326 + case sz_word: return "0xffff";
7327 + case sz_long: return "0xffffffff";
7328 + default: abort ();
7333 +int nexti_no_inc = 0;
7336 +static const char *gen_nextilong (void)
7338 + static char buffer[80];
7339 + int r = m68k_pc_offset;
7341 + if (!nexti_no_inc)
7342 + m68k_pc_offset += 4;
7344 + insn_n_cycles += 8;
7346 + if (using_prefetch)
7347 + sprintf (buffer, "get_ilong_prefetch(%d)", r);
7349 + sprintf (buffer, "get_ilong(%d)", r);
7353 +static const char *gen_nextiword (void)
7355 + static char buffer[80];
7356 + int r = m68k_pc_offset;
7358 + if (!nexti_no_inc)
7359 + m68k_pc_offset += 2;
7361 + insn_n_cycles += 4;
7363 + if (using_prefetch)
7364 + sprintf (buffer, "get_iword_prefetch(%d)", r);
7366 + sprintf (buffer, "get_iword(%d)", r);
7370 +static const char *gen_nextibyte (void)
7372 + static char buffer[80];
7373 + int r = m68k_pc_offset;
7374 + m68k_pc_offset += 2;
7376 + insn_n_cycles += 4;
7378 + if (using_prefetch)
7379 + sprintf (buffer, "get_ibyte_prefetch(%d)", r);
7381 + sprintf (buffer, "get_ibyte(%d)", r);
7385 +static void fill_prefetch_0 (void)
7387 + if (using_prefetch)
7388 + printf ("fill_prefetch_0 ();\n");
7391 +static void fill_prefetch_2 (void)
7393 + if (using_prefetch)
7394 + printf ("fill_prefetch_2 ();\n");
7397 +static void sync_m68k_pc (void)
7399 + if (m68k_pc_offset == 0)
7401 + printf ("m68k_incpc(%d);\n", m68k_pc_offset);
7402 + switch (m68k_pc_offset) {
7404 + /*write_log ("refilling prefetch at 0\n"); */
7407 + fill_prefetch_2 ();
7410 + fill_prefetch_0 ();
7413 + m68k_pc_offset = 0;
7416 +/* getv == 1: fetch data; getv != 0: check for odd address. If movem != 0,
7417 + * the calling routine handles Apdi and Aipi modes.
7418 + * gb-- movem == 2 means the same thing but for a MOVE16 instruction */
7419 +static void genamode (amodes mode, char *reg, wordsizes size, char *name, int getv, int movem, int xlateflag)
7424 + xlateflag = XLATE_PHYS;
7431 + if (getv == GENA_GETV_FETCH)
7434 +#if defined(AMIGA) && !defined(WARPUP)
7435 + /* sam: I don't know why gcc.2.7.2.1 produces a code worse */
7436 + /* if it is not done like that: */
7437 + printf ("\tuae_s8 %s = ((uae_u8*)&m68k_dreg(regs, %s))[3];\n", name, reg);
7439 + printf ("\tuae_s8 %s = m68k_dreg(regs, %s);\n", name, reg);
7443 +#if defined(AMIGA) && !defined(WARPUP)
7444 + printf ("\tuae_s16 %s = ((uae_s16*)&m68k_dreg(regs, %s))[1];\n", name, reg);
7446 + printf ("\tuae_s16 %s = m68k_dreg(regs, %s);\n", name, reg);
7450 + printf ("\tuae_s32 %s = m68k_dreg(regs, %s);\n", name, reg);
7459 + if (getv == GENA_GETV_FETCH)
7462 + printf ("\tuae_s16 %s = m68k_areg(regs, %s);\n", name, reg);
7465 + printf ("\tuae_s32 %s = m68k_areg(regs, %s);\n", name, reg);
7472 + printf ("\tuaecptr %sa = m68k_areg(regs, %s);\n", name, reg);
7475 + printf ("\tuaecptr %sa = m68k_areg(regs, %s);\n", name, reg);
7478 + insn_n_cycles += 2;
7482 + printf ("\tuaecptr %sa = m68k_areg(regs, %s);\n", name, reg);
7484 + printf ("\tuaecptr %sa = m68k_areg(regs, %s) - areg_byteinc[%s];\n", name, reg, reg);
7487 + printf ("\tuaecptr %sa = m68k_areg(regs, %s) - %d;\n", name, reg, movem ? 0 : 2);
7490 + printf ("\tuaecptr %sa = m68k_areg(regs, %s) - %d;\n", name, reg, movem ? 0 : 4);
7497 + printf ("\tuaecptr %sa = m68k_areg(regs, %s) + (uae_s32)(uae_s16)%s;\n", name, reg, gen_nextiword ());
7500 + insn_n_cycles += 2;
7501 + if (cpu_level > 1) {
7502 + if (next_cpu_level < 1)
7503 + next_cpu_level = 1;
7506 + /* This would ordinarily be done in gen_nextiword, which we bypass. */
7507 + insn_n_cycles += 4;
7508 + printf ("\tuaecptr %sa = get_disp_ea_020(m68k_areg(regs, %s), next_iword());\n", name, reg);
7510 + printf ("\tuaecptr %sa = get_disp_ea_000(m68k_areg(regs, %s), %s);\n", name, reg, gen_nextiword ());
7514 + printf ("\tuaecptr %sa = m68k_getpc () + %d;\n", name, m68k_pc_offset);
7515 + printf ("\t%sa += (uae_s32)(uae_s16)%s;\n", name, gen_nextiword ());
7518 + insn_n_cycles += 2;
7519 + if (cpu_level > 1) {
7520 + if (next_cpu_level < 1)
7521 + next_cpu_level = 1;
7524 + /* This would ordinarily be done in gen_nextiword, which we bypass. */
7525 + insn_n_cycles += 4;
7526 + printf ("\tuaecptr tmppc = m68k_getpc();\n");
7527 + printf ("\tuaecptr %sa = get_disp_ea_020(tmppc, next_iword());\n", name);
7529 + printf ("\tuaecptr tmppc = m68k_getpc() + %d;\n", m68k_pc_offset);
7530 + printf ("\tuaecptr %sa = get_disp_ea_000(tmppc, %s);\n", name, gen_nextiword ());
7535 + printf ("\tuaecptr %sa = (uae_s32)(uae_s16)%s;\n", name, gen_nextiword ());
7538 + printf ("\tuaecptr %sa = %s;\n", name, gen_nextilong ());
7541 + if (getv != GENA_GETV_FETCH)
7545 + printf ("\tuae_s8 %s = %s;\n", name, gen_nextibyte ());
7548 + printf ("\tuae_s16 %s = %s;\n", name, gen_nextiword ());
7551 + printf ("\tuae_s32 %s = %s;\n", name, gen_nextilong ());
7558 + if (getv != GENA_GETV_FETCH)
7560 + printf ("\tuae_s8 %s = %s;\n", name, gen_nextibyte ());
7563 + if (getv != GENA_GETV_FETCH)
7565 + printf ("\tuae_s16 %s = %s;\n", name, gen_nextiword ());
7568 + if (getv != GENA_GETV_FETCH)
7570 + printf ("\tuae_s32 %s = %s;\n", name, gen_nextilong ());
7573 + if (getv != GENA_GETV_FETCH)
7575 + printf ("\tuae_u32 %s = %s;\n", name, reg);
7581 + /* We get here for all non-reg non-immediate addressing modes to
7582 + * actually fetch the value. */
7584 + if (using_exception_3 && getv != GENA_GETV_NO_FETCH && size != sz_byte) {
7585 + printf ("\tif ((%sa & 1) != 0) {\n", name);
7586 + printf ("\t\tlast_fault_for_exception_3 = %sa;\n", name);
7587 + printf ("\t\tlast_op_for_exception_3 = opcode;\n");
7588 + printf ("\t\tlast_addr_for_exception_3 = m68k_getpc() + %d;\n", m68k_pc_offset);
7589 + printf ("\t\tException(3, 0);\n");
7590 + printf ("\t\tgoto %s;\n", endlabelstr);
7592 + need_endlabel = 1;
7596 + if (getv == GENA_GETV_FETCH) {
7598 + case sz_byte: insn_n_cycles += 4; break;
7599 + case sz_word: insn_n_cycles += 4; break;
7600 + case sz_long: insn_n_cycles += 8; break;
7601 + default: abort ();
7605 + case sz_byte: printf ("\tuae_s8 %s = %sget_byte(%sa);\n", name, mem_prefix[xlateflag], name); break;
7606 + case sz_word: printf ("\tuae_s16 %s = %sget_word(%sa);\n", name, mem_prefix[xlateflag], name); break;
7607 + case sz_long: printf ("\tuae_s32 %s = %sget_long(%sa);\n", name, mem_prefix[xlateflag], name); break;
7608 + default: abort ();
7612 + /* We now might have to fix up the register for pre-dec or post-inc
7613 + * addressing modes. */
7619 + printf ("\tm68k_areg(regs, %s) += areg_byteinc[%s];\n", reg, reg);
7622 + printf ("\tm68k_areg(regs, %s) += 2;\n", reg);
7625 + printf ("\tm68k_areg(regs, %s) += 4;\n", reg);
7632 + printf ("\tm68k_areg (regs, %s) = %sa;\n", reg, name);
7639 +static void genastore (char *from, amodes mode, char *reg, wordsizes size, char *to, int xlateflag)
7645 + printf ("\tm68k_dreg(regs, %s) = (m68k_dreg(regs, %s) & ~0xff) | ((%s) & 0xff);\n", reg, reg, from);
7648 + printf ("\tm68k_dreg(regs, %s) = (m68k_dreg(regs, %s) & ~0xffff) | ((%s) & 0xffff);\n", reg, reg, from);
7651 + printf ("\tm68k_dreg(regs, %s) = (%s);\n", reg, from);
7660 + write_log ("Foo\n");
7661 + printf ("\tm68k_areg(regs, %s) = (uae_s32)(uae_s16)(%s);\n", reg, from);
7664 + printf ("\tm68k_areg(regs, %s) = (%s);\n", reg, from);
7679 + if (using_prefetch)
7683 + insn_n_cycles += 4;
7684 + printf ("\t%sput_byte(%sa,%s);\n", mem_prefix[xlateflag], to, from);
7687 + insn_n_cycles += 4;
7688 + if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
7690 + printf ("\t%sput_word(%sa,%s);\n", mem_prefix[xlateflag], to, from);
7693 + insn_n_cycles += 8;
7694 + if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
7696 + printf ("\t%sput_long(%sa,%s);\n", mem_prefix[xlateflag], to, from);
7714 +static void genmovemel (uae_u16 opcode)
7716 + char getcode[100];
7717 + int size = table68k[opcode].size == sz_long ? 4 : 2;
7718 + int xlateflag = using_mmu ? XLATE_LOG : XLATE_PHYS;
7720 + if (table68k[opcode].size == sz_long) {
7721 + strcpy (getcode, mem_prefix[xlateflag]);
7722 + strcat (getcode, "get_long(srca)");
7724 + strcpy (getcode, "(uae_s32)(uae_s16)");
7725 + strcat (getcode, mem_prefix[xlateflag]);
7726 + strcat (getcode, "get_word(srca)");
7729 + printf ("\tuae_u16 mask = %s;\n", gen_nextiword ());
7730 + printf ("\tunsigned int dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n");
7731 + genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_NO_INC, xlateflag);
7733 + printf ("\twhile (dmask) { m68k_dreg(regs, movem_index1[dmask]) = %s; srca += %d; dmask = movem_next[dmask]; }\n",
7735 + printf ("\twhile (amask) { m68k_areg(regs, movem_index1[amask]) = %s; srca += %d; amask = movem_next[amask]; }\n",
7738 + if (table68k[opcode].dmode == Aipi)
7739 + printf ("\tm68k_areg(regs, dstreg) = srca;\n");
7742 +static void genmovemle (uae_u16 opcode)
7744 + char putcode[100];
7745 + int size = table68k[opcode].size == sz_long ? 4 : 2;
7746 + int noxlate = using_mmu ? XLATE_LOG : XLATE_PHYS;
7748 + strcpy(putcode, mem_prefix[noxlate]);
7750 + if (table68k[opcode].size == sz_long) {
7751 + strcat (putcode, "put_long(srca,");
7753 + strcat (putcode, "put_word(srca,");
7756 + printf ("\tuae_u16 mask = %s;\n", gen_nextiword ());
7757 + genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src",
7758 + GENA_GETV_FETCH_ALIGN, GENA_MOVEM_NO_INC, XLATE_LOG);
7759 + if (using_prefetch)
7763 + if (table68k[opcode].dmode == Apdi) {
7764 + printf ("\tuae_u16 amask = mask & 0xff, dmask = (mask >> 8) & 0xff;\n");
7765 + printf ("\twhile (amask) { srca -= %d; %s m68k_areg(regs, movem_index2[amask])); amask = movem_next[amask]; }\n",
7767 + printf ("\twhile (dmask) { srca -= %d; %s m68k_dreg(regs, movem_index2[dmask])); dmask = movem_next[dmask]; }\n",
7769 + printf ("\tm68k_areg(regs, dstreg) = srca;\n");
7771 + printf ("\tuae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n");
7772 + printf ("\twhile (dmask) { %s m68k_dreg(regs, movem_index1[dmask])); srca += %d; dmask = movem_next[dmask]; }\n",
7774 + printf ("\twhile (amask) { %s m68k_areg(regs, movem_index1[amask])); srca += %d; amask = movem_next[amask]; }\n",
7779 +static void duplicate_carry (void)
7781 + printf ("\tCOPY_CARRY;\n");
7786 + flag_logical_noclobber, flag_logical, flag_add, flag_sub, flag_cmp, flag_addx, flag_subx, flag_zn,
7791 +static void genflags_normal (flagtypes type, wordsizes size, char *value, char *src, char *dst)
7793 + char vstr[100], sstr[100], dstr[100];
7794 + char usstr[100], udstr[100];
7795 + char unsstr[100], undstr[100];
7799 + strcpy (vstr, "((uae_s8)(");
7800 + strcpy (usstr, "((uae_u8)(");
7803 + strcpy (vstr, "((uae_s16)(");
7804 + strcpy (usstr, "((uae_u16)(");
7807 + strcpy (vstr, "((uae_s32)(");
7808 + strcpy (usstr, "((uae_u32)(");
7813 + strcpy (unsstr, usstr);
7815 + strcpy (sstr, vstr);
7816 + strcpy (dstr, vstr);
7817 + strcat (vstr, value);
7818 + strcat (vstr, "))");
7819 + strcat (dstr, dst);
7820 + strcat (dstr, "))");
7821 + strcat (sstr, src);
7822 + strcat (sstr, "))");
7824 + strcpy (udstr, usstr);
7825 + strcat (udstr, dst);
7826 + strcat (udstr, "))");
7827 + strcat (usstr, src);
7828 + strcat (usstr, "))");
7830 + strcpy (undstr, unsstr);
7831 + strcat (unsstr, "-");
7832 + strcat (undstr, "~");
7833 + strcat (undstr, dst);
7834 + strcat (undstr, "))");
7835 + strcat (unsstr, src);
7836 + strcat (unsstr, "))");
7839 + case flag_logical_noclobber:
7840 + case flag_logical:
7850 + printf ("uae_u32 %s = %s + %s;\n", value, dstr, sstr);
7855 + printf ("uae_u32 %s = %s - %s;\n", value, dstr, sstr);
7860 + case flag_logical_noclobber:
7861 + case flag_logical:
7873 + printf ("\t" BOOL_TYPE " flgs = %s < 0;\n", sstr);
7874 + printf ("\t" BOOL_TYPE " flgo = %s < 0;\n", dstr);
7875 + printf ("\t" BOOL_TYPE " flgn = %s < 0;\n", vstr);
7880 + case flag_logical:
7881 + printf ("\tCLEAR_CZNV;\n");
7882 + printf ("\tSET_ZFLG (%s == 0);\n", vstr);
7883 + printf ("\tSET_NFLG (%s < 0);\n", vstr);
7885 + case flag_logical_noclobber:
7886 + printf ("\tSET_ZFLG (%s == 0);\n", vstr);
7887 + printf ("\tSET_NFLG (%s < 0);\n", vstr);
7890 + printf ("\tSET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));\n");
7893 + printf ("\tSET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));\n");
7896 + printf ("\tSET_ZFLG (GET_ZFLG & (%s == 0));\n", vstr);
7897 + printf ("\tSET_NFLG (%s < 0);\n", vstr);
7900 + printf ("\tSET_ZFLG (%s == 0);\n", vstr);
7901 + printf ("\tSET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));\n");
7902 + printf ("\tSET_CFLG (%s < %s);\n", undstr, usstr);
7903 + duplicate_carry ();
7904 + printf ("\tSET_NFLG (flgn != 0);\n");
7907 + printf ("\tSET_ZFLG (%s == 0);\n", vstr);
7908 + printf ("\tSET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));\n");
7909 + printf ("\tSET_CFLG (%s > %s);\n", usstr, udstr);
7910 + duplicate_carry ();
7911 + printf ("\tSET_NFLG (flgn != 0);\n");
7914 + printf ("\tSET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));\n"); /* minterm SON: 0x42 */
7915 + printf ("\tSET_CFLG (flgs ^ ((flgs ^ flgo) & (flgo ^ flgn)));\n"); /* minterm SON: 0xD4 */
7916 + duplicate_carry ();
7919 + printf ("\tSET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));\n"); /* minterm SON: 0x24 */
7920 + printf ("\tSET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));\n"); /* minterm SON: 0xB2 */
7921 + duplicate_carry ();
7924 + printf ("\tSET_ZFLG (%s == 0);\n", vstr);
7925 + printf ("\tSET_VFLG ((flgs != flgo) && (flgn != flgo));\n");
7926 + printf ("\tSET_CFLG (%s > %s);\n", usstr, udstr);
7927 + printf ("\tSET_NFLG (flgn != 0);\n");
7932 +static void genflags (flagtypes type, wordsizes size, char *value, char *src, char *dst)
7934 + /* Temporarily deleted 68k/ARM flag optimizations. I'd prefer to have
7935 + them in the appropriate m68k.h files and use just one copy of this
7936 + code here. The API can be changed if necessary. */
7937 +#ifdef OPTIMIZED_FLAGS
7942 + printf ("\tuae_u32 %s;\n", value);
7949 + /* At least some of those casts are fairly important! */
7951 + case flag_logical_noclobber:
7952 + printf ("\t{uae_u32 oldcznv = GET_CZNV & ~(FLAGVAL_Z | FLAGVAL_N);\n");
7953 + if (strcmp (value, "0") == 0) {
7954 + printf ("\tSET_CZNV (olcznv | FLAGVAL_Z);\n");
7957 + case sz_byte: printf ("\toptflag_testb ((uae_s8)(%s));\n", value); break;
7958 + case sz_word: printf ("\toptflag_testw ((uae_s16)(%s));\n", value); break;
7959 + case sz_long: printf ("\toptflag_testl ((uae_s32)(%s));\n", value); break;
7961 + printf ("\tIOR_CZNV (oldcznv);\n");
7965 + case flag_logical:
7966 + if (strcmp (value, "0") == 0) {
7967 + printf ("\tSET_CZNV (FLAGVAL_Z);\n");
7970 + case sz_byte: printf ("\toptflag_testb ((uae_s8)(%s));\n", value); break;
7971 + case sz_word: printf ("\toptflag_testw ((uae_s16)(%s));\n", value); break;
7972 + case sz_long: printf ("\toptflag_testl ((uae_s32)(%s));\n", value); break;
7979 + case sz_byte: printf ("\toptflag_addb (%s, (uae_s8)(%s), (uae_s8)(%s));\n", value, src, dst); break;
7980 + case sz_word: printf ("\toptflag_addw (%s, (uae_s16)(%s), (uae_s16)(%s));\n", value, src, dst); break;
7981 + case sz_long: printf ("\toptflag_addl (%s, (uae_s32)(%s), (uae_s32)(%s));\n", value, src, dst); break;
7987 + case sz_byte: printf ("\toptflag_subb (%s, (uae_s8)(%s), (uae_s8)(%s));\n", value, src, dst); break;
7988 + case sz_word: printf ("\toptflag_subw (%s, (uae_s16)(%s), (uae_s16)(%s));\n", value, src, dst); break;
7989 + case sz_long: printf ("\toptflag_subl (%s, (uae_s32)(%s), (uae_s32)(%s));\n", value, src, dst); break;
7995 + case sz_byte: printf ("\toptflag_cmpb ((uae_s8)(%s), (uae_s8)(%s));\n", src, dst); break;
7996 + case sz_word: printf ("\toptflag_cmpw ((uae_s16)(%s), (uae_s16)(%s));\n", src, dst); break;
7997 + case sz_long: printf ("\toptflag_cmpl ((uae_s32)(%s), (uae_s32)(%s));\n", src, dst); break;
8006 + genflags_normal (type, size, value, src, dst);
8009 +static void force_range_for_rox (const char *var, wordsizes size)
8011 + /* Could do a modulo operation here... which one is faster? */
8014 + printf ("\tif (%s >= 33) %s -= 33;\n", var, var);
8017 + printf ("\tif (%s >= 34) %s -= 34;\n", var, var);
8018 + printf ("\tif (%s >= 17) %s -= 17;\n", var, var);
8021 + printf ("\tif (%s >= 36) %s -= 36;\n", var, var);
8022 + printf ("\tif (%s >= 18) %s -= 18;\n", var, var);
8023 + printf ("\tif (%s >= 9) %s -= 9;\n", var, var);
8028 +static const char *cmask (wordsizes size)
8031 + case sz_byte: return "0x80";
8032 + case sz_word: return "0x8000";
8033 + case sz_long: return "0x80000000";
8034 + default: abort ();
8038 +static int source_is_imm1_8 (struct instr *i)
8040 + return i->stype == 3;
8043 +static void gen_opcode (unsigned long int opcode)
8045 + struct instr *curi = table68k + opcode;
8046 + int xlateflag = using_mmu ? XLATE_LOG : XLATE_PHYS;
8047 + insn_n_cycles = 4;
8051 + printf ("uae_u8 *m68k_pc = regs.pc_p;\n");
8053 + m68k_pc_offset = 2;
8054 + switch (curi->plev) {
8055 + case 0: /* not privileged */
8057 + case 1: /* unprivileged only on 68000 */
8058 + if (cpu_level == 0)
8060 + if (next_cpu_level < 0)
8061 + next_cpu_level = 0;
8063 + /* fall through */
8064 + case 2: /* priviledged */
8065 + printf ("if (!regs.s) { Exception(8,0); goto %s; }\n", endlabelstr);
8066 + need_endlabel = 1;
8069 + case 3: /* privileged if size == word */
8070 + if (curi->size == sz_byte)
8072 + printf ("if (!regs.s) { Exception(8,0); goto %s; }\n", endlabelstr);
8073 + need_endlabel = 1;
8077 + switch (curi->mnemo) {
8081 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8082 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8083 + printf ("\tsrc %c= dst;\n", curi->mnemo == i_OR ? '|' : curi->mnemo == i_AND ? '&' : '^');
8084 + genflags (flag_logical, curi->size, "src", "", "");
8085 + genastore ("src", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
8089 + printf ("\tMakeSR();\n");
8090 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8091 + if (curi->size == sz_byte) {
8092 + printf ("\tsrc &= 0xFF;\n");
8094 + printf ("\tregs.sr %c= src;\n", curi->mnemo == i_EORSR ? '^' : '|');
8095 + printf ("\tMakeFromSR();\n");
8098 + printf ("\tMakeSR();\n");
8099 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8100 + if (curi->size == sz_byte) {
8101 + printf ("\tsrc |= 0xFF00;\n");
8103 + printf ("\tregs.sr &= src;\n");
8104 + printf ("\tMakeFromSR();\n");
8107 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8108 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8110 + genflags (flag_sub, curi->size, "newv", "src", "dst");
8111 + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
8114 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8115 + genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8117 + printf ("\tuae_u32 newv = dst - src;\n");
8118 + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", xlateflag);
8121 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8122 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8124 + printf ("\tuae_u32 newv = dst - src - (GET_XFLG ? 1 : 0);\n");
8125 + genflags (flag_subx, curi->size, "newv", "src", "dst");
8126 + genflags (flag_zn, curi->size, "newv", "", "");
8127 + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
8130 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8131 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8133 + printf ("\tuae_u16 newv_lo = (dst & 0xF) - (src & 0xF) - (GET_XFLG ? 1 : 0);\n");
8134 + printf ("\tuae_u16 newv_hi = (dst & 0xF0) - (src & 0xF0);\n");
8135 + printf ("\tuae_u16 newv, tmp_newv;\n");
8136 + printf ("\tint bcd = 0;\n");
8137 + printf ("\tnewv = tmp_newv = newv_hi + newv_lo;\n");
8138 + printf ("\tif (newv_lo & 0xF0) { newv -= 6; bcd = 6; };\n");
8139 + printf ("\tif ((((dst & 0xFF) - (src & 0xFF) - (GET_XFLG ? 1 : 0)) & 0x100) > 0xFF) { newv -= 0x60; }\n");
8140 + printf ("\tSET_CFLG ((((dst & 0xFF) - (src & 0xFF) - bcd - (GET_XFLG ? 1 : 0)) & 0x300) > 0xFF);\n");
8141 + duplicate_carry ();
8142 + genflags (flag_zn, curi->size, "newv", "", "");
8143 + printf ("\tSET_VFLG ((tmp_newv & 0x80) != 0 && (newv & 0x80) == 0);\n");
8144 + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
8147 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8148 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8150 + genflags (flag_add, curi->size, "newv", "src", "dst");
8151 + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
8154 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8155 + genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8157 + printf ("\tuae_u32 newv = dst + src;\n");
8158 + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", xlateflag);
8161 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8162 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8164 + printf ("\tuae_u32 newv = dst + src + (GET_XFLG ? 1 : 0);\n");
8165 + genflags (flag_addx, curi->size, "newv", "src", "dst");
8166 + genflags (flag_zn, curi->size, "newv", "", "");
8167 + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
8170 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8171 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8173 + printf ("\tuae_u16 newv_lo = (src & 0xF) + (dst & 0xF) + (GET_XFLG ? 1 : 0);\n");
8174 + printf ("\tuae_u16 newv_hi = (src & 0xF0) + (dst & 0xF0);\n");
8175 + printf ("\tuae_u16 newv, tmp_newv;\n");
8176 + printf ("\tint cflg;\n");
8177 + printf ("\tnewv = tmp_newv = newv_hi + newv_lo;");
8178 + printf ("\tif (newv_lo > 9) { newv += 6; }\n");
8179 + printf ("\tcflg = (newv & 0x3F0) > 0x90;\n");
8180 + printf ("\tif (cflg) newv += 0x60;\n");
8181 + printf ("\tSET_CFLG (cflg);\n");
8182 + duplicate_carry ();
8183 + genflags (flag_zn, curi->size, "newv", "", "");
8184 + printf ("\tSET_VFLG ((tmp_newv & 0x80) == 0 && (newv & 0x80) != 0);\n");
8185 + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
8188 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8190 + genflags (flag_sub, curi->size, "dst", "src", "0");
8191 + genastore ("dst", curi->smode, "srcreg", curi->size, "src", xlateflag);
8194 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8196 + printf ("\tuae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);\n");
8197 + genflags (flag_subx, curi->size, "newv", "src", "0");
8198 + genflags (flag_zn, curi->size, "newv", "", "");
8199 + genastore ("newv", curi->smode, "srcreg", curi->size, "src", xlateflag);
8202 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8204 + printf ("\tuae_u16 newv_lo = - (src & 0xF) - (GET_XFLG ? 1 : 0);\n");
8205 + printf ("\tuae_u16 newv_hi = - (src & 0xF0);\n");
8206 + printf ("\tuae_u16 newv;\n");
8207 + printf ("\tint cflg;\n");
8208 + printf ("\tif (newv_lo > 9) { newv_lo -= 6; }\n");
8209 + printf ("\tnewv = newv_hi + newv_lo;");
8210 + printf ("\tcflg = (newv & 0x1F0) > 0x90;\n");
8211 + printf ("\tif (cflg) newv -= 0x60;\n");
8212 + printf ("\tSET_CFLG (cflg);\n");
8213 + duplicate_carry();
8214 + genflags (flag_zn, curi->size, "newv", "", "");
8215 + genastore ("newv", curi->smode, "srcreg", curi->size, "src", xlateflag);
8218 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG);
8219 + genflags (flag_logical, curi->size, "0", "", "");
8220 + genastore ("0", curi->smode, "srcreg", curi->size, "src", xlateflag);
8223 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8225 + printf ("\tuae_u32 dst = ~src;\n");
8226 + genflags (flag_logical, curi->size, "dst", "", "");
8227 + genastore ("dst", curi->smode, "srcreg", curi->size, "src", xlateflag);
8230 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8231 + genflags (flag_logical, curi->size, "src", "", "");
8234 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8235 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8236 + if (curi->size == sz_byte)
8237 + printf ("\tsrc &= 7;\n");
8239 + printf ("\tsrc &= 31;\n");
8240 + printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n");
8243 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8244 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8245 + if (curi->size == sz_byte)
8246 + printf ("\tsrc &= 7;\n");
8248 + printf ("\tsrc &= 31;\n");
8249 + printf ("\tdst ^= (1 << src);\n");
8250 + printf ("\tSET_ZFLG (((uae_u32)dst & (1 << src)) >> src);\n");
8251 + genastore ("dst", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
8254 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8255 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8256 + if (curi->size == sz_byte)
8257 + printf ("\tsrc &= 7;\n");
8259 + printf ("\tsrc &= 31;\n");
8260 + printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n");
8261 + printf ("\tdst &= ~(1 << src);\n");
8262 + genastore ("dst", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
8265 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8266 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8267 + if (curi->size == sz_byte)
8268 + printf ("\tsrc &= 7;\n");
8270 + printf ("\tsrc &= 31;\n");
8271 + printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n");
8272 + printf ("\tdst |= (1 << src);\n");
8273 + genastore ("dst", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
8277 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8278 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8280 + genflags (flag_cmp, curi->size, "newv", "src", "dst");
8283 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8284 + genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8286 + genflags (flag_cmp, sz_long, "newv", "src", "dst");
8288 + /* The next two are coded a little unconventional, but they are doing
8289 + * weird things... */
8291 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8293 + printf ("\tuaecptr memp = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword ());
8294 + if (curi->size == sz_word) {
8295 + printf ("\tput_byte(memp, src >> 8); put_byte(memp + 2, src);\n");
8297 + printf ("\tput_byte(memp, src >> 24); put_byte(memp + 2, src >> 16);\n");
8298 + printf ("\tput_byte(memp + 4, src >> 8); put_byte(memp + 6, src);\n");
8302 + printf ("\tuaecptr memp = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword ());
8303 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG);
8304 + if (curi->size == sz_word) {
8305 + printf ("\tuae_u16 val = (get_byte(memp) << 8) + get_byte(memp + 2);\n");
8307 + printf ("\tuae_u32 val = (get_byte(memp) << 24) + (get_byte(memp + 2) << 16)\n");
8308 + printf (" + (get_byte(memp + 4) << 8) + get_byte(memp + 6);\n");
8310 + genastore ("val", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
8313 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8314 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG);
8315 + genflags (flag_logical, curi->size, "src", "", "");
8316 + genastore ("src", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
8319 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8320 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG);
8321 + if (curi->size == sz_word) {
8322 + printf ("\tuae_u32 val = (uae_s32)(uae_s16)src;\n");
8324 + printf ("\tuae_u32 val = src;\n");
8326 + genastore ("val", curi->dmode, "dstreg", sz_long, "dst", xlateflag);
8329 + genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG);
8330 + printf ("\tMakeSR();\n");
8331 + if (curi->size == sz_byte)
8332 + genastore ("regs.sr & 0xff", curi->smode, "srcreg", sz_word, "src", xlateflag);
8334 + genastore ("regs.sr", curi->smode, "srcreg", sz_word, "src", xlateflag);
8337 + genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8338 + if (curi->size == sz_byte)
8339 + printf ("\tMakeSR();\n\tregs.sr &= 0xFF00;\n\tregs.sr |= src & 0xFF;\n");
8341 + printf ("\tregs.sr = src;\n");
8343 + printf ("\tMakeFromSR();\n");
8346 + genamode (curi->smode, "srcreg", sz_long, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8348 + printf ("\tuae_u32 dst = ((src >> 16)&0xFFFF) | ((src&0xFFFF)<<16);\n");
8349 + genflags (flag_logical, sz_long, "dst", "", "");
8350 + genastore ("dst", curi->smode, "srcreg", sz_long, "src", xlateflag);
8353 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8354 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8355 + genastore ("dst", curi->smode, "srcreg", curi->size, "src", xlateflag);
8356 + genastore ("src", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
8359 + genamode (curi->smode, "srcreg", sz_long, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8361 + switch (curi->size) {
8362 + case sz_byte: printf ("\tuae_u32 dst = (uae_s32)(uae_s8)src;\n"); break;
8363 + case sz_word: printf ("\tuae_u16 dst = (uae_s16)(uae_s8)src;\n"); break;
8364 + case sz_long: printf ("\tuae_u32 dst = (uae_s32)(uae_s16)src;\n"); break;
8365 + default: abort ();
8367 + genflags (flag_logical,
8368 + curi->size == sz_word ? sz_word : sz_long, "dst", "", "");
8369 + genastore ("dst", curi->smode, "srcreg",
8370 + curi->size == sz_word ? sz_word : sz_long, "src", xlateflag);
8373 + genmovemel (opcode);
8376 + genmovemle (opcode);
8379 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8381 + printf ("\tException(src+32,0);\n");
8382 + m68k_pc_offset = 0;
8385 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8386 + printf ("\tregs.usp = src;\n");
8389 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG);
8390 + genastore ("regs.usp", curi->smode, "srcreg", curi->size, "src", xlateflag);
8393 + printf ("\tcustomreset();\n");
8398 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8399 + printf ("\tregs.sr = src;\n");
8400 + printf ("\tMakeFromSR();\n");
8401 + printf ("\tm68k_setstopped(1);\n");
8404 + if (cpu_level == 0) {
8405 + genamode (Aipi, "7", sz_word, "sr", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8406 + genamode (Aipi, "7", sz_long, "pc", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8407 + printf ("\tregs.sr = sr; m68k_setpc_rte(pc);\n");
8408 + fill_prefetch_0 ();
8409 + printf ("\tMakeFromSR();\n");
8411 + int old_brace_level = n_braces;
8412 + if (next_cpu_level < 0)
8413 + next_cpu_level = 0;
8414 + printf ("\tuae_u16 newsr; uae_u32 newpc; for (;;) {\n");
8415 + genamode (Aipi, "7", sz_word, "sr", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8416 + genamode (Aipi, "7", sz_long, "pc", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8417 + genamode (Aipi, "7", sz_word, "format", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8418 + printf ("\tnewsr = sr; newpc = pc;\n");
8419 + printf ("\tif ((format & 0xF000) == 0x0000) { break; }\n");
8420 + printf ("\telse if ((format & 0xF000) == 0x1000) { ; }\n");
8421 + printf ("\telse if ((format & 0xF000) == 0x2000) { m68k_areg(regs, 7) += 4; break; }\n");
8422 + printf ("\telse if ((format & 0xF000) == 0x7000) { in_exception_2--; write_log(\"RTE: 2\\n\"); m68k_areg(regs, 7) += 60; break; }\n");
8423 + printf ("\telse if ((format & 0xF000) == 0x8000) { m68k_areg(regs, 7) += 50; break; }\n");
8424 + printf ("\telse if ((format & 0xF000) == 0x9000) { m68k_areg(regs, 7) += 12; break; }\n");
8425 + printf ("\telse if ((format & 0xF000) == 0xa000) { m68k_areg(regs, 7) += 24; break; }\n");
8426 + printf ("\telse if ((format & 0xF000) == 0xb000) { m68k_areg(regs, 7) += 84; break; }\n");
8427 + printf ("\telse { Exception(14,0); goto %s; }\n", endlabelstr);
8428 + printf ("\tregs.sr = newsr; MakeFromSR();\n}\n");
8429 + pop_braces (old_brace_level);
8430 + printf ("\tregs.sr = newsr; MakeFromSR();\n");
8431 + printf ("\tm68k_setpc_rte(newpc);\n");
8432 + fill_prefetch_0 ();
8433 + need_endlabel = 1;
8435 + /* PC is set and prefetch filled. */
8436 + m68k_pc_offset = 0;
8439 + printf ("\tcompiler_flush_jsr_stack();\n");
8440 + genamode (Aipi, "7", sz_long, "pc", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8441 + genamode (curi->smode, "srcreg", curi->size, "offs", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8442 + printf ("\tm68k_areg(regs, 7) += offs;\n");
8443 + printf ("\tm68k_setpc_rte(pc);\n");
8444 + fill_prefetch_0 ();
8445 + /* PC is set and prefetch filled. */
8446 + m68k_pc_offset = 0;
8449 + genamode (Apdi, "7", sz_long, "old", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG);
8450 + genamode (curi->smode, "srcreg", sz_long, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8451 + genastore ("src", Apdi, "7", sz_long, "old", xlateflag);
8452 + genastore ("m68k_areg(regs, 7)", curi->smode, "srcreg", sz_long, "src", xlateflag);
8453 + genamode (curi->dmode, "dstreg", curi->size, "offs", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8454 + printf ("\tm68k_areg(regs, 7) += offs;\n");
8457 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8458 + printf ("\tm68k_areg(regs, 7) = src;\n");
8459 + genamode (Aipi, "7", sz_long, "old", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8460 + genastore ("old", curi->smode, "srcreg", curi->size, "src", xlateflag);
8463 + printf ("\tm68k_do_rts();\n");
8464 + fill_prefetch_0 ();
8465 + m68k_pc_offset = 0;
8469 + printf ("\tif (GET_VFLG) { Exception(7,m68k_getpc()); goto %s; }\n", endlabelstr);
8470 + need_endlabel = 1;
8473 + printf ("\tcompiler_flush_jsr_stack();\n");
8474 + printf ("\tMakeSR();\n");
8475 + genamode (Aipi, "7", sz_word, "sr", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8476 + genamode (Aipi, "7", sz_long, "pc", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8477 + printf ("\tregs.sr &= 0xFF00; sr &= 0xFF;\n");
8478 + printf ("\tregs.sr |= sr; m68k_setpc(pc);\n");
8479 + fill_prefetch_0 ();
8480 + printf ("\tMakeFromSR();\n");
8481 + m68k_pc_offset = 0;
8484 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_NO_FETCH, GENA_MOVEM_DO_INC, XLATE_PHYS);
8485 + printf ("\tm68k_do_jsr(m68k_getpc() + %d, srca);\n", m68k_pc_offset);
8486 + fill_prefetch_0 ();
8487 + m68k_pc_offset = 0;
8490 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_NO_FETCH, GENA_MOVEM_DO_INC, XLATE_PHYS);
8491 + printf ("\tm68k_setpc(srca);\n");
8492 + fill_prefetch_0 ();
8493 + m68k_pc_offset = 0;
8496 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_PHYS);
8497 + printf ("\tuae_s32 s = (uae_s32)src + 2;\n");
8498 + if (using_exception_3) {
8499 + printf ("\tif (src & 1) {\n");
8500 + printf ("\tlast_addr_for_exception_3 = m68k_getpc() + 2;\n");
8501 + printf ("\t\tlast_fault_for_exception_3 = m68k_getpc() + s;\n");
8502 + printf ("\t\tlast_op_for_exception_3 = opcode; Exception(3,0); goto %s;\n", endlabelstr);
8504 + need_endlabel = 1;
8506 + printf ("\tm68k_do_bsr(m68k_getpc() + %d, s);\n", m68k_pc_offset);
8507 + fill_prefetch_0 ();
8508 + m68k_pc_offset = 0;
8511 + if (curi->size == sz_long) {
8512 + if (cpu_level < 2) {
8513 + printf ("\tm68k_incpc(2);\n");
8514 + printf ("\tif (!cctrue(%d)) goto %s;\n", curi->cc, endlabelstr);
8515 + printf ("\t\tlast_addr_for_exception_3 = m68k_getpc() + 2;\n");
8516 + printf ("\t\tlast_fault_for_exception_3 = m68k_getpc() + 1;\n");
8517 + printf ("\t\tlast_op_for_exception_3 = opcode; Exception(3,0); goto %s;\n", endlabelstr);
8518 + need_endlabel = 1;
8520 + if (next_cpu_level < 1)
8521 + next_cpu_level = 1;
8524 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_PHYS);
8525 + printf ("\tif (!cctrue(%d)) goto didnt_jump;\n", curi->cc);
8526 + if (using_exception_3) {
8527 + printf ("\tif (src & 1) {\n");
8528 + printf ("\t\tlast_addr_for_exception_3 = m68k_getpc() + 2;\n");
8529 + printf ("\t\tlast_fault_for_exception_3 = m68k_getpc() + 2 + (uae_s32)src;\n");
8530 + printf ("\t\tlast_op_for_exception_3 = opcode; Exception(3,0); goto %s;\n", endlabelstr);
8532 + need_endlabel = 1;
8534 +#ifdef USE_COMPILER
8535 + printf ("\tm68k_setpc_bcc(m68k_getpc() + 2 + (uae_s32)src);\n");
8537 + printf ("\tm68k_incpc ((uae_s32)src + 2);\n");
8539 + fill_prefetch_0 ();
8540 + printf ("\treturn 5 * CYCLE_UNIT;\n");
8541 + printf ("didnt_jump:;\n");
8542 + need_endlabel = 1;
8543 + insn_n_cycles = curi->size == sz_byte ? 8 : 12;
8546 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_NO_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8547 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG);
8548 + genastore ("srca", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
8551 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_NO_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8552 + genamode (Apdi, "7", sz_long, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG);
8553 + genastore ("srca", Apdi, "7", sz_long, "dst", xlateflag);
8556 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8557 + genamode (curi->dmode, "dstreg", curi->size, "offs", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8559 + printf ("\tif (!cctrue(%d)) {\n", curi->cc);
8560 + genastore ("(src-1)", curi->smode, "srcreg", curi->size, "src", xlateflag);
8562 + printf ("\t\tif (src) {\n");
8563 + if (using_exception_3) {
8564 + printf ("\t\t\tif (offs & 1) {\n");
8565 + printf ("\t\t\tlast_addr_for_exception_3 = m68k_getpc() + 2;\n");
8566 + printf ("\t\t\tlast_fault_for_exception_3 = m68k_getpc() + 2 + (uae_s32)offs + 2;\n");
8567 + printf ("\t\t\tlast_op_for_exception_3 = opcode; Exception(3,0); goto %s;\n", endlabelstr);
8568 + printf ("\t\t}\n");
8569 + need_endlabel = 1;
8571 +#ifdef USE_COMPILER
8572 + printf ("\t\t\tm68k_setpc_bcc(m68k_getpc() + (uae_s32)offs + 2);\n");
8574 + printf ("\t\t\tm68k_incpc((uae_s32)offs + 2);\n");
8576 + fill_prefetch_0 ();
8577 + /* ??? Cycle count is a guess. */
8578 + printf ("\t\treturn 6 * CYCLE_UNIT;\n");
8579 + printf ("\t\t}\n");
8581 + insn_n_cycles = 12;
8582 + need_endlabel = 1;
8585 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG);
8587 + printf ("\tint val = cctrue(%d) ? 0xff : 0;\n", curi->cc);
8588 + genastore ("val", curi->smode, "srcreg", curi->size, "src", xlateflag);
8591 + printf ("\tuaecptr oldpc = m68k_getpc();\n");
8592 + genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8593 + genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8595 + /* Clear V flag when dividing by zero - Alcatraz Odyssey demo depends
8596 + * on this (actually, it's doing a DIVS). */
8597 + printf ("\tif (src == 0) { SET_VFLG (0); Exception (5, oldpc); goto %s; } else {\n", endlabelstr);
8598 + printf ("\tuae_u32 newv = (uae_u32)dst / (uae_u32)(uae_u16)src;\n");
8599 + printf ("\tuae_u32 rem = (uae_u32)dst %% (uae_u32)(uae_u16)src;\n");
8600 + /* The N flag appears to be set each time there is an overflow.
8602 + printf ("\tif (newv > 0xffff) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else\n\t{\n");
8603 + genflags (flag_logical, sz_word, "newv", "", "");
8604 + printf ("\tnewv = (newv & 0xffff) | ((uae_u32)rem << 16);\n");
8605 + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", xlateflag);
8608 + insn_n_cycles += 136;
8609 + need_endlabel = 1;
8612 + printf ("\tuaecptr oldpc = m68k_getpc();\n");
8613 + genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8614 + genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8616 + printf ("\tif (src == 0) { SET_VFLG (0); Exception(5,oldpc); goto %s; } else {\n", endlabelstr);
8617 + printf ("\tuae_s32 newv = (uae_s32)dst / (uae_s32)(uae_s16)src;\n");
8618 + printf ("\tuae_u16 rem = (uae_s32)dst %% (uae_s32)(uae_s16)src;\n");
8619 + printf ("\tif ((newv & 0xffff8000) != 0 && (newv & 0xffff8000) != 0xffff8000) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else\n\t{\n");
8620 + printf ("\tif (((uae_s16)rem < 0) != ((uae_s32)dst < 0)) rem = -rem;\n");
8621 + genflags (flag_logical, sz_word, "newv", "", "");
8622 + printf ("\tnewv = (newv & 0xffff) | ((uae_u32)rem << 16);\n");
8623 + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", xlateflag);
8626 + insn_n_cycles += 154;
8627 + need_endlabel = 1;
8630 + genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8631 + genamode (curi->dmode, "dstreg", sz_word, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8633 + printf ("\tuae_u32 newv = (uae_u32)(uae_u16)dst * (uae_u32)(uae_u16)src;\n");
8634 + genflags (flag_logical, sz_long, "newv", "", "");
8635 + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", xlateflag);
8636 + insn_n_cycles += 66;
8639 + genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8640 + genamode (curi->dmode, "dstreg", sz_word, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8642 + printf ("\tuae_u32 newv = (uae_s32)(uae_s16)dst * (uae_s32)(uae_s16)src;\n");
8643 + genflags (flag_logical, sz_long, "newv", "", "");
8644 + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", xlateflag);
8645 + insn_n_cycles += 66;
8648 + printf ("\tuaecptr oldpc = m68k_getpc();\n");
8649 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8650 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8651 + printf ("\tif ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc); goto %s; }\n", endlabelstr);
8652 + printf ("\telse if (dst > src) { SET_NFLG (0); Exception(6,oldpc); goto %s; }\n", endlabelstr);
8653 + need_endlabel = 1;
8657 + printf ("\tuaecptr oldpc = m68k_getpc();\n");
8658 + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8659 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG);
8660 + printf ("\t{uae_s32 upper,lower,reg = regs.regs[(extra >> 12) & 15];\n");
8661 + switch (curi->size) {
8663 + printf ("\tlower=(uae_s32)(uae_s8)get_byte(dsta); upper = (uae_s32)(uae_s8)get_byte(dsta+1);\n");
8664 + printf ("\tif ((extra & 0x8000) == 0) reg = (uae_s32)(uae_s8)reg;\n");
8667 + printf ("\tlower=(uae_s32)(uae_s16)get_word(dsta); upper = (uae_s32)(uae_s16)get_word(dsta+2);\n");
8668 + printf ("\tif ((extra & 0x8000) == 0) reg = (uae_s32)(uae_s16)reg;\n");
8671 + printf ("\tlower=get_long(dsta); upper = get_long(dsta+4);\n");
8676 + printf ("\tSET_ZFLG (upper == reg || lower == reg);\n");
8677 + printf ("\tSET_CFLG (lower <= upper ? reg < lower || reg > upper : reg > upper || reg < lower);\n");
8678 + printf ("\tif ((extra & 0x800) && GET_CFLG) { Exception(6,oldpc); goto %s; }\n}\n", endlabelstr);
8679 + need_endlabel = 1;
8683 + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8684 + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8686 + switch (curi->size) {
8687 + case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
8688 + case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
8689 + case sz_long: printf ("\tuae_u32 val = data;\n"); break;
8690 + default: abort ();
8692 + printf ("\tuae_u32 sign = (%s & val) >> %d;\n", cmask (curi->size), bit_size (curi->size) - 1);
8693 + printf ("\tcnt &= 63;\n");
8694 + printf ("\tCLEAR_CZNV;\n");
8695 + printf ("\tif (cnt >= %d) {\n", bit_size (curi->size));
8696 + printf ("\t\tval = %s & (uae_u32)-sign;\n", bit_mask (curi->size));
8697 + printf ("\t\tSET_CFLG (sign);\n");
8698 + duplicate_carry ();
8699 + if (source_is_imm1_8 (curi))
8700 + printf ("\t} else {\n");
8702 + printf ("\t} else if (cnt > 0) {\n");
8703 + printf ("\t\tval >>= cnt - 1;\n");
8704 + printf ("\t\tSET_CFLG (val & 1);\n");
8705 + duplicate_carry ();
8706 + printf ("\t\tval >>= 1;\n");
8707 + printf ("\t\tval |= (%s << (%d - cnt)) & (uae_u32)-sign;\n",
8708 + bit_mask (curi->size),
8709 + bit_size (curi->size));
8710 + printf ("\t\tval &= %s;\n", bit_mask (curi->size));
8712 + genflags (flag_logical_noclobber, curi->size, "val", "", "");
8713 + genastore ("val", curi->dmode, "dstreg", curi->size, "data", xlateflag);
8716 + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8717 + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8719 + switch (curi->size) {
8720 + case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
8721 + case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
8722 + case sz_long: printf ("\tuae_u32 val = data;\n"); break;
8723 + default: abort ();
8725 + printf ("\tcnt &= 63;\n");
8726 + printf ("\tCLEAR_CZNV;\n");
8727 + printf ("\tif (cnt >= %d) {\n", bit_size (curi->size));
8728 + printf ("\t\tSET_VFLG (val != 0);\n");
8729 + printf ("\t\tSET_CFLG (cnt == %d ? val & 1 : 0);\n",
8730 + bit_size (curi->size));
8731 + duplicate_carry ();
8732 + printf ("\t\tval = 0;\n");
8733 + if (source_is_imm1_8 (curi))
8734 + printf ("\t} else {\n");
8736 + printf ("\t} else if (cnt > 0) {\n");
8737 + printf ("\t\tuae_u32 mask = (%s << (%d - cnt)) & %s;\n",
8738 + bit_mask (curi->size),
8739 + bit_size (curi->size) - 1,
8740 + bit_mask (curi->size));
8741 + printf ("\t\tSET_VFLG ((val & mask) != mask && (val & mask) != 0);\n");
8742 + printf ("\t\tval <<= cnt - 1;\n");
8743 + printf ("\t\tSET_CFLG ((val & %s) >> %d);\n", cmask (curi->size), bit_size (curi->size) - 1);
8744 + duplicate_carry ();
8745 + printf ("\t\tval <<= 1;\n");
8746 + printf ("\t\tval &= %s;\n", bit_mask (curi->size));
8748 + genflags (flag_logical_noclobber, curi->size, "val", "", "");
8749 + genastore ("val", curi->dmode, "dstreg", curi->size, "data", xlateflag);
8752 + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8753 + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8755 + switch (curi->size) {
8756 + case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
8757 + case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
8758 + case sz_long: printf ("\tuae_u32 val = data;\n"); break;
8759 + default: abort ();
8761 + printf ("\tcnt &= 63;\n");
8762 + printf ("\tCLEAR_CZNV;\n");
8763 + printf ("\tif (cnt >= %d) {\n", bit_size (curi->size));
8764 + printf ("\t\tSET_CFLG ((cnt == %d) & (val >> %d));\n",
8765 + bit_size (curi->size), bit_size (curi->size) - 1);
8766 + duplicate_carry ();
8767 + printf ("\t\tval = 0;\n");
8768 + if (source_is_imm1_8 (curi))
8769 + printf ("\t} else {\n");
8771 + printf ("\t} else if (cnt > 0) {\n");
8772 + printf ("\t\tval >>= cnt - 1;\n");
8773 + printf ("\t\tSET_CFLG (val & 1);\n");
8774 + duplicate_carry ();
8775 + printf ("\t\tval >>= 1;\n");
8777 + genflags (flag_logical_noclobber, curi->size, "val", "", "");
8778 + genastore ("val", curi->dmode, "dstreg", curi->size, "data", xlateflag);
8781 + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8782 + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8784 + switch (curi->size) {
8785 + case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
8786 + case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
8787 + case sz_long: printf ("\tuae_u32 val = data;\n"); break;
8788 + default: abort ();
8790 + printf ("\tcnt &= 63;\n");
8791 + printf ("\tCLEAR_CZNV;\n");
8792 + printf ("\tif (cnt >= %d) {\n", bit_size (curi->size));
8793 + printf ("\t\tSET_CFLG (cnt == %d ? val & 1 : 0);\n",
8794 + bit_size (curi->size));
8795 + duplicate_carry ();
8796 + printf ("\t\tval = 0;\n");
8797 + if (source_is_imm1_8 (curi))
8798 + printf ("\t} else {\n");
8800 + printf ("\t} else if (cnt > 0) {\n");
8801 + printf ("\t\tval <<= (cnt - 1);\n");
8802 + printf ("\t\tSET_CFLG ((val & %s) >> %d);\n", cmask (curi->size), bit_size (curi->size) - 1);
8803 + duplicate_carry ();
8804 + printf ("\t\tval <<= 1;\n");
8805 + printf ("\tval &= %s;\n", bit_mask (curi->size));
8807 + genflags (flag_logical_noclobber, curi->size, "val", "", "");
8808 + genastore ("val", curi->dmode, "dstreg", curi->size, "data", xlateflag);
8811 + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8812 + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8814 + switch (curi->size) {
8815 + case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
8816 + case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
8817 + case sz_long: printf ("\tuae_u32 val = data;\n"); break;
8818 + default: abort ();
8820 + printf ("\tcnt &= 63;\n");
8821 + printf ("\tCLEAR_CZNV;\n");
8822 + if (source_is_imm1_8 (curi))
8825 + printf ("\tif (cnt > 0) {\n");
8826 + printf ("\tuae_u32 loval;\n");
8827 + printf ("\tcnt &= %d;\n", bit_size (curi->size) - 1);
8828 + printf ("\tloval = val >> (%d - cnt);\n", bit_size (curi->size));
8829 + printf ("\tval <<= cnt;\n");
8830 + printf ("\tval |= loval;\n");
8831 + printf ("\tval &= %s;\n", bit_mask (curi->size));
8832 + printf ("\tSET_CFLG (val & 1);\n");
8834 + genflags (flag_logical_noclobber, curi->size, "val", "", "");
8835 + genastore ("val", curi->dmode, "dstreg", curi->size, "data", xlateflag);
8838 + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8839 + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8841 + switch (curi->size) {
8842 + case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
8843 + case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
8844 + case sz_long: printf ("\tuae_u32 val = data;\n"); break;
8845 + default: abort ();
8847 + printf ("\tcnt &= 63;\n");
8848 + printf ("\tCLEAR_CZNV;\n");
8849 + if (source_is_imm1_8 (curi))
8852 + printf ("\tif (cnt > 0) {");
8853 + printf ("\tuae_u32 hival;\n");
8854 + printf ("\tcnt &= %d;\n", bit_size (curi->size) - 1);
8855 + printf ("\thival = val << (%d - cnt);\n", bit_size (curi->size));
8856 + printf ("\tval >>= cnt;\n");
8857 + printf ("\tval |= hival;\n");
8858 + printf ("\tval &= %s;\n", bit_mask (curi->size));
8859 + printf ("\tSET_CFLG ((val & %s) >> %d);\n", cmask (curi->size), bit_size (curi->size) - 1);
8861 + genflags (flag_logical_noclobber, curi->size, "val", "", "");
8862 + genastore ("val", curi->dmode, "dstreg", curi->size, "data", xlateflag);
8865 + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8866 + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8868 + switch (curi->size) {
8869 + case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
8870 + case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
8871 + case sz_long: printf ("\tuae_u32 val = data;\n"); break;
8872 + default: abort ();
8874 + printf ("\tcnt &= 63;\n");
8875 + printf ("\tCLEAR_CZNV;\n");
8876 + if (source_is_imm1_8 (curi))
8879 + force_range_for_rox ("cnt", curi->size);
8880 + printf ("\tif (cnt > 0) {\n");
8882 + printf ("\tcnt--;\n");
8883 + printf ("\t{\n\tuae_u32 carry;\n");
8884 + printf ("\tuae_u32 loval = val >> (%d - cnt);\n", bit_size (curi->size) - 1);
8885 + printf ("\tcarry = loval & 1;\n");
8886 + printf ("\tval = (((val << 1) | GET_XFLG) << cnt) | (loval >> 1);\n");
8887 + printf ("\tSET_XFLG (carry);\n");
8888 + printf ("\tval &= %s;\n", bit_mask (curi->size));
8889 + printf ("\t} }\n");
8890 + printf ("\tSET_CFLG (GET_XFLG);\n");
8891 + genflags (flag_logical_noclobber, curi->size, "val", "", "");
8892 + genastore ("val", curi->dmode, "dstreg", curi->size, "data", xlateflag);
8895 + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8896 + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8898 + switch (curi->size) {
8899 + case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
8900 + case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
8901 + case sz_long: printf ("\tuae_u32 val = data;\n"); break;
8902 + default: abort ();
8904 + printf ("\tcnt &= 63;\n");
8905 + printf ("\tCLEAR_CZNV;\n");
8906 + if (source_is_imm1_8 (curi))
8909 + force_range_for_rox ("cnt", curi->size);
8910 + printf ("\tif (cnt > 0) {\n");
8912 + printf ("\tcnt--;\n");
8913 + printf ("\t{\n\tuae_u32 carry;\n");
8914 + printf ("\tuae_u32 hival = (val << 1) | GET_XFLG;\n");
8915 + printf ("\thival <<= (%d - cnt);\n", bit_size (curi->size) - 1);
8916 + printf ("\tval >>= cnt;\n");
8917 + printf ("\tcarry = val & 1;\n");
8918 + printf ("\tval >>= 1;\n");
8919 + printf ("\tval |= hival;\n");
8920 + printf ("\tSET_XFLG (carry);\n");
8921 + printf ("\tval &= %s;\n", bit_mask (curi->size));
8922 + printf ("\t} }\n");
8923 + printf ("\tSET_CFLG (GET_XFLG);\n");
8924 + genflags (flag_logical_noclobber, curi->size, "val", "", "");
8925 + genastore ("val", curi->dmode, "dstreg", curi->size, "data", xlateflag);
8928 + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8930 + switch (curi->size) {
8931 + case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
8932 + case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
8933 + case sz_long: printf ("\tuae_u32 val = data;\n"); break;
8934 + default: abort ();
8936 + printf ("\tuae_u32 sign = %s & val;\n", cmask (curi->size));
8937 + printf ("\tuae_u32 cflg = val & 1;\n");
8938 + printf ("\tval = (val >> 1) | sign;\n");
8939 + genflags (flag_logical, curi->size, "val", "", "");
8940 + printf ("\tSET_CFLG (cflg);\n");
8941 + duplicate_carry ();
8942 + genastore ("val", curi->smode, "srcreg", curi->size, "data", xlateflag);
8945 + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8947 + switch (curi->size) {
8948 + case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
8949 + case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
8950 + case sz_long: printf ("\tuae_u32 val = data;\n"); break;
8951 + default: abort ();
8953 + printf ("\tuae_u32 sign = %s & val;\n", cmask (curi->size));
8954 + printf ("\tuae_u32 sign2;\n");
8955 + printf ("\tval <<= 1;\n");
8956 + genflags (flag_logical, curi->size, "val", "", "");
8957 + printf ("\tsign2 = %s & val;\n", cmask (curi->size));
8958 + printf ("\tSET_CFLG (sign != 0);\n");
8959 + duplicate_carry ();
8961 + printf ("\tSET_VFLG (GET_VFLG | (sign2 != sign));\n");
8962 + genastore ("val", curi->smode, "srcreg", curi->size, "data", xlateflag);
8965 + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8967 + switch (curi->size) {
8968 + case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
8969 + case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
8970 + case sz_long: printf ("\tuae_u32 val = data;\n"); break;
8971 + default: abort ();
8973 + printf ("\tuae_u32 carry = val & 1;\n");
8974 + printf ("\tval >>= 1;\n");
8975 + genflags (flag_logical, curi->size, "val", "", "");
8976 + printf ("SET_CFLG (carry);\n");
8977 + duplicate_carry ();
8978 + genastore ("val", curi->smode, "srcreg", curi->size, "data", xlateflag);
8981 + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8983 + switch (curi->size) {
8984 + case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
8985 + case sz_word: printf ("\tuae_u16 val = data;\n"); break;
8986 + case sz_long: printf ("\tuae_u32 val = data;\n"); break;
8987 + default: abort ();
8989 + printf ("\tuae_u32 carry = val & %s;\n", cmask (curi->size));
8990 + printf ("\tval <<= 1;\n");
8991 + genflags (flag_logical, curi->size, "val", "", "");
8992 + printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1);
8993 + duplicate_carry ();
8994 + genastore ("val", curi->smode, "srcreg", curi->size, "data", xlateflag);
8997 + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8999 + switch (curi->size) {
9000 + case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
9001 + case sz_word: printf ("\tuae_u16 val = data;\n"); break;
9002 + case sz_long: printf ("\tuae_u32 val = data;\n"); break;
9003 + default: abort ();
9005 + printf ("\tuae_u32 carry = val & %s;\n", cmask (curi->size));
9006 + printf ("\tval <<= 1;\n");
9007 + printf ("\tif (carry) val |= 1;\n");
9008 + genflags (flag_logical, curi->size, "val", "", "");
9009 + printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1);
9010 + genastore ("val", curi->smode, "srcreg", curi->size, "data", xlateflag);
9013 + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9015 + switch (curi->size) {
9016 + case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
9017 + case sz_word: printf ("\tuae_u16 val = data;\n"); break;
9018 + case sz_long: printf ("\tuae_u32 val = data;\n"); break;
9019 + default: abort ();
9021 + printf ("\tuae_u32 carry = val & 1;\n");
9022 + printf ("\tval >>= 1;\n");
9023 + printf ("\tif (carry) val |= %s;\n", cmask (curi->size));
9024 + genflags (flag_logical, curi->size, "val", "", "");
9025 + printf ("SET_CFLG (carry);\n");
9026 + genastore ("val", curi->smode, "srcreg", curi->size, "data", xlateflag);
9029 + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9031 + switch (curi->size) {
9032 + case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
9033 + case sz_word: printf ("\tuae_u16 val = data;\n"); break;
9034 + case sz_long: printf ("\tuae_u32 val = data;\n"); break;
9035 + default: abort ();
9037 + printf ("\tuae_u32 carry = val & %s;\n", cmask (curi->size));
9038 + printf ("\tval <<= 1;\n");
9039 + printf ("\tif (GET_XFLG) val |= 1;\n");
9040 + genflags (flag_logical, curi->size, "val", "", "");
9041 + printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1);
9042 + duplicate_carry ();
9043 + genastore ("val", curi->smode, "srcreg", curi->size, "data", xlateflag);
9046 + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9048 + switch (curi->size) {
9049 + case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
9050 + case sz_word: printf ("\tuae_u16 val = data;\n"); break;
9051 + case sz_long: printf ("\tuae_u32 val = data;\n"); break;
9052 + default: abort ();
9054 + printf ("\tuae_u32 carry = val & 1;\n");
9055 + printf ("\tval >>= 1;\n");
9056 + printf ("\tif (GET_XFLG) val |= %s;\n", cmask (curi->size));
9057 + genflags (flag_logical, curi->size, "val", "", "");
9058 + printf ("SET_CFLG (carry);\n");
9059 + duplicate_carry ();
9060 + genastore ("val", curi->smode, "srcreg", curi->size, "data", xlateflag);
9063 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9065 + printf ("\tint regno = (src >> 12) & 15;\n");
9066 + printf ("\tuae_u32 *regp = regs.regs + regno;\n");
9067 + printf ("\tif (! m68k_movec2(src & 0xFFF, regp)) goto %s;\n", endlabelstr);
9070 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9072 + printf ("\tint regno = (src >> 12) & 15;\n");
9073 + printf ("\tuae_u32 *regp = regs.regs + regno;\n");
9074 + printf ("\tif (! m68k_move2c(src & 0xFFF, regp)) goto %s;\n", endlabelstr);
9078 + int old_brace_level;
9079 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9080 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9082 + printf ("\tint ru = (src >> 6) & 7;\n");
9083 + printf ("\tint rc = src & 7;\n");
9084 + genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, rc)", "dst");
9085 + printf ("\tif (GET_ZFLG)");
9086 + old_brace_level = n_braces;
9088 + genastore ("(m68k_dreg(regs, ru))", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
9089 + pop_braces (old_brace_level);
9092 + printf ("m68k_dreg(regs, rc) = dst;\n");
9093 + pop_braces (old_brace_level);
9097 + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9098 + printf ("\tuae_u32 rn1 = regs.regs[(extra >> 28) & 15];\n");
9099 + printf ("\tuae_u32 rn2 = regs.regs[(extra >> 12) & 15];\n");
9100 + if (curi->size == sz_word) {
9101 + int old_brace_level = n_braces;
9102 + printf ("\tuae_u16 dst1 = get_word(rn1), dst2 = get_word(rn2);\n");
9103 + genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, (extra >> 16) & 7)", "dst1");
9104 + printf ("\tif (GET_ZFLG) {\n");
9105 + genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, extra & 7)", "dst2");
9106 + printf ("\tif (GET_ZFLG) {\n");
9107 + printf ("\tput_word(rn1, m68k_dreg(regs, (extra >> 22) & 7));\n");
9108 + printf ("\tput_word(rn1, m68k_dreg(regs, (extra >> 6) & 7));\n");
9109 + printf ("\t}}\n");
9110 + pop_braces (old_brace_level);
9111 + printf ("\tif (! GET_ZFLG) {\n");
9112 + printf ("\tm68k_dreg(regs, (extra >> 22) & 7) = (m68k_dreg(regs, (extra >> 22) & 7) & ~0xffff) | (dst1 & 0xffff);\n");
9113 + printf ("\tm68k_dreg(regs, (extra >> 6) & 7) = (m68k_dreg(regs, (extra >> 6) & 7) & ~0xffff) | (dst2 & 0xffff);\n");
9116 + int old_brace_level = n_braces;
9117 + printf ("\tuae_u32 dst1 = get_long(rn1), dst2 = get_long(rn2);\n");
9118 + genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, (extra >> 16) & 7)", "dst1");
9119 + printf ("\tif (GET_ZFLG) {\n");
9120 + genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, extra & 7)", "dst2");
9121 + printf ("\tif (GET_ZFLG) {\n");
9122 + printf ("\tput_long(rn1, m68k_dreg(regs, (extra >> 22) & 7));\n");
9123 + printf ("\tput_long(rn1, m68k_dreg(regs, (extra >> 6) & 7));\n");
9124 + printf ("\t}}\n");
9125 + pop_braces (old_brace_level);
9126 + printf ("\tif (! GET_ZFLG) {\n");
9127 + printf ("\tm68k_dreg(regs, (extra >> 22) & 7) = dst1;\n");
9128 + printf ("\tm68k_dreg(regs, (extra >> 6) & 7) = dst2;\n");
9134 + int old_brace_level;
9136 + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9138 + printf ("\tif (extra & 0x0800)\n"); /* from reg to ea */
9141 + old_brace_level = n_braces;
9143 + printf ("\tuae_u32 src = regs.regs[(extra >> 12) & 15];\n");
9144 + nexti_no_inc = 1; /* prevent strange problems with misaligned insns */
9145 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_DFC);
9147 + genastore ("src", curi->dmode, "dstreg", curi->size, "dst", XLATE_DFC);
9148 + pop_braces (old_brace_level);
9150 + printf ("else"); /* from ea to reg */
9154 + genamode (curi->dmode, "dstreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_SFC);
9155 + printf ("\tif (extra & 0x8000) {\n"); /* address/data */
9156 + switch (curi->size) {
9157 + case sz_byte: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = (uae_s32)(uae_s8)src;\n"); break;
9158 + case sz_word: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = (uae_s32)(uae_s16)src;\n"); break;
9159 + case sz_long: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = src;\n"); break;
9160 + default: abort ();
9162 + printf ("\t} else {\n");
9163 + genastore ("src", Dreg, "(extra >> 12) & 7", curi->size, "", XLATE_LOG);
9165 + pop_braces (old_brace_level);
9169 + case i_BKPT: /* only needed for hardware emulators */
9171 + printf ("\top_illg(opcode);\n");
9173 + case i_CALLM: /* not present in 68030 */
9175 + printf ("\top_illg(opcode);\n");
9177 + case i_RTM: /* not present in 68030 */
9179 + printf ("\top_illg(opcode);\n");
9182 + if (curi->smode != am_unknown && curi->smode != am_illg)
9183 + genamode (curi->smode, "srcreg", curi->size, "dummy", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9184 + printf ("\tif (cctrue(%d)) { Exception(7,m68k_getpc()); goto %s; }\n", curi->cc, endlabelstr);
9185 + need_endlabel = 1;
9190 + printf ("\tuaecptr oldpc = m68k_getpc();\n");
9191 + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9192 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9194 + printf ("\tm68k_divl(opcode, dst, extra, oldpc);\n");
9197 + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9198 + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9200 + printf ("\tm68k_mull(opcode, dst, extra);\n");
9210 + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9211 + genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG);
9213 + printf ("\tuae_s32 offset = extra & 0x800 ? m68k_dreg(regs, (extra >> 6) & 7) : (extra >> 6) & 0x1f;\n");
9214 + printf ("\tint width = (((extra & 0x20 ? m68k_dreg(regs, extra & 7) : extra) -1) & 0x1f) +1;\n");
9215 + if (curi->dmode == Dreg) {
9216 + printf ("\tuae_u32 tmp = m68k_dreg(regs, dstreg) << (offset & 0x1f);\n");
9218 + printf ("\tuae_u32 tmp,bf0,bf1;\n");
9219 + printf ("\tdsta += (offset >> 3) | (offset & 0x80000000 ? ~0x1fffffff : 0);\n");
9220 + printf ("\tbf0 = get_long(dsta);bf1 = get_byte(dsta+4) & 0xff;\n");
9221 + printf ("\ttmp = (bf0 << (offset & 7)) | (bf1 >> (8 - (offset & 7)));\n");
9223 + printf ("\ttmp >>= (32 - width);\n");
9224 + printf ("\tSET_NFLG (tmp & (1 << (width-1)) ? 1 : 0);\n");
9225 + printf ("\tSET_ZFLG (tmp == 0); SET_VFLG (0); SET_CFLG (0);\n");
9226 + switch (curi->mnemo) {
9230 + printf ("\tm68k_dreg(regs, (extra >> 12) & 7) = tmp;\n");
9233 + printf ("\ttmp = ~tmp;\n");
9236 + printf ("\tif (GET_NFLG) tmp |= width == 32 ? 0 : (-1 << width);\n");
9237 + printf ("\tm68k_dreg(regs, (extra >> 12) & 7) = tmp;\n");
9240 + printf ("\ttmp = 0;\n");
9243 + printf ("\t{ uae_u32 mask = 1 << (width-1);\n");
9244 + printf ("\twhile (mask) { if (tmp & mask) break; mask >>= 1; offset++; }}\n");
9245 + printf ("\tm68k_dreg(regs, (extra >> 12) & 7) = offset;\n");
9248 + printf ("\ttmp = 0xffffffff;\n");
9251 + printf ("\ttmp = m68k_dreg(regs, (extra >> 12) & 7);\n");
9252 + printf ("\tSET_NFLG (tmp & (1 << (width - 1)) ? 1 : 0);\n");
9253 + printf ("\tSET_ZFLG (tmp == 0);\n");
9258 + if (curi->mnemo == i_BFCHG
9259 + || curi->mnemo == i_BFCLR
9260 + || curi->mnemo == i_BFSET
9261 + || curi->mnemo == i_BFINS)
9263 + printf ("\ttmp <<= (32 - width);\n");
9264 + if (curi->dmode == Dreg) {
9265 + printf ("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ((offset & 0x1f) == 0 ? 0 :\n");
9266 + printf ("\t\t(0xffffffff << (32 - (offset & 0x1f))))) |\n");
9267 + printf ("\t\t(tmp >> (offset & 0x1f)) |\n");
9268 + printf ("\t\t(((offset & 0x1f) + width) >= 32 ? 0 :\n");
9269 + printf (" (m68k_dreg(regs, dstreg) & ((uae_u32)0xffffffff >> ((offset & 0x1f) + width))));\n");
9271 + printf ("\tbf0 = (bf0 & (0xff000000 << (8 - (offset & 7)))) |\n");
9272 + printf ("\t\t(tmp >> (offset & 7)) |\n");
9273 + printf ("\t\t(((offset & 7) + width) >= 32 ? 0 :\n");
9274 + printf ("\t\t (bf0 & ((uae_u32)0xffffffff >> ((offset & 7) + width))));\n");
9275 + printf ("\tput_long(dsta,bf0 );\n");
9276 + printf ("\tif (((offset & 7) + width) > 32) {\n");
9277 + printf ("\t\tbf1 = (bf1 & (0xff >> (width - 32 + (offset & 7)))) |\n");
9278 + printf ("\t\t\t(tmp << (8 - (offset & 7)));\n");
9279 + printf ("\t\tput_byte(dsta+4,bf1);\n");
9285 + if (curi->smode == Dreg) {
9286 + printf ("\tuae_u16 val = m68k_dreg(regs, srcreg) + %s;\n", gen_nextiword ());
9287 + printf ("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & 0xffffff00) | ((val >> 4) & 0xf0) | (val & 0xf);\n");
9289 + printf ("\tuae_u16 val;\n");
9290 + printf ("\tm68k_areg(regs, srcreg) -= areg_byteinc[srcreg];\n");
9291 + printf ("\tval = (uae_u16)get_byte(m68k_areg(regs, srcreg));\n");
9292 + printf ("\tm68k_areg(regs, srcreg) -= areg_byteinc[srcreg];\n");
9293 + printf ("\tval = (val | ((uae_u16)get_byte(m68k_areg(regs, srcreg)) << 8)) + %s;\n", gen_nextiword ());
9294 + printf ("\tm68k_areg(regs, dstreg) -= areg_byteinc[dstreg];\n");
9295 + printf ("\tput_byte(m68k_areg(regs, dstreg),((val >> 4) & 0xf0) | (val & 0xf));\n");
9299 + if (curi->smode == Dreg) {
9300 + printf ("\tuae_u16 val = m68k_dreg(regs, srcreg);\n");
9301 + printf ("\tval = (((val << 4) & 0xf00) | (val & 0xf)) + %s;\n", gen_nextiword ());
9302 + printf ("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & 0xffff0000) | (val & 0xffff);\n");
9304 + printf ("\tuae_u16 val;\n");
9305 + printf ("\tm68k_areg(regs, srcreg) -= areg_byteinc[srcreg];\n");
9306 + printf ("\tval = (uae_u16)get_byte(m68k_areg(regs, srcreg));\n");
9307 + printf ("\tval = (((val << 4) & 0xf00) | (val & 0xf)) + %s;\n", gen_nextiword ());
9308 + printf ("\tm68k_areg(regs, dstreg) -= areg_byteinc[dstreg];\n");
9309 + printf ("\tput_byte(m68k_areg(regs, dstreg),val);\n");
9310 + printf ("\tm68k_areg(regs, dstreg) -= areg_byteinc[dstreg];\n");
9311 + printf ("\tput_byte(m68k_areg(regs, dstreg),val >> 8);\n");
9315 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9316 + genflags (flag_logical, curi->size, "src", "", "");
9317 + printf ("\tsrc |= 0x80;\n");
9318 + genastore ("src", curi->smode, "srcreg", curi->size, "src", xlateflag);
9321 + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9323 + printf ("\tfpp_opp(opcode,extra);\n");
9326 + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9328 + printf ("\tfdbcc_opp(opcode,extra);\n");
9331 + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9333 + printf ("\tfscc_opp(opcode,extra);\n");
9338 + printf ("\tuaecptr oldpc = m68k_getpc();\n");
9339 + if (curi->smode != am_unknown && curi->smode != am_illg)
9340 + genamode (curi->smode, "srcreg", curi->size, "dummy", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9342 + printf ("\tftrapcc_opp(opcode,oldpc);\n");
9347 + printf ("\tuaecptr pc = m68k_getpc();\n");
9348 + genamode (curi->dmode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9350 + printf ("\tfbcc_opp(opcode,pc,extra);\n");
9354 + printf ("\tfsave_opp(opcode);\n");
9358 + printf ("\tfrestore_opp(opcode);\n");
9369 + if ((opcode & 0xfff8) == 0xf620) {
9370 + /* MOVE16 (Ax)+,(Ay)+ */
9371 + printf ("\tuaecptr mems = m68k_areg(regs, srcreg) & ~15, memd;\n");
9372 + printf ("\tdstreg = (%s >> 12) & 7;\n", gen_nextiword());
9373 + printf ("\tmemd = m68k_areg(regs, dstreg) & ~15;\n");
9374 + printf ("\tput_long(memd, get_long(mems));\n");
9375 + printf ("\tput_long(memd+4, get_long(mems+4));\n");
9376 + printf ("\tput_long(memd+8, get_long(mems+8));\n");
9377 + printf ("\tput_long(memd+12, get_long(mems+12));\n");
9378 + printf ("\tif (srcreg != dstreg)\n");
9379 + printf ("\tm68k_areg(regs, srcreg) += 16;\n");
9380 + printf ("\tm68k_areg(regs, dstreg) += 16;\n");
9382 + /* Other variants */
9383 + genamode (curi->smode, "srcreg", curi->size, "mems", GENA_GETV_NO_FETCH, GENA_MOVEM_MOVE16, XLATE_LOG);
9384 + genamode (curi->dmode, "dstreg", curi->size, "memd", GENA_GETV_NO_FETCH, GENA_MOVEM_MOVE16, XLATE_LOG);
9385 + printf ("\tmemsa &= ~15;\n");
9386 + printf ("\tmemda &= ~15;\n");
9387 + printf ("\tput_long(memda, get_long(memsa));\n");
9388 + printf ("\tput_long(memda+4, get_long(memsa+4));\n");
9389 + printf ("\tput_long(memda+8, get_long(memsa+8));\n");
9390 + printf ("\tput_long(memda+12, get_long(memsa+12));\n");
9391 + if ((opcode & 0xfff8) == 0xf600)
9392 + printf ("\tm68k_areg(regs, srcreg) += 16;\n");
9393 + else if ((opcode & 0xfff8) == 0xf608)
9394 + printf ("\tm68k_areg(regs, dstreg) += 16;\n");
9399 + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9401 + printf ("\tmmu_op(opcode,extra);\n");
9411 +static void generate_includes (FILE * f)
9413 + fprintf (f, "#include \"sysconfig.h\"\n");
9414 + fprintf (f, "#include \"sysdeps.h\"\n");
9415 + fprintf (f, "#include \"config.h\"\n");
9416 + fprintf (f, "#include \"options.h\"\n");
9417 + fprintf (f, "#include \"memory.h\"\n");
9418 + fprintf (f, "#include \"custom.h\"\n");
9419 + fprintf (f, "#include \"newcpu.h\"\n");
9420 + fprintf (f, "#include \"compiler.h\"\n");
9421 + fprintf (f, "#include \"cputbl.h\"\n");
9423 + fprintf (f, "#define CPUFUNC(x) x##_ff\n"
9424 + "#ifdef NOFLAGS\n"
9425 + "#include \"noflags.h\"\n"
9429 +static int postfix;
9431 +static void generate_one_opcode (int rp)
9434 + uae_u16 smsk, dmsk;
9435 + long int opcode = opcode_map[rp];
9437 + if (table68k[opcode].mnemo == i_ILLG
9438 + || table68k[opcode].clev > cpu_level)
9441 + for (i = 0; lookuptab[i].name[0]; i++) {
9442 + if (table68k[opcode].mnemo == lookuptab[i].mnemo)
9446 + if (table68k[opcode].handler != -1)
9449 + if (opcode_next_clev[rp] != cpu_level) {
9450 + fprintf (stblfile, "{ CPUFUNC(op_%lx_%d), 0, %ld }, /* %s */\n", opcode, opcode_last_postfix[rp],
9451 + opcode, lookuptab[i].name);
9454 + fprintf (stblfile, "{ CPUFUNC(op_%lx_%d), 0, %ld }, /* %s */\n", opcode, postfix, opcode, lookuptab[i].name);
9455 + fprintf (headerfile, "extern cpuop_func op_%lx_%d_nf;\n", opcode, postfix);
9456 + fprintf (headerfile, "extern cpuop_func op_%lx_%d_ff;\n", opcode, postfix);
9457 + printf ("unsigned long REGPARAM2 CPUFUNC(op_%lx_%d)(uae_u32 opcode) /* %s */\n{\n", opcode, postfix, lookuptab[i].name);
9459 + switch (table68k[opcode].stype) {
9460 + case 0: smsk = 7; break;
9461 + case 1: smsk = 255; break;
9462 + case 2: smsk = 15; break;
9463 + case 3: smsk = 7; break;
9464 + case 4: smsk = 7; break;
9465 + case 5: smsk = 63; break;
9466 + case 7: smsk = 3; break;
9467 + default: abort ();
9471 + next_cpu_level = -1;
9472 + if (table68k[opcode].suse
9473 + && table68k[opcode].smode != imm && table68k[opcode].smode != imm0
9474 + && table68k[opcode].smode != imm1 && table68k[opcode].smode != imm2
9475 + && table68k[opcode].smode != absw && table68k[opcode].smode != absl
9476 + && table68k[opcode].smode != PC8r && table68k[opcode].smode != PC16)
9478 + if (table68k[opcode].spos == -1) {
9479 + if (((int) table68k[opcode].sreg) >= 128)
9480 + printf ("\tuae_u32 srcreg = (uae_s32)(uae_s8)%d;\n", (int) table68k[opcode].sreg);
9482 + printf ("\tuae_u32 srcreg = %d;\n", (int) table68k[opcode].sreg);
9485 + int pos = table68k[opcode].spos;
9488 + sprintf (source, "((opcode >> %d) & %d)", pos, smsk);
9490 + sprintf (source, "(opcode & %d)", smsk);
9492 + if (table68k[opcode].stype == 3)
9493 + printf ("\tuae_u32 srcreg = imm8_table[%s];\n", source);
9494 + else if (table68k[opcode].stype == 1)
9495 + printf ("\tuae_u32 srcreg = (uae_s32)(uae_s8)%s;\n", source);
9497 + printf ("\tuae_u32 srcreg = %s;\n", source);
9500 + if (table68k[opcode].duse
9501 + /* Yes, the dmode can be imm, in case of LINK or DBcc */
9502 + && table68k[opcode].dmode != imm && table68k[opcode].dmode != imm0
9503 + && table68k[opcode].dmode != imm1 && table68k[opcode].dmode != imm2
9504 + && table68k[opcode].dmode != absw && table68k[opcode].dmode != absl)
9506 + if (table68k[opcode].dpos == -1) {
9507 + if (((int) table68k[opcode].dreg) >= 128)
9508 + printf ("\tuae_u32 dstreg = (uae_s32)(uae_s8)%d;\n", (int) table68k[opcode].dreg);
9510 + printf ("\tuae_u32 dstreg = %d;\n", (int) table68k[opcode].dreg);
9512 + int pos = table68k[opcode].dpos;
9514 + /* Check that we can do the little endian optimization safely. */
9515 + if (pos < 8 && (dmsk >> (8 - pos)) != 0)
9519 + printf ("\tuae_u32 dstreg = (opcode >> %d) & %d;\n",
9522 + printf ("\tuae_u32 dstreg = opcode & %d;\n", dmsk);
9525 + need_endlabel = 0;
9527 + sprintf (endlabelstr, "endlabel%d", endlabelno);
9528 + gen_opcode (opcode);
9529 + if (need_endlabel)
9530 + printf ("%s: ;\n", endlabelstr);
9531 + printf ("return %d;\n", insn_n_cycles * CYCLE_UNIT / 2);
9533 + opcode_next_clev[rp] = next_cpu_level;
9534 + opcode_last_postfix[rp] = postfix;
9537 +static void generate_func (void)
9541 + using_prefetch = 0;
9542 + using_exception_3 = 0;
9545 + for (i = 0; i < 6; i++) {
9546 + cpu_level = 4 - i;
9547 + using_mmu = cpu_level == 4;
9550 + using_prefetch = 1;
9551 + using_exception_3 = 1;
9552 + for (rp = 0; rp < nr_cpuop_funcs; rp++)
9553 + opcode_next_clev[rp] = 0;
9557 + fprintf (stblfile, "struct cputbl CPUFUNC(op_smalltbl_%d)[] = {\n", postfix);
9559 + /* sam: this is for people with low memory (eg. me :)) */
9561 + "#if !defined(PART_1) && !defined(PART_2) && "
9562 + "!defined(PART_3) && !defined(PART_4) && "
9563 + "!defined(PART_5) && !defined(PART_6) && "
9564 + "!defined(PART_7) && !defined(PART_8)"
9566 + "#define PART_1 1\n"
9567 + "#define PART_2 1\n"
9568 + "#define PART_3 1\n"
9569 + "#define PART_4 1\n"
9570 + "#define PART_5 1\n"
9571 + "#define PART_6 1\n"
9572 + "#define PART_7 1\n"
9573 + "#define PART_8 1\n"
9577 + for(j=1;j<=8;++j) {
9578 + int k = (j*nr_cpuop_funcs)/8;
9579 + printf ("#ifdef PART_%d\n",j);
9580 + for (; rp < k; rp++)
9581 + generate_one_opcode (rp);
9582 + printf ("#endif\n\n");
9585 + fprintf (stblfile, "{ 0, 0, 0 }};\n");
9590 +int main (int argc, char **argv)
9595 + opcode_map = (int *) xmalloc (sizeof (int) * nr_cpuop_funcs);
9596 + opcode_last_postfix = (int *) xmalloc (sizeof (int) * nr_cpuop_funcs);
9597 + opcode_next_clev = (int *) xmalloc (sizeof (int) * nr_cpuop_funcs);
9598 + counts = (unsigned long *) xmalloc (65536 * sizeof (unsigned long));
9601 + /* It would be a lot nicer to put all in one file (we'd also get rid of
9602 + * cputbl.h that way), but cpuopti can't cope. That could be fixed, but
9603 + * I don't dare to touch the 68k version. */
9605 + headerfile = fopen ("cputbl.h", "wb");
9606 + stblfile = fopen ("cpustbl.c", "wb");
9607 + freopen ("cpuemu.c", "wb", stdout);
9609 + generate_includes (stdout);
9610 + generate_includes (stblfile);
9617 diff -urN src-0.8.22/src/include/memory.h src-0.8.22-mmu/src/include/memory.h
9618 --- src-0.8.22/src/include/memory.h 2001-11-19 18:52:21.000000000 +0100
9619 +++ src-0.8.22-mmu/src/include/memory.h 2003-07-25 12:25:56.000000000 +0200
9625 STATIC_INLINE uae_u32 get_long(uaecptr addr)
9627 return longget_1(addr);
9628 @@ -173,13 +174,14 @@
9634 -STATIC_INLINE uae_u8 *get_real_address(uaecptr addr)
9635 +STATIC_INLINE uae_u8 *phys_get_real_address(uaecptr addr)
9637 return get_mem_bank(addr).xlateaddr(addr);
9640 -STATIC_INLINE int valid_address(uaecptr addr, uae_u32 size)
9641 +STATIC_INLINE int phys_valid_address(uaecptr addr, uae_u32 size)
9643 return get_mem_bank(addr).check(addr, size);
9645 diff -urN src-0.8.22/src/include/memory.h~ src-0.8.22-mmu/src/include/memory.h~
9646 --- src-0.8.22/src/include/memory.h~ 1970-01-01 01:00:00.000000000 +0100
9647 +++ src-0.8.22-mmu/src/include/memory.h~ 2003-07-25 12:11:11.000000000 +0200
9650 + * UAE - The Un*x Amiga Emulator
9652 + * memory management
9654 + * Copyright 1995 Bernd Schmidt
9658 +extern void memory_reset (void);
9660 +extern int special_mem;
9664 +typedef uae_u32 (*mem_get_func)(uaecptr) REGPARAM;
9665 +typedef void (*mem_put_func)(uaecptr, uae_u32) REGPARAM;
9666 +typedef uae_u8 *(*xlate_func)(uaecptr) REGPARAM;
9667 +typedef int (*check_func)(uaecptr, uae_u32) REGPARAM;
9669 +extern char *address_space, *good_address_map;
9670 +extern uae_u8 *chipmemory;
9672 +extern uae_u32 allocated_chipmem;
9673 +extern uae_u32 allocated_fastmem;
9674 +extern uae_u32 allocated_bogomem;
9675 +extern uae_u32 allocated_gfxmem;
9676 +extern uae_u32 allocated_z3fastmem;
9677 +extern uae_u32 allocated_a3000mem;
9679 +#undef DIRECT_MEMFUNCS_SUCCESSFUL
9680 +#include "machdep/maccess.h"
9682 +#ifndef CAN_MAP_MEMORY
9683 +#undef USE_COMPILER
9686 +#if defined(USE_COMPILER) && !defined(USE_MAPPED_MEMORY)
9687 +#define USE_MAPPED_MEMORY
9690 +#define kickmem_size 0x080000
9692 +#define chipmem_start 0x00000000
9693 +#define bogomem_start 0x00C00000
9694 +#define a3000mem_start 0x07000000
9695 +#define kickmem_start 0x00F80000
9697 +extern int ersatzkickfile;
9698 +extern int cloanto_rom;
9700 +extern uae_u8* baseaddr[];
9703 + /* These ones should be self-explanatory... */
9704 + mem_get_func lget, wget, bget;
9705 + mem_put_func lput, wput, bput;
9706 + /* Use xlateaddr to translate an Amiga address to a uae_u8 * that can
9707 + * be used to address memory without calling the wget/wput functions.
9708 + * This doesn't work for all memory banks, so this function may call
9710 + xlate_func xlateaddr;
9711 + /* To prevent calls to abort(), use check before calling xlateaddr.
9712 + * It checks not only that the memory bank can do xlateaddr, but also
9713 + * that the pointer points to an area of at least the specified size.
9714 + * This is used for example to translate bitplane pointers in custom.c */
9716 + /* For those banks that refer to real memory, we can save the whole trouble
9717 + of going through function calls, and instead simply grab the memory
9718 + ourselves. This holds the memory address where the start of memory is
9719 + for this particular bank. */
9723 +extern uae_u8 *filesysory;
9724 +extern uae_u8 *rtarea;
9726 +extern addrbank chipmem_bank;
9727 +extern addrbank kickmem_bank;
9728 +extern addrbank custom_bank;
9729 +extern addrbank clock_bank;
9730 +extern addrbank cia_bank;
9731 +extern addrbank rtarea_bank;
9732 +extern addrbank expamem_bank;
9733 +extern addrbank fastmem_bank;
9734 +extern addrbank gfxmem_bank;
9736 +extern void rtarea_init (void);
9737 +extern void rtarea_setup (void);
9738 +extern void expamem_init (void);
9739 +extern void expamem_reset (void);
9741 +extern uae_u32 gfxmem_start;
9742 +extern uae_u8 *gfxmemory;
9743 +extern uae_u32 gfxmem_mask;
9744 +extern int address_space_24;
9746 +/* Default memory access functions */
9748 +extern int default_check(uaecptr addr, uae_u32 size) REGPARAM;
9749 +extern uae_u8 *default_xlate(uaecptr addr) REGPARAM;
9751 +#define bankindex(addr) (((uaecptr)(addr)) >> 16)
9753 +extern addrbank *mem_banks[65536];
9754 +extern uae_u8 *baseaddr[65536];
9755 +#define get_mem_bank(addr) (*mem_banks[bankindex(addr)])
9756 +#define put_mem_bank(addr, b, realstart) do { \
9757 + (mem_banks[bankindex(addr)] = (b)); \
9758 + if ((b)->baseaddr) \
9759 + baseaddr[bankindex(addr)] = (b)->baseaddr - (realstart); \
9761 + baseaddr[bankindex(addr)] = (uae_u8*)(((long)b)+1); \
9764 +extern void memory_init (void);
9765 +extern void memory_cleanup (void);
9766 +extern void map_banks (addrbank *bank, int first, int count, int realsize);
9768 +#ifndef NO_INLINE_MEMORY_ACCESS
9770 +#define longget(addr) (call_mem_get_func(get_mem_bank(addr).lget, addr))
9771 +#define wordget(addr) (call_mem_get_func(get_mem_bank(addr).wget, addr))
9772 +#define byteget(addr) (call_mem_get_func(get_mem_bank(addr).bget, addr))
9773 +#define longput(addr,l) (call_mem_put_func(get_mem_bank(addr).lput, addr, l))
9774 +#define wordput(addr,w) (call_mem_put_func(get_mem_bank(addr).wput, addr, w))
9775 +#define byteput(addr,b) (call_mem_put_func(get_mem_bank(addr).bput, addr, b))
9779 +extern uae_u32 alongget(uaecptr addr);
9780 +extern uae_u32 awordget(uaecptr addr);
9781 +extern uae_u32 longget(uaecptr addr);
9782 +extern uae_u32 wordget(uaecptr addr);
9783 +extern uae_u32 byteget(uaecptr addr);
9784 +extern void longput(uaecptr addr, uae_u32 l);
9785 +extern void wordput(uaecptr addr, uae_u32 w);
9786 +extern void byteput(uaecptr addr, uae_u32 b);
9791 +#ifndef MD_HAVE_MEM_1_FUNCS
9793 +#define longget_1 longget
9794 +#define wordget_1 wordget
9795 +#define byteget_1 byteget
9796 +#define longput_1 longput
9797 +#define wordput_1 wordput
9798 +#define byteput_1 byteput
9803 +STATIC_INLINE uae_u32 get_long(uaecptr addr)
9805 + return longget_1(addr);
9807 +STATIC_INLINE uae_u32 get_word(uaecptr addr)
9809 + return wordget_1(addr);
9811 +STATIC_INLINE uae_u32 get_byte(uaecptr addr)
9813 + return byteget_1(addr);
9815 +STATIC_INLINE void put_long(uaecptr addr, uae_u32 l)
9817 + longput_1(addr, l);
9819 +STATIC_INLINE void put_word(uaecptr addr, uae_u32 w)
9821 + wordput_1(addr, w);
9823 +STATIC_INLINE void put_byte(uaecptr addr, uae_u32 b)
9825 + byteput_1(addr, b);
9829 +STATIC_INLINE uae_u8 *phys_get_real_address(uaecptr addr)
9831 + return get_mem_bank(addr).xlateaddr(addr);
9834 +STATIC_INLINE int phys_valid_address(uaecptr addr, uae_u32 size)
9836 + return get_mem_bank(addr).check(addr, size);
9840 +/* For faster access in custom chip emulation. */
9841 +extern uae_u32 chipmem_lget (uaecptr) REGPARAM;
9842 +extern uae_u32 chipmem_wget (uaecptr) REGPARAM;
9843 +extern uae_u32 chipmem_bget (uaecptr) REGPARAM;
9844 +extern void chipmem_lput (uaecptr, uae_u32) REGPARAM;
9845 +extern void chipmem_wput (uaecptr, uae_u32) REGPARAM;
9846 +extern void chipmem_bput (uaecptr, uae_u32) REGPARAM;
9848 +#ifdef NATMEM_OFFSET
9850 +typedef struct shmpiece_reg {
9851 + uae_u8 *native_address;
9854 + struct shmpiece_reg *next;
9855 + struct shmpiece_reg *prev;
9858 +extern shmpiece *shm_start;
9859 +extern int canbang;
9863 +extern uae_u8 *mapped_malloc (size_t, char *);
9864 +extern void mapped_free (uae_u8 *);
9865 diff -urN src-0.8.22/src/include/mmu.h src-0.8.22-mmu/src/include/mmu.h
9866 --- src-0.8.22/src/include/mmu.h 1970-01-01 01:00:00.000000000 +0100
9867 +++ src-0.8.22-mmu/src/include/mmu.h 2003-07-25 12:38:43.000000000 +0200
9870 +#define MMU_TEST_PTEST 1
9871 +#define MMU_TEST_VERBOSE 2
9872 +#define MMU_TEST_FORCE_TABLE_SEARCH 4
9873 +#define MMU_TEST_NO_BUSERR 8
9875 +#define HAVE_MMU (currprefs.cpu_level == 4)
9877 +extern void mmu_dump_tables(void);
9879 +#define MMU_PAGE_8KB 1
9880 +#define MMU_PAGE_4KB 0
9882 +#define MMU_TTR_LOGICAL_BASE 0xff000000
9883 +#define MMU_TTR_LOGICAL_MASK 0x00ff0000
9884 +#define MMU_TTR_BIT_ENABLED (1 << 15)
9885 +#define MMU_TTR_BIT_SFIELD_ENABLED (1 << 14)
9886 +#define MMU_TTR_BIT_SFIELD_SUPER (1 << 13)
9887 +#define MMU_TTR_SFIELD_SHIFT 13
9888 +#define MMU_TTR_UX_MASK ((1 << 9) | (1 << 8))
9889 +#define MMU_TTR_UX_SHIFT 8
9890 +#define MMU_TTR_CACHE_MASK ((1 << 6) | (1 << 5))
9891 +#define MMU_TTR_CACHE_SHIFT 5
9892 +#define MMU_TTR_BIT_WRITE_PROTECT (1 << 2)
9894 +#define MMU_UDT_MASK 3
9895 +#define MMU_PDT_MASK 3
9897 +#define MMU_DES_WP 4
9898 +#define MMU_DES_USED 8
9900 +/* page descriptors only */
9901 +#define MMU_DES_MODIFIED 16
9902 +#define MMU_DES_SUPER (1 << 7)
9903 +#define MMU_DES_GLOBAL (1 << 10)
9905 +#define MMU_ROOT_PTR_ADDR_MASK 0xfffffe00
9906 +#define MMU_PTR_PAGE_ADDR_MASK_8 0xffffff80
9907 +#define MMU_PTR_PAGE_ADDR_MASK_4 0xffffff00
9909 +#define MMU_PAGE_INDIRECT_MASK 0xfffffffc
9910 +#define MMU_PAGE_ADDR_MASK_8 0xffffe000
9911 +#define MMU_PAGE_ADDR_MASK_4 0xfffff000
9912 +#define MMU_PAGE_UR_MASK_8 ((1 << 12) | (1 << 11))
9913 +#define MMU_PAGE_UR_MASK_4 (1 << 11)
9914 +#define MMU_PAGE_UR_SHIFT 11
9916 +#define MMU_MMUSR_ADDR_MASK 0xfffff000
9917 +#define MMU_MMUSR_B (1 << 11)
9918 +#define MMU_MMUSR_G (1 << 10)
9919 +#define MMU_MMUSR_U1 (1 << 9)
9920 +#define MMU_MMUSR_U0 (1 << 8)
9921 +#define MMU_MMUSR_S (1 << 7)
9922 +#define MMU_MMUSR_CM (1 << 6) | ( 1 << 5)
9923 +#define MMU_MMUSR_M (1 << 4)
9924 +#define MMU_MMUSR_W (1 << 2)
9925 +#define MMU_MMUSR_R (1 << 1)
9926 +#define MMU_MMUSR_T (1 << 0)
9928 +struct mmu_atc_line {
9929 + int v, umode, g, s, cm, m, w, r, fc2;
9930 + uaecptr phys, log;
9933 +extern struct mmu_atc_line atc[64];
9940 +#define TTR_NO_MATCH 0
9941 +#define TTR_NO_WRITE 1
9942 +#define TTR_OK_MATCH 2
9944 +STATIC_INLINE void mmu_set_tc(uae_u16 tc)
9946 + extern void activate_debugger (void);
9949 + if (currprefs.cpu_level >= 4)
9955 + m68k_disasm(stdout, m68k_getpc(), &nextpc, 10);
9959 + regs.mmu_enabled = tc & 0x8000 ? 1 : 0;
9960 + regs.mmu_pagesize = tc & 0x4000 ? MMU_PAGE_8KB : MMU_PAGE_4KB;
9962 + write_log("MMU: enabled=%d page=%d\n", regs.mmu_enabled, regs.mmu_pagesize);
9969 +extern void mmu_make_transparent_region(uaecptr baseaddr, uae_u32 size, int datamode);
9971 +STATIC_INLINE void mmu_set_ttr(int regno, uae_u32 val)
9975 + case TTR_I0: ttr = ®s.itt0; break;
9976 + case TTR_I1: ttr = ®s.itt1; break;
9977 + case TTR_D0: ttr = ®s.dtt0; break;
9978 + case TTR_D1: ttr = ®s.dtt1; break;
9984 +STATIC_INLINE void mmu_set_mmusr(uae_u32 val)
9989 +STATIC_INLINE void mmu_set_root_pointer(int regno, uae_u32 val)
9993 + case 0x806: rp = ®s.urp; break;
9994 + case 0x807: rp = ®s.srp; break;
10001 +/* MMU related stuff */
10003 +#if 0 /* later, for speedup */
10004 +extern uae_u32 (*log_get_long)(uaecptr addr);
10005 +extern void (*log_put_long)(uaecptr addr, uae_u32 l);
10006 +extern uae_u16 (*log_get_word)(uaecptr addr);
10007 +extern void (*log_put_word)(uaecptr addr, uae_u16 w);
10008 +extern uae_u8 (*log_get_byte)(uaecptr addr);
10009 +extern void (*log_put_byte)(uaecptr addr, uae_u8 b);
10012 +#define phys_get_long(addr) longget_1(addr)
10013 +#define phys_get_word(addr) wordget_1(addr)
10014 +#define phys_get_byte(addr) byteget_1(addr)
10015 +#define phys_put_long(addr,l) longput_1(addr,l)
10016 +#define phys_put_word(addr,w) wordput_1(addr,w)
10017 +#define phys_put_byte(addr,b) byteput_1(addr,b)
10019 +STATIC_INLINE uae_u32 get_long(uaecptr addr)
10021 + return phys_get_long(HAVE_MMU ?
10022 + mmu_translate(addr, FC_DATA, 0, m68k_getpc(), sz_long, 0)
10025 +STATIC_INLINE uae_u16 get_word(uaecptr addr)
10027 + return phys_get_word(HAVE_MMU ?
10028 + mmu_translate(addr, FC_DATA, 0, m68k_getpc(), sz_word, 0)
10031 +STATIC_INLINE uae_u8 get_byte(uaecptr addr)
10033 + return phys_get_byte(HAVE_MMU ?
10034 + mmu_translate(addr, FC_DATA, 0, m68k_getpc(), sz_byte, 0)
10038 +STATIC_INLINE void put_long(uaecptr addr, uae_u32 l)
10040 + phys_put_long(HAVE_MMU ?
10041 + mmu_translate(addr, FC_DATA, 1, m68k_getpc(), sz_long, 0)
10045 +STATIC_INLINE void put_word(uaecptr addr, uae_u16 w)
10047 + phys_put_word(HAVE_MMU ?
10048 + mmu_translate(addr, FC_DATA, 1, m68k_getpc(), sz_word, 0)
10052 +STATIC_INLINE void put_byte(uaecptr addr, uae_u16 b)
10054 + phys_put_byte(HAVE_MMU ?
10055 + mmu_translate(addr, FC_DATA, 1, m68k_getpc(), sz_byte, 0)
10060 +STATIC_INLINE uae_u8 *get_real_address(uaecptr addr)
10062 + return phys_get_real_address(HAVE_MMU ? mmu_translate(addr, FC_DATA, 0, 0, sz_byte, 0) : addr);
10065 +STATIC_INLINE int valid_address(uaecptr addr, uae_u32 size)
10067 + return phys_valid_address(HAVE_MMU ? mmu_translate(addr, FC_DATA, 0, 0, sz_byte, 0) : addr, size);
10071 +STATIC_INLINE uae_u32 sfc_get_long(uaecptr addr)
10073 + return phys_get_long(HAVE_MMU ?
10074 + mmu_translate(addr, regs.sfc, 0, m68k_getpc(), sz_long, 0)
10077 +STATIC_INLINE uae_u16 sfc_get_word(uaecptr addr)
10079 + return phys_get_word(HAVE_MMU ?
10080 + mmu_translate(addr, regs.sfc, 0, m68k_getpc(), sz_word, 0)
10083 +STATIC_INLINE uae_u8 sfc_get_byte(uaecptr addr)
10085 + return phys_get_byte(HAVE_MMU ?
10086 + mmu_translate(addr, regs.sfc, 0, m68k_getpc(), sz_byte, 0)
10091 +STATIC_INLINE void dfc_put_long(uaecptr addr, uae_u32 l)
10093 + phys_put_long(HAVE_MMU ?
10094 + mmu_translate(addr, regs.dfc, 1, m68k_getpc(), sz_long, 0)
10098 +STATIC_INLINE void dfc_put_word(uaecptr addr, uae_u16 w)
10100 + phys_put_word(HAVE_MMU ?
10101 + mmu_translate(addr, regs.dfc, 1, m68k_getpc(), sz_word, 0)
10105 +STATIC_INLINE void dfc_put_byte(uaecptr addr, uae_u16 b)
10107 + phys_put_byte(HAVE_MMU ?
10108 + mmu_translate(addr, regs.dfc, 1, m68k_getpc(), sz_byte, 0)
10114 diff -urN src-0.8.22/src/include/newcpu.h src-0.8.22-mmu/src/include/newcpu.h
10115 --- src-0.8.22/src/include/newcpu.h 2001-12-17 19:38:38.000000000 +0100
10116 +++ src-0.8.22-mmu/src/include/newcpu.h 2003-07-25 12:29:03.000000000 +0200
10119 #include "readcpu.h"
10120 #include "machdep/m68k.h"
10121 +#include <setjmp.h>
10125 @@ -99,6 +100,12 @@
10127 uae_u32 prefetch_pc;
10130 + uae_u32 caar, cacr, itt0, itt1, dtt0, dtt1, tc, mmusr, urp, srp;
10132 + int mmu_enabled, mmu_pagesize;
10133 + uae_u32 mmu_fslw, mmu_fault_addr;
10135 } regs, lastint_regs;
10137 STATIC_INLINE void set_special (uae_u32 x)
10138 @@ -114,6 +121,37 @@
10139 #define m68k_dreg(r,num) ((r).regs[(num)])
10140 #define m68k_areg(r,num) (((r).regs + 8)[(num)])
10142 +STATIC_INLINE uaecptr m68k_getpc (void)
10144 + return regs.pc + ((char *)regs.pc_p - (char *)regs.pc_oldp);
10147 +STATIC_INLINE uaecptr m68k_getpc_p (uae_u8 *p)
10149 + return regs.pc + ((char *)p - (char *)regs.pc_oldp);
10153 +extern void Exception (int, uaecptr);
10154 +extern jmp_buf m68k_exception;
10155 +extern int in_exception_2;
10156 +extern void m68k_dumpstate (FILE *, uaecptr *);
10157 +extern void m68k_disasm (FILE *, uaecptr, uaecptr *, int);
10159 +/* function codes for mmu_translation */
10161 +#define FC_DATA regs.s ? 5 : 1
10162 +#define FC_INST regs.s ? 6 : 2
10164 +extern uaecptr mmu_translate(uaecptr addr,
10168 + int size, /* sz_xxx */
10173 #if !defined USE_COMPILER
10174 STATIC_INLINE void m68k_setpc (uaecptr newpc)
10176 @@ -124,19 +162,64 @@
10177 extern void m68k_setpc (uaecptr newpc);
10180 -STATIC_INLINE uaecptr m68k_getpc (void)
10183 +#define get_ibyte(o) do_get_mem_byte((uae_u8 *)(regs.pc_p + (o) + 1))
10184 +#define get_iword(o) do_get_mem_word((uae_u16 *)(regs.pc_p + (o)))
10185 +#define get_ilong(o) do_get_mem_long((uae_u32 *)(regs.pc_p + (o)))
10188 +STATIC_INLINE uae_u8 get_ibyte(uae_u32 o)
10190 - return regs.pc + ((char *)regs.pc_p - (char *)regs.pc_oldp);
10192 + uaecptr addr = m68k_getpc() + o + 1;
10193 + return phys_get_byte(mmu_translate(addr, FC_INST, 0, addr, sz_byte, 0));
10195 + return do_get_mem_byte((uae_u8 *)(regs.pc_p + (o) + 1));
10197 +STATIC_INLINE uae_u16 get_iword(uae_u32 o)
10200 + uaecptr addr = m68k_getpc() + o;
10201 + return phys_get_word(mmu_translate(addr, FC_INST, 0, addr, sz_word, 0));
10203 + return do_get_mem_word((uae_u16 *)(regs.pc_p + (o)));
10205 +STATIC_INLINE uae_u32 get_ilong(uae_u32 o)
10208 + uaecptr addr = m68k_getpc() + o;
10209 + return phys_get_long(mmu_translate(addr, FC_INST, 0, addr, sz_long, 0));
10211 + return do_get_mem_long((uae_u32 *)(regs.pc_p + (o)));
10214 -STATIC_INLINE uaecptr m68k_getpc_p (uae_u8 *p)
10216 +STATIC_INLINE uae_u8 get_ibyte_1(uae_u32 o)
10218 - return regs.pc + ((char *)p - (char *)regs.pc_oldp);
10220 + uaecptr addr = m68k_getpc() + o + 1;
10221 + return phys_get_byte(mmu_translate(addr, FC_INST, 0, addr, sz_byte, 0));
10223 + return byteget_1(regs.pc + (regs.pc_p - regs.pc_oldp) + (o) + 1);
10225 +STATIC_INLINE uae_u16 get_iword_1(uae_u32 o)
10228 + uaecptr addr = m68k_getpc() + o;
10229 + return phys_get_word(mmu_translate(addr, FC_INST, 0, addr, sz_word, 0));
10231 + return wordget_1(regs.pc + (regs.pc_p - regs.pc_oldp) + (o));
10234 -#define get_ibyte(o) do_get_mem_byte((uae_u8 *)(regs.pc_p + (o) + 1))
10235 -#define get_iword(o) do_get_mem_word((uae_u16 *)(regs.pc_p + (o)))
10236 -#define get_ilong(o) do_get_mem_long((uae_u32 *)(regs.pc_p + (o)))
10237 +STATIC_INLINE uae_u32 get_ilong_1(uae_u32 o)
10240 + uaecptr addr = m68k_getpc() + o;
10241 + return phys_get_long(mmu_translate(addr, FC_INST, 0, addr, sz_long, 0));
10243 + return longget_1(regs.pc + (regs.pc_p - regs.pc_oldp) + (o));
10246 STATIC_INLINE void refill_prefetch (uae_u32 currpc, uae_u32 offs)
10248 @@ -144,6 +227,16 @@
10249 uae_s32 pc_p_offs = t - currpc;
10250 uae_u8 *ptr = regs.pc_p + pc_p_offs;
10253 + regs.prefetch_pc = t;
10256 + t = mmu_translate(t, FC_INST, 0, t, sz_long, 0);
10257 + r = phys_get_long(t);
10258 + do_put_mem_long(®s.prefetch, r);
10262 #ifdef UNALIGNED_PROFITABLE
10263 r = *(uae_u32 *)ptr;
10265 @@ -152,7 +245,6 @@
10266 do_put_mem_long (®s.prefetch, r);
10268 /* printf ("PC %lx T %lx PCPOFFS %d R %lx\n", currpc, t, pc_p_offs, r); */
10269 - regs.prefetch_pc = t;
10272 STATIC_INLINE uae_u32 get_ibyte_prefetch (uae_s32 o)
10273 @@ -184,7 +276,7 @@
10274 v = do_get_mem_word ((uae_u16 *)(((uae_u8 *)®s.prefetch) + offs));
10276 refill_prefetch (currpc, 4);
10277 - /* printf ("get_iword PC %lx ADDR %lx OFFS %lx V %lx\n", currpc, addr, offs, v); */
10278 +/* printf ("get_iword_prefetch PC %lx ADDR %lx OFFS %lx V %lx\n", currpc, addr, offs, v); */
10281 STATIC_INLINE uae_u32 get_ilong_prefetch (uae_s32 o)
10282 @@ -252,7 +344,6 @@
10284 extern void MakeSR (void);
10285 extern void MakeFromSR (void);
10286 -extern void Exception (int, uaecptr);
10287 extern void dump_counts (void);
10288 extern int m68k_move2c (int, uae_u32 *);
10289 extern int m68k_movec2 (int, uae_u32 *);
10290 @@ -260,8 +351,6 @@
10291 extern void m68k_mull (uae_u32, uae_u32, uae_u16);
10292 extern void init_m68k (void);
10293 extern void m68k_go (int);
10294 -extern void m68k_dumpstate (FILE *, uaecptr *);
10295 -extern void m68k_disasm (FILE *, uaecptr, uaecptr *, int);
10296 extern void m68k_reset (void);
10298 extern void mmu_op (uae_u32, uae_u16);
10299 diff -urN src-0.8.22/src/include/newcpu.h~ src-0.8.22-mmu/src/include/newcpu.h~
10300 --- src-0.8.22/src/include/newcpu.h~ 1970-01-01 01:00:00.000000000 +0100
10301 +++ src-0.8.22-mmu/src/include/newcpu.h~ 2003-07-25 12:11:11.000000000 +0200
10304 + * UAE - The Un*x Amiga Emulator
10306 + * MC68000 emulation
10308 + * Copyright 1995 Bernd Schmidt
10311 +#include "readcpu.h"
10312 +#include "machdep/m68k.h"
10313 +#include <setjmp.h>
10317 +#define SET_CFLG(x) (CFLG = (x))
10318 +#define SET_NFLG(x) (NFLG = (x))
10319 +#define SET_VFLG(x) (VFLG = (x))
10320 +#define SET_ZFLG(x) (ZFLG = (x))
10321 +#define SET_XFLG(x) (XFLG = (x))
10323 +#define GET_CFLG CFLG
10324 +#define GET_NFLG NFLG
10325 +#define GET_VFLG VFLG
10326 +#define GET_ZFLG ZFLG
10327 +#define GET_XFLG XFLG
10329 +#define CLEAR_CZNV do { \
10336 +#define COPY_CARRY (SET_XFLG (GET_CFLG))
10339 +extern int areg_byteinc[];
10340 +extern int imm8_table[];
10342 +extern int movem_index1[256];
10343 +extern int movem_index2[256];
10344 +extern int movem_next[256];
10346 +extern int fpp_movem_index1[256];
10347 +extern int fpp_movem_index2[256];
10348 +extern int fpp_movem_next[256];
10350 +extern int broken_in;
10352 +typedef unsigned long cpuop_func (uae_u32) REGPARAM;
10355 + cpuop_func *handler;
10360 +extern unsigned long op_illg (uae_u32) REGPARAM;
10362 +typedef char flagtype;
10364 +/* You can set this to long double to be more accurate. However, the
10365 + resulting alignment issues will cost a lot of performance in some
10367 +#define USE_LONG_DOUBLE 0
10369 +#if USE_LONG_DOUBLE
10370 +typedef long double fptype;
10372 +typedef double fptype;
10375 +extern struct regstruct
10377 + uae_u32 regs[16];
10378 + uaecptr usp,isp,msp;
10385 + flagtype stopped;
10392 + uae_u32 vbr,sfc,dfc;
10395 + fptype fp_result;
10397 + uae_u32 fpcr,fpsr,fpiar;
10398 + uae_u32 fpsr_highbyte;
10400 + uae_u32 spcflags;
10401 + uae_u32 kick_mask;
10403 + uae_u32 prefetch_pc;
10404 + uae_u32 prefetch;
10406 + uae_u32 caar, cacr, itt0, itt1, dtt0, dtt1, tc, mmusr, urp, srp;
10408 + int mmu_enabled, mmu_pagesize;
10409 + uae_u32 mmu_fslw, mmu_fault_addr;
10411 +} regs, lastint_regs;
10413 +STATIC_INLINE void set_special (uae_u32 x)
10415 + regs.spcflags |= x;
10418 +STATIC_INLINE void unset_special (uae_u32 x)
10420 + regs.spcflags &= ~x;
10423 +#define m68k_dreg(r,num) ((r).regs[(num)])
10424 +#define m68k_areg(r,num) (((r).regs + 8)[(num)])
10426 +STATIC_INLINE uaecptr m68k_getpc (void)
10428 + return regs.pc + ((char *)regs.pc_p - (char *)regs.pc_oldp);
10431 +STATIC_INLINE uaecptr m68k_getpc_p (uae_u8 *p)
10433 + return regs.pc + ((char *)p - (char *)regs.pc_oldp);
10437 +extern void Exception (int, uaecptr);
10438 +extern jmp_buf m68k_exception;
10439 +extern int in_exception_2;
10440 +extern void m68k_dumpstate (FILE *, uaecptr *);
10441 +extern void m68k_disasm (FILE *, uaecptr, uaecptr *, int);
10443 +/* function codes for mmu_translation */
10445 +#define FC_DATA regs.s ? 5 : 1
10446 +#define FC_INST regs.s ? 6 : 2
10448 +extern uaecptr mmu_translate(uaecptr addr,
10452 + int size, /* sz_xxx */
10457 +#if !defined USE_COMPILER
10458 +STATIC_INLINE void m68k_setpc (uaecptr newpc)
10460 + regs.pc_p = regs.pc_oldp = get_real_address (newpc);
10464 +extern void m68k_setpc (uaecptr newpc);
10469 +#define get_ibyte(o) do_get_mem_byte((uae_u8 *)(regs.pc_p + (o) + 1))
10470 +#define get_iword(o) do_get_mem_word((uae_u16 *)(regs.pc_p + (o)))
10471 +#define get_ilong(o) do_get_mem_long((uae_u32 *)(regs.pc_p + (o)))
10474 +STATIC_INLINE uae_u8 get_ibyte(uae_u32 o)
10477 + uaecptr addr = m68k_getpc() + o + 1;
10478 + return phys_get_byte(mmu_translate(addr, FC_INST, 0, addr, sz_byte, 0));
10480 + return do_get_mem_byte((uae_u8 *)(regs.pc_p + (o) + 1));
10482 +STATIC_INLINE uae_u16 get_iword(uae_u32 o)
10485 + uaecptr addr = m68k_getpc() + o;
10486 + return phys_get_word(mmu_translate(addr, FC_INST, 0, addr, sz_word, 0));
10488 + return do_get_mem_word((uae_u16 *)(regs.pc_p + (o)));
10490 +STATIC_INLINE uae_u32 get_ilong(uae_u32 o)
10493 + uaecptr addr = m68k_getpc() + o;
10494 + return phys_get_long(mmu_translate(addr, FC_INST, 0, addr, sz_long, 0));
10496 + return do_get_mem_long((uae_u32 *)(regs.pc_p + (o)));
10500 +STATIC_INLINE uae_u8 get_ibyte_1(uae_u32 o)
10503 + uaecptr addr = m68k_getpc() + o + 1;
10504 + return phys_get_byte(mmu_translate(addr, FC_INST, 0, addr, sz_byte, 0));
10506 + return byteget_1(regs.pc + (regs.pc_p - regs.pc_oldp) + (o) + 1);
10508 +STATIC_INLINE uae_u16 get_iword_1(uae_u32 o)
10511 + uaecptr addr = m68k_getpc() + o;
10512 + return phys_get_word(mmu_translate(addr, FC_INST, 0, addr, sz_word, 0));
10514 + return wordget_1(regs.pc + (regs.pc_p - regs.pc_oldp) + (o));
10517 +STATIC_INLINE uae_u32 get_ilong_1(uae_u32 o)
10520 + uaecptr addr = m68k_getpc() + o;
10521 + return phys_get_long(mmu_translate(addr, FC_INST, 0, addr, sz_long, 0));
10523 + return longget_1(regs.pc + (regs.pc_p - regs.pc_oldp) + (o));
10529 +STATIC_INLINE void refill_prefetch (uae_u32 currpc, uae_u32 offs)
10531 + uae_u32 t = (currpc + offs) & ~3;
10532 + uae_s32 pc_p_offs = t - currpc;
10533 + uae_u8 *ptr = regs.pc_p + pc_p_offs;
10536 + regs.prefetch_pc = t;
10539 + t = mmu_translate(t, FC_INST, 0, t, sz_long, 0);
10540 + r = phys_get_long(t);
10541 + do_put_mem_long(®s.prefetch, r);
10545 +#ifdef UNALIGNED_PROFITABLE
10546 + r = *(uae_u32 *)ptr;
10547 + regs.prefetch = r;
10549 + r = do_get_mem_long ((uae_u32 *)ptr);
10550 + do_put_mem_long (®s.prefetch, r);
10552 + /* printf ("PC %lx T %lx PCPOFFS %d R %lx\n", currpc, t, pc_p_offs, r); */
10555 +STATIC_INLINE uae_u32 get_ibyte_prefetch (uae_s32 o)
10557 + uae_u32 currpc = m68k_getpc ();
10558 + uae_u32 addr = currpc + o + 1;
10559 + uae_u32 offs = addr - regs.prefetch_pc;
10562 + refill_prefetch (currpc, o + 1);
10563 + offs = addr - regs.prefetch_pc;
10565 + v = do_get_mem_byte (((uae_u8 *)®s.prefetch) + offs);
10567 + refill_prefetch (currpc, 4);
10568 + /* printf ("get_ibyte PC %lx ADDR %lx OFFS %lx V %lx\n", currpc, addr, offs, v); */
10571 +STATIC_INLINE uae_u32 get_iword_prefetch (uae_s32 o)
10573 + uae_u32 currpc = m68k_getpc ();
10574 + uae_u32 addr = currpc + o;
10575 + uae_u32 offs = addr - regs.prefetch_pc;
10578 + refill_prefetch (currpc, o);
10579 + offs = addr - regs.prefetch_pc;
10581 + v = do_get_mem_word ((uae_u16 *)(((uae_u8 *)®s.prefetch) + offs));
10583 + refill_prefetch (currpc, 4);
10584 +/* printf ("get_iword_prefetch PC %lx ADDR %lx OFFS %lx V %lx\n", currpc, addr, offs, v); */
10587 +STATIC_INLINE uae_u32 get_ilong_prefetch (uae_s32 o)
10589 + uae_u32 v = get_iword_prefetch (o);
10591 + v |= get_iword_prefetch (o + 2);
10595 +#define m68k_incpc(o) (regs.pc_p += (o))
10597 +STATIC_INLINE void fill_prefetch_0 (void)
10601 +#define fill_prefetch_2 fill_prefetch_0
10603 +/* These are only used by the 68020/68881 code, and therefore don't
10604 + * need to handle prefetch. */
10605 +STATIC_INLINE uae_u32 next_ibyte (void)
10607 + uae_u32 r = get_ibyte (0);
10612 +STATIC_INLINE uae_u32 next_iword (void)
10614 + uae_u32 r = get_iword (0);
10619 +STATIC_INLINE uae_u32 next_ilong (void)
10621 + uae_u32 r = get_ilong (0);
10626 +#ifdef USE_COMPILER
10627 +extern void m68k_setpc_fast (uaecptr newpc);
10628 +extern void m68k_setpc_bcc (uaecptr newpc);
10629 +extern void m68k_setpc_rte (uaecptr newpc);
10631 +#define m68k_setpc_fast m68k_setpc
10632 +#define m68k_setpc_bcc m68k_setpc
10633 +#define m68k_setpc_rte m68k_setpc
10636 +STATIC_INLINE void m68k_setstopped (int stop)
10638 + regs.stopped = stop;
10639 + /* A traced STOP instruction drops through immediately without
10640 + actually stopping. */
10641 + if (stop && (regs.spcflags & SPCFLAG_DOTRACE) == 0)
10642 + regs.spcflags |= SPCFLAG_STOP;
10645 +extern uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp);
10646 +extern uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp);
10648 +extern uae_s32 ShowEA (FILE *, int reg, amodes mode, wordsizes size, char *buf);
10650 +extern void MakeSR (void);
10651 +extern void MakeFromSR (void);
10652 +extern void dump_counts (void);
10653 +extern int m68k_move2c (int, uae_u32 *);
10654 +extern int m68k_movec2 (int, uae_u32 *);
10655 +extern void m68k_divl (uae_u32, uae_u32, uae_u16, uaecptr);
10656 +extern void m68k_mull (uae_u32, uae_u32, uae_u16);
10657 +extern void init_m68k (void);
10658 +extern void m68k_go (int);
10659 +extern void m68k_reset (void);
10661 +extern void mmu_op (uae_u32, uae_u16);
10663 +extern void fpp_opp (uae_u32, uae_u16);
10664 +extern void fdbcc_opp (uae_u32, uae_u16);
10665 +extern void fscc_opp (uae_u32, uae_u16);
10666 +extern void ftrapcc_opp (uae_u32,uaecptr);
10667 +extern void fbcc_opp (uae_u32, uaecptr, uae_u32);
10668 +extern void fsave_opp (uae_u32);
10669 +extern void frestore_opp (uae_u32);
10671 +/* Opcode of faulting instruction */
10672 +extern uae_u16 last_op_for_exception_3;
10673 +/* PC at fault time */
10674 +extern uaecptr last_addr_for_exception_3;
10675 +/* Address that generated the exception */
10676 +extern uaecptr last_fault_for_exception_3;
10678 +#define CPU_OP_NAME(a) op ## a
10681 +extern struct cputbl op_smalltbl_0_ff[];
10682 +/* 68020 + 68881 */
10683 +extern struct cputbl op_smalltbl_1_ff[];
10685 +extern struct cputbl op_smalltbl_2_ff[];
10687 +extern struct cputbl op_smalltbl_3_ff[];
10689 +extern struct cputbl op_smalltbl_4_ff[];
10690 +/* 68000 slow but compatible. */
10691 +extern struct cputbl op_smalltbl_5_ff[];
10693 +extern cpuop_func *cpufunctbl[65536] ASM_SYM_FOR_FUNC ("cpufunctbl");
10697 +#define flush_icache(X) do {} while (0)
10702 diff -urN src-0.8.22/src/memory.c src-0.8.22-mmu/src/memory.c
10703 --- src-0.8.22/src/memory.c 2002-02-16 15:29:42.000000000 +0100
10704 +++ src-0.8.22-mmu/src/memory.c 2003-07-25 12:11:11.000000000 +0200
10705 @@ -686,9 +686,10 @@
10707 uae_u8 REGPARAM2 *default_xlate (uaecptr a)
10709 - write_log ("Your Amiga program just did something terribly stupid\n");
10711 - return kickmem_xlate (get_long (0xF80000)); /* So we don't crash. */
10712 + write_log ("Your Amiga program just did something terribly stupid"
10713 + "(xlate of %lx)\n", a);
10715 + longjmp(m68k_exception, 0);
10718 /* Address banks */
10719 diff -urN src-0.8.22/src/memory.c~ src-0.8.22-mmu/src/memory.c~
10720 --- src-0.8.22/src/memory.c~ 1970-01-01 01:00:00.000000000 +0100
10721 +++ src-0.8.22-mmu/src/memory.c~ 2003-07-25 12:08:14.000000000 +0200
10724 + * UAE - The Un*x Amiga Emulator
10726 + * Memory management
10728 + * (c) 1995 Bernd Schmidt
10731 +#include "sysconfig.h"
10732 +#include "sysdeps.h"
10734 +#include "config.h"
10735 +#include "options.h"
10737 +#include "memory.h"
10738 +#include "ersatz.h"
10739 +#include "zfile.h"
10740 +#include "custom.h"
10741 +#include "events.h"
10742 +#include "newcpu.h"
10743 +#include "autoconf.h"
10744 +#include "savestate.h"
10746 +#ifdef USE_MAPPED_MEMORY
10747 +#include <sys/mman.h>
10750 +/* Set by each memory handler that does not simply access real memory. */
10753 +int ersatzkickfile = 0;
10755 +uae_u32 allocated_chipmem;
10756 +uae_u32 allocated_fastmem;
10757 +uae_u32 allocated_bogomem;
10758 +uae_u32 allocated_gfxmem;
10759 +uae_u32 allocated_z3fastmem;
10760 +uae_u32 allocated_a3000mem;
10762 +static long chip_filepos;
10763 +static long bogo_filepos;
10764 +static long rom_filepos;
10766 +addrbank *mem_banks[65536];
10768 +/* This has two functions. It either holds a host address that, when added
10769 + to the 68k address, gives the host address corresponding to that 68k
10770 + address (in which case the value in this array is even), OR it holds the
10771 + same value as mem_banks, for those banks that have baseaddr==0. In that
10772 + case, bit 0 is set (the memory access routines will take care of it). */
10774 +uae_u8 *baseaddr[65536];
10776 +#ifdef NO_INLINE_MEMORY_ACCESS
10777 +__inline__ uae_u32 longget (uaecptr addr)
10779 + return call_mem_get_func (get_mem_bank (addr).lget, addr);
10781 +__inline__ uae_u32 wordget (uaecptr addr)
10783 + return call_mem_get_func (get_mem_bank (addr).wget, addr);
10785 +__inline__ uae_u32 byteget (uaecptr addr)
10787 + return call_mem_get_func (get_mem_bank (addr).bget, addr);
10789 +__inline__ void longput (uaecptr addr, uae_u32 l)
10791 + call_mem_put_func (get_mem_bank (addr).lput, addr, l);
10793 +__inline__ void wordput (uaecptr addr, uae_u32 w)
10795 + call_mem_put_func (get_mem_bank (addr).wput, addr, w);
10797 +__inline__ void byteput (uaecptr addr, uae_u32 b)
10799 + call_mem_put_func (get_mem_bank (addr).bput, addr, b);
10803 +uae_u32 chipmem_mask, kickmem_mask, extendedkickmem_mask, bogomem_mask, a3000mem_mask;
10805 +static int illegal_count;
10806 +/* A dummy bank that only contains zeros */
10808 +static uae_u32 dummy_lget (uaecptr) REGPARAM;
10809 +static uae_u32 dummy_wget (uaecptr) REGPARAM;
10810 +static uae_u32 dummy_bget (uaecptr) REGPARAM;
10811 +static void dummy_lput (uaecptr, uae_u32) REGPARAM;
10812 +static void dummy_wput (uaecptr, uae_u32) REGPARAM;
10813 +static void dummy_bput (uaecptr, uae_u32) REGPARAM;
10814 +static int dummy_check (uaecptr addr, uae_u32 size) REGPARAM;
10816 +uae_u32 REGPARAM2 dummy_lget (uaecptr addr)
10818 + special_mem |= S_READ;
10819 + if (currprefs.illegal_mem) {
10820 + if (illegal_count < 20) {
10822 + write_log ("Illegal lget at %08lx\n", addr);
10826 + return 0xFFFFFFFF;
10829 +uae_u32 REGPARAM2 dummy_wget (uaecptr addr)
10831 + special_mem |= S_READ;
10832 + if (currprefs.illegal_mem) {
10833 + if (illegal_count < 20) {
10835 + write_log ("Illegal wget at %08lx\n", addr);
10842 +uae_u32 REGPARAM2 dummy_bget (uaecptr addr)
10844 + special_mem |= S_READ;
10845 + if (currprefs.illegal_mem) {
10846 + if (illegal_count < 20) {
10848 + write_log ("Illegal bget at %08lx\n", addr);
10855 +void REGPARAM2 dummy_lput (uaecptr addr, uae_u32 l)
10857 + special_mem |= S_WRITE;
10858 + if (currprefs.illegal_mem) {
10859 + if (illegal_count < 20) {
10861 + write_log ("Illegal lput at %08lx\n", addr);
10865 +void REGPARAM2 dummy_wput (uaecptr addr, uae_u32 w)
10867 + special_mem |= S_WRITE;
10868 + if (currprefs.illegal_mem) {
10869 + if (illegal_count < 20) {
10871 + write_log ("Illegal wput at %08lx\n", addr);
10875 +void REGPARAM2 dummy_bput (uaecptr addr, uae_u32 b)
10877 + special_mem |= S_WRITE;
10878 + if (currprefs.illegal_mem) {
10879 + if (illegal_count < 20) {
10881 + write_log ("Illegal bput at %08lx\n", addr);
10886 +int REGPARAM2 dummy_check (uaecptr addr, uae_u32 size)
10888 + special_mem |= S_READ;
10889 + if (currprefs.illegal_mem) {
10890 + if (illegal_count < 20) {
10892 + write_log ("Illegal check at %08lx\n", addr);
10899 +/* A3000 "motherboard resources" bank. */
10900 +static uae_u32 mbres_lget (uaecptr) REGPARAM;
10901 +static uae_u32 mbres_wget (uaecptr) REGPARAM;
10902 +static uae_u32 mbres_bget (uaecptr) REGPARAM;
10903 +static void mbres_lput (uaecptr, uae_u32) REGPARAM;
10904 +static void mbres_wput (uaecptr, uae_u32) REGPARAM;
10905 +static void mbres_bput (uaecptr, uae_u32) REGPARAM;
10906 +static int mbres_check (uaecptr addr, uae_u32 size) REGPARAM;
10908 +static int mbres_val = 0;
10910 +uae_u32 REGPARAM2 mbres_lget (uaecptr addr)
10912 + special_mem |= S_READ;
10913 + if (currprefs.illegal_mem)
10914 + write_log ("Illegal lget at %08lx\n", addr);
10919 +uae_u32 REGPARAM2 mbres_wget (uaecptr addr)
10921 + special_mem |= S_READ;
10922 + if (currprefs.illegal_mem)
10923 + write_log ("Illegal wget at %08lx\n", addr);
10928 +uae_u32 REGPARAM2 mbres_bget (uaecptr addr)
10930 + special_mem |= S_READ;
10931 + if (currprefs.illegal_mem)
10932 + write_log ("Illegal bget at %08lx\n", addr);
10934 + return (addr & 0xFFFF) == 3 ? mbres_val : 0;
10937 +void REGPARAM2 mbres_lput (uaecptr addr, uae_u32 l)
10939 + special_mem |= S_WRITE;
10940 + if (currprefs.illegal_mem)
10941 + write_log ("Illegal lput at %08lx\n", addr);
10943 +void REGPARAM2 mbres_wput (uaecptr addr, uae_u32 w)
10945 + special_mem |= S_WRITE;
10946 + if (currprefs.illegal_mem)
10947 + write_log ("Illegal wput at %08lx\n", addr);
10949 +void REGPARAM2 mbres_bput (uaecptr addr, uae_u32 b)
10951 + special_mem |= S_WRITE;
10952 + if (currprefs.illegal_mem)
10953 + write_log ("Illegal bput at %08lx\n", addr);
10955 + if ((addr & 0xFFFF) == 3)
10959 +int REGPARAM2 mbres_check (uaecptr addr, uae_u32 size)
10961 + if (currprefs.illegal_mem)
10962 + write_log ("Illegal check at %08lx\n", addr);
10969 +uae_u8 *chipmemory;
10971 +static int chipmem_check (uaecptr addr, uae_u32 size) REGPARAM;
10972 +static uae_u8 *chipmem_xlate (uaecptr addr) REGPARAM;
10974 +uae_u32 REGPARAM2 chipmem_lget (uaecptr addr)
10978 + addr -= chipmem_start & chipmem_mask;
10979 + addr &= chipmem_mask;
10980 + m = (uae_u32 *)(chipmemory + addr);
10981 + return do_get_mem_long (m);
10984 +uae_u32 REGPARAM2 chipmem_wget (uaecptr addr)
10988 + addr -= chipmem_start & chipmem_mask;
10989 + addr &= chipmem_mask;
10990 + m = (uae_u16 *)(chipmemory + addr);
10991 + return do_get_mem_word (m);
10994 +uae_u32 REGPARAM2 chipmem_bget (uaecptr addr)
10996 + addr -= chipmem_start & chipmem_mask;
10997 + addr &= chipmem_mask;
10998 + return chipmemory[addr];
11001 +void REGPARAM2 chipmem_lput (uaecptr addr, uae_u32 l)
11005 + addr -= chipmem_start & chipmem_mask;
11006 + addr &= chipmem_mask;
11007 + m = (uae_u32 *)(chipmemory + addr);
11008 + do_put_mem_long (m, l);
11011 +void REGPARAM2 chipmem_wput (uaecptr addr, uae_u32 w)
11015 + addr -= chipmem_start & chipmem_mask;
11016 + addr &= chipmem_mask;
11017 + m = (uae_u16 *)(chipmemory + addr);
11018 + do_put_mem_word (m, w);
11021 +void REGPARAM2 chipmem_bput (uaecptr addr, uae_u32 b)
11023 + addr -= chipmem_start & chipmem_mask;
11024 + addr &= chipmem_mask;
11025 + chipmemory[addr] = b;
11028 +int REGPARAM2 chipmem_check (uaecptr addr, uae_u32 size)
11030 + addr -= chipmem_start & chipmem_mask;
11031 + addr &= chipmem_mask;
11032 + return (addr + size) <= allocated_chipmem;
11035 +uae_u8 REGPARAM2 *chipmem_xlate (uaecptr addr)
11037 + addr -= chipmem_start & chipmem_mask;
11038 + addr &= chipmem_mask;
11039 + return chipmemory + addr;
11044 +static uae_u8 *bogomemory;
11046 +static uae_u32 bogomem_lget (uaecptr) REGPARAM;
11047 +static uae_u32 bogomem_wget (uaecptr) REGPARAM;
11048 +static uae_u32 bogomem_bget (uaecptr) REGPARAM;
11049 +static void bogomem_lput (uaecptr, uae_u32) REGPARAM;
11050 +static void bogomem_wput (uaecptr, uae_u32) REGPARAM;
11051 +static void bogomem_bput (uaecptr, uae_u32) REGPARAM;
11052 +static int bogomem_check (uaecptr addr, uae_u32 size) REGPARAM;
11053 +static uae_u8 *bogomem_xlate (uaecptr addr) REGPARAM;
11055 +uae_u32 REGPARAM2 bogomem_lget (uaecptr addr)
11058 + addr -= bogomem_start & bogomem_mask;
11059 + addr &= bogomem_mask;
11060 + m = (uae_u32 *)(bogomemory + addr);
11061 + return do_get_mem_long (m);
11064 +uae_u32 REGPARAM2 bogomem_wget (uaecptr addr)
11067 + addr -= bogomem_start & bogomem_mask;
11068 + addr &= bogomem_mask;
11069 + m = (uae_u16 *)(bogomemory + addr);
11070 + return do_get_mem_word (m);
11073 +uae_u32 REGPARAM2 bogomem_bget (uaecptr addr)
11075 + addr -= bogomem_start & bogomem_mask;
11076 + addr &= bogomem_mask;
11077 + return bogomemory[addr];
11080 +void REGPARAM2 bogomem_lput (uaecptr addr, uae_u32 l)
11083 + addr -= bogomem_start & bogomem_mask;
11084 + addr &= bogomem_mask;
11085 + m = (uae_u32 *)(bogomemory + addr);
11086 + do_put_mem_long (m, l);
11089 +void REGPARAM2 bogomem_wput (uaecptr addr, uae_u32 w)
11092 + addr -= bogomem_start & bogomem_mask;
11093 + addr &= bogomem_mask;
11094 + m = (uae_u16 *)(bogomemory + addr);
11095 + do_put_mem_word (m, w);
11098 +void REGPARAM2 bogomem_bput (uaecptr addr, uae_u32 b)
11100 + addr -= bogomem_start & bogomem_mask;
11101 + addr &= bogomem_mask;
11102 + bogomemory[addr] = b;
11105 +int REGPARAM2 bogomem_check (uaecptr addr, uae_u32 size)
11107 + addr -= bogomem_start & bogomem_mask;
11108 + addr &= bogomem_mask;
11109 + return (addr + size) <= allocated_bogomem;
11112 +uae_u8 REGPARAM2 *bogomem_xlate (uaecptr addr)
11114 + addr -= bogomem_start & bogomem_mask;
11115 + addr &= bogomem_mask;
11116 + return bogomemory + addr;
11119 +/* A3000 motherboard fast memory */
11121 +static uae_u8 *a3000memory;
11123 +static uae_u32 a3000mem_lget (uaecptr) REGPARAM;
11124 +static uae_u32 a3000mem_wget (uaecptr) REGPARAM;
11125 +static uae_u32 a3000mem_bget (uaecptr) REGPARAM;
11126 +static void a3000mem_lput (uaecptr, uae_u32) REGPARAM;
11127 +static void a3000mem_wput (uaecptr, uae_u32) REGPARAM;
11128 +static void a3000mem_bput (uaecptr, uae_u32) REGPARAM;
11129 +static int a3000mem_check (uaecptr addr, uae_u32 size) REGPARAM;
11130 +static uae_u8 *a3000mem_xlate (uaecptr addr) REGPARAM;
11132 +uae_u32 REGPARAM2 a3000mem_lget (uaecptr addr)
11135 + addr -= a3000mem_start & a3000mem_mask;
11136 + addr &= a3000mem_mask;
11137 + m = (uae_u32 *)(a3000memory + addr);
11138 + return do_get_mem_long (m);
11141 +uae_u32 REGPARAM2 a3000mem_wget (uaecptr addr)
11144 + addr -= a3000mem_start & a3000mem_mask;
11145 + addr &= a3000mem_mask;
11146 + m = (uae_u16 *)(a3000memory + addr);
11147 + return do_get_mem_word (m);
11150 +uae_u32 REGPARAM2 a3000mem_bget (uaecptr addr)
11152 + addr -= a3000mem_start & a3000mem_mask;
11153 + addr &= a3000mem_mask;
11154 + return a3000memory[addr];
11157 +void REGPARAM2 a3000mem_lput (uaecptr addr, uae_u32 l)
11160 + addr -= a3000mem_start & a3000mem_mask;
11161 + addr &= a3000mem_mask;
11162 + m = (uae_u32 *)(a3000memory + addr);
11163 + do_put_mem_long (m, l);
11166 +void REGPARAM2 a3000mem_wput (uaecptr addr, uae_u32 w)
11169 + addr -= a3000mem_start & a3000mem_mask;
11170 + addr &= a3000mem_mask;
11171 + m = (uae_u16 *)(a3000memory + addr);
11172 + do_put_mem_word (m, w);
11175 +void REGPARAM2 a3000mem_bput (uaecptr addr, uae_u32 b)
11177 + addr -= a3000mem_start & a3000mem_mask;
11178 + addr &= a3000mem_mask;
11179 + a3000memory[addr] = b;
11182 +int REGPARAM2 a3000mem_check (uaecptr addr, uae_u32 size)
11184 + addr -= a3000mem_start & a3000mem_mask;
11185 + addr &= a3000mem_mask;
11186 + return (addr + size) <= allocated_a3000mem;
11189 +uae_u8 REGPARAM2 *a3000mem_xlate (uaecptr addr)
11191 + addr -= a3000mem_start & a3000mem_mask;
11192 + addr &= a3000mem_mask;
11193 + return a3000memory + addr;
11198 +uae_u8 *kickmemory;
11201 + * A1000 kickstart RAM handling
11203 + * RESET instruction unhides boot ROM and disables write protection
11204 + * write access to boot ROM hides boot ROM and enables write protection
11207 +static int a1000_kickstart_mode;
11208 +static uae_u8 *a1000_bootrom;
11209 +static void a1000_handle_kickstart (int mode)
11212 + a1000_kickstart_mode = 0;
11213 + memcpy (kickmemory, kickmemory + 262144, 262144);
11215 + a1000_kickstart_mode = 1;
11216 + memset (kickmemory, 0, 262144);
11217 + memcpy (kickmemory, a1000_bootrom, 8192);
11218 + memcpy (kickmemory + 131072, a1000_bootrom, 8192);
11222 +static uae_u32 kickmem_lget (uaecptr) REGPARAM;
11223 +static uae_u32 kickmem_wget (uaecptr) REGPARAM;
11224 +static uae_u32 kickmem_bget (uaecptr) REGPARAM;
11225 +static void kickmem_lput (uaecptr, uae_u32) REGPARAM;
11226 +static void kickmem_wput (uaecptr, uae_u32) REGPARAM;
11227 +static void kickmem_bput (uaecptr, uae_u32) REGPARAM;
11228 +static int kickmem_check (uaecptr addr, uae_u32 size) REGPARAM;
11229 +static uae_u8 *kickmem_xlate (uaecptr addr) REGPARAM;
11231 +uae_u32 REGPARAM2 kickmem_lget (uaecptr addr)
11234 + addr -= kickmem_start & kickmem_mask;
11235 + addr &= kickmem_mask;
11236 + m = (uae_u32 *)(kickmemory + addr);
11237 + return do_get_mem_long (m);
11240 +uae_u32 REGPARAM2 kickmem_wget (uaecptr addr)
11243 + addr -= kickmem_start & kickmem_mask;
11244 + addr &= kickmem_mask;
11245 + m = (uae_u16 *)(kickmemory + addr);
11246 + return do_get_mem_word (m);
11249 +uae_u32 REGPARAM2 kickmem_bget (uaecptr addr)
11251 + addr -= kickmem_start & kickmem_mask;
11252 + addr &= kickmem_mask;
11253 + return kickmemory[addr];
11256 +void REGPARAM2 kickmem_lput (uaecptr addr, uae_u32 b)
11259 + if (a1000_kickstart_mode) {
11260 + if (addr >= 0xfc0000) {
11261 + addr -= kickmem_start & kickmem_mask;
11262 + addr &= kickmem_mask;
11263 + m = (uae_u32 *)(kickmemory + addr);
11264 + do_put_mem_long (m, b);
11267 + a1000_handle_kickstart (0);
11268 + } else if (currprefs.illegal_mem)
11269 + write_log ("Illegal kickmem lput at %08lx\n", addr);
11272 +void REGPARAM2 kickmem_wput (uaecptr addr, uae_u32 b)
11275 + if (a1000_kickstart_mode) {
11276 + if (addr >= 0xfc0000) {
11277 + addr -= kickmem_start & kickmem_mask;
11278 + addr &= kickmem_mask;
11279 + m = (uae_u16 *)(kickmemory + addr);
11280 + do_put_mem_word (m, b);
11283 + a1000_handle_kickstart (0);
11284 + } else if (currprefs.illegal_mem)
11285 + write_log ("Illegal kickmem wput at %08lx\n", addr);
11288 +void REGPARAM2 kickmem_bput (uaecptr addr, uae_u32 b)
11290 + if (a1000_kickstart_mode) {
11291 + if (addr >= 0xfc0000) {
11292 + addr -= kickmem_start & kickmem_mask;
11293 + addr &= kickmem_mask;
11294 + kickmemory[addr] = b;
11297 + a1000_handle_kickstart (0);
11298 + } else if (currprefs.illegal_mem)
11299 + write_log ("Illegal kickmem lput at %08lx\n", addr);
11302 +int REGPARAM2 kickmem_check (uaecptr addr, uae_u32 size)
11304 + addr -= kickmem_start & kickmem_mask;
11305 + addr &= kickmem_mask;
11306 + return (addr + size) <= kickmem_size;
11309 +uae_u8 REGPARAM2 *kickmem_xlate (uaecptr addr)
11311 + addr -= kickmem_start & kickmem_mask;
11312 + addr &= kickmem_mask;
11313 + return kickmemory + addr;
11316 +/* CD32/CDTV extended kick memory */
11318 +uae_u8 *extendedkickmemory;
11319 +static int extendedkickmem_size;
11320 +static uae_u32 extendedkickmem_start;
11322 +#define EXTENDED_ROM_CD32 1
11323 +#define EXTENDED_ROM_CDTV 2
11325 +static int extromtype (void)
11327 + switch (extendedkickmem_size) {
11329 + return EXTENDED_ROM_CD32;
11331 + return EXTENDED_ROM_CDTV;
11336 +static uae_u32 extendedkickmem_lget (uaecptr) REGPARAM;
11337 +static uae_u32 extendedkickmem_wget (uaecptr) REGPARAM;
11338 +static uae_u32 extendedkickmem_bget (uaecptr) REGPARAM;
11339 +static void extendedkickmem_lput (uaecptr, uae_u32) REGPARAM;
11340 +static void extendedkickmem_wput (uaecptr, uae_u32) REGPARAM;
11341 +static void extendedkickmem_bput (uaecptr, uae_u32) REGPARAM;
11342 +static int extendedkickmem_check (uaecptr addr, uae_u32 size) REGPARAM;
11343 +static uae_u8 *extendedkickmem_xlate (uaecptr addr) REGPARAM;
11345 +uae_u32 REGPARAM2 extendedkickmem_lget (uaecptr addr)
11348 + addr -= extendedkickmem_start & extendedkickmem_mask;
11349 + addr &= extendedkickmem_mask;
11350 + m = (uae_u32 *)(extendedkickmemory + addr);
11351 + return do_get_mem_long (m);
11354 +uae_u32 REGPARAM2 extendedkickmem_wget (uaecptr addr)
11357 + addr -= extendedkickmem_start & extendedkickmem_mask;
11358 + addr &= extendedkickmem_mask;
11359 + m = (uae_u16 *)(extendedkickmemory + addr);
11360 + return do_get_mem_word (m);
11363 +uae_u32 REGPARAM2 extendedkickmem_bget (uaecptr addr)
11365 + addr -= extendedkickmem_start & extendedkickmem_mask;
11366 + addr &= extendedkickmem_mask;
11367 + return extendedkickmemory[addr];
11370 +void REGPARAM2 extendedkickmem_lput (uaecptr addr, uae_u32 b)
11372 + if (currprefs.illegal_mem)
11373 + write_log ("Illegal extendedkickmem lput at %08lx\n", addr);
11376 +void REGPARAM2 extendedkickmem_wput (uaecptr addr, uae_u32 b)
11378 + if (currprefs.illegal_mem)
11379 + write_log ("Illegal extendedkickmem wput at %08lx\n", addr);
11382 +void REGPARAM2 extendedkickmem_bput (uaecptr addr, uae_u32 b)
11384 + if (currprefs.illegal_mem)
11385 + write_log ("Illegal extendedkickmem lput at %08lx\n", addr);
11388 +int REGPARAM2 extendedkickmem_check (uaecptr addr, uae_u32 size)
11390 + addr -= extendedkickmem_start & extendedkickmem_mask;
11391 + addr &= extendedkickmem_mask;
11392 + return (addr + size) <= extendedkickmem_size;
11395 +uae_u8 REGPARAM2 *extendedkickmem_xlate (uaecptr addr)
11397 + addr -= extendedkickmem_start & extendedkickmem_mask;
11398 + addr &= extendedkickmem_mask;
11399 + return extendedkickmemory + addr;
11402 +/* Default memory access functions */
11404 +int REGPARAM2 default_check (uaecptr a, uae_u32 b)
11409 +uae_u8 REGPARAM2 *default_xlate (uaecptr a)
11411 + write_log ("Your Amiga program just did something terribly stupid\n");
11413 + return kickmem_xlate (get_long (0xF80000)); /* So we don't crash. */
11416 +/* Address banks */
11418 +addrbank dummy_bank = {
11419 + dummy_lget, dummy_wget, dummy_bget,
11420 + dummy_lput, dummy_wput, dummy_bput,
11421 + default_xlate, dummy_check, NULL
11424 +addrbank mbres_bank = {
11425 + mbres_lget, mbres_wget, mbres_bget,
11426 + mbres_lput, mbres_wput, mbres_bput,
11427 + default_xlate, mbres_check, NULL
11430 +addrbank chipmem_bank = {
11431 + chipmem_lget, chipmem_wget, chipmem_bget,
11432 + chipmem_lput, chipmem_wput, chipmem_bput,
11433 + chipmem_xlate, chipmem_check, NULL
11436 +addrbank bogomem_bank = {
11437 + bogomem_lget, bogomem_wget, bogomem_bget,
11438 + bogomem_lput, bogomem_wput, bogomem_bput,
11439 + bogomem_xlate, bogomem_check, NULL
11442 +addrbank a3000mem_bank = {
11443 + a3000mem_lget, a3000mem_wget, a3000mem_bget,
11444 + a3000mem_lput, a3000mem_wput, a3000mem_bput,
11445 + a3000mem_xlate, a3000mem_check, NULL
11448 +addrbank kickmem_bank = {
11449 + kickmem_lget, kickmem_wget, kickmem_bget,
11450 + kickmem_lput, kickmem_wput, kickmem_bput,
11451 + kickmem_xlate, kickmem_check, NULL
11454 +addrbank extendedkickmem_bank = {
11455 + extendedkickmem_lget, extendedkickmem_wget, extendedkickmem_bget,
11456 + extendedkickmem_lput, extendedkickmem_wput, extendedkickmem_bput,
11457 + extendedkickmem_xlate, extendedkickmem_check, NULL
11460 +static int decode_cloanto_rom (uae_u8 *mem, int size, int real_size)
11467 + if (strlen (currprefs.keyfile) == 0) {
11468 + write_log ("No filename given for ROM key file and ROM image is an encrypted \"Amiga Forever\" ROM file.\n");
11471 + keyf = zfile_open (currprefs.keyfile, "rb");
11473 + write_log ("Could not find specified ROM key-file.\n");
11477 + p = (uae_u8 *) xmalloc (524288);
11478 + keysize = fread (p, 1, 524288, keyf);
11479 + for (t = cnt = 0; cnt < size; cnt++, t = (t + 1) % keysize) {
11480 + mem[cnt] ^= p[t];
11481 + if (real_size == cnt + 1)
11489 +static int kickstart_checksum (uae_u8 *mem, int size)
11491 + uae_u32 cksum = 0, prevck = 0;
11493 + for (i = 0; i < size; i += 4) {
11494 + uae_u32 data = mem[i] * 65536 * 256 + mem[i + 1] * 65536 + mem[i + 2] * 256 + mem[i + 3];
11496 + if (cksum < prevck)
11500 + if (cksum != 0xFFFFFFFFul) {
11501 + write_log ("Kickstart checksum incorrect. You probably have a corrupted ROM image.\n");
11506 +static int read_kickstart (FILE *f, uae_u8 *mem, int size, int dochecksum, int *cloanto_rom)
11508 + unsigned char buffer[20];
11512 + *cloanto_rom = 0;
11513 + i = fread (buffer, 1, 11, f);
11514 + if (strncmp ((char *) buffer, "AMIROMTYPE1", 11) != 0) {
11515 + fseek (f, 0, SEEK_SET);
11520 + i = fread (mem, 1, size, f);
11522 + a1000_bootrom = malloc (8192);
11523 + memcpy (a1000_bootrom, kickmemory, 8192);
11524 + a1000_handle_kickstart (1);
11525 + } else if (i == size / 2) {
11526 + memcpy (mem + size / 2, mem, i);
11527 + } else if (i != size) {
11528 + write_log ("Error while reading Kickstart.\n");
11535 + decode_cloanto_rom (mem, size, i);
11536 + if (dochecksum && i >= 262144)
11537 + kickstart_checksum (mem, size);
11539 + *cloanto_rom = cr;
11543 +static int load_extendedkickstart (void)
11548 + if (strlen (currprefs.romextfile) == 0)
11550 + f = zfile_open (currprefs.romextfile, "rb");
11552 + write_log ("No extended Kickstart ROM found");
11556 + fseek (f, 0, SEEK_END);
11557 + size = ftell (f);
11558 + if (size > 300000)
11559 + extendedkickmem_size = 524288;
11561 + extendedkickmem_size = 262144;
11562 + fseek (f, 0, SEEK_SET);
11564 + switch (extromtype ()) {
11565 + case EXTENDED_ROM_CDTV:
11566 + extendedkickmemory = (uae_u8 *) mapped_malloc (extendedkickmem_size, "rom_f0");
11567 + extendedkickmem_bank.baseaddr = (uae_u8 *) extendedkickmemory;
11569 + case EXTENDED_ROM_CD32:
11570 + extendedkickmemory = (uae_u8 *) mapped_malloc (extendedkickmem_size, "rom_e0");
11571 + extendedkickmem_bank.baseaddr = (uae_u8 *) extendedkickmemory;
11574 + read_kickstart (f, extendedkickmemory, 524288, 0, 0);
11580 +static int load_kickstart (void)
11582 + FILE *f = zfile_open (currprefs.romfile, "rb");
11585 +#if defined(AMIGA)||defined(__POS__)
11586 +#define USE_UAE_ERSATZ "USE_UAE_ERSATZ"
11587 + if (!getenv (USE_UAE_ERSATZ)) {
11588 + write_log ("Using current ROM. (create ENV:%s to " "use uae's ROM replacement)\n", USE_UAE_ERSATZ);
11589 + memcpy (kickmemory, (char *) 0x1000000 - kickmem_size, kickmem_size);
11590 + kickstart_checksum (kickmemory, kickmem_size);
11597 + if (!read_kickstart (f, kickmemory, kickmem_size, 1, &cloanto_rom))
11600 +#if defined(AMIGA)
11604 + if (currprefs.kickshifter) {
11605 + /* Patch Kickstart ROM for ShapeShifter - from Christian Bauer.
11606 + Changes 'lea $400,a0' to 'lea $2000,a0' for ShapeShifter compatability.
11607 + NOTE: lea is 0x41f8, so we should do this better with a search for
11608 + 0x41f80400 --> 0x41f82000
11610 + if (kickmemory[0x24a] == 0x04 && kickmemory[0x24b] == 0x00) { /* Kick 3.0 */
11611 + kickmemory[0x24a] = 0x20;
11612 + kickmemory[0x7ffea] -= 0x1c;
11613 + write_log ("Kickstart KickShifted\n");
11614 + } else if (kickmemory[0x26e] == 0x04 && kickmemory[0x26f] == 0x00) { /* Kick 3.1 */
11615 + kickmemory[0x26e] = 0x20;
11616 + kickmemory[0x7ffea] -= 0x1c;
11617 + write_log ("Kickstart KickShifted\n");
11618 + } else if (kickmemory[0x24e] == 0x04 && kickmemory[0x24f] == 0x00) { /* Kick 2.04 */
11619 + kickmemory[0x24e] = 0x20;
11620 + kickmemory[0x7ffea] -= 0x1c;
11621 + write_log ("Kickstart KickShifted\n");
11627 +char *address_space, *good_address_map;
11628 +int good_address_fd;
11630 +#ifndef NATMEM_OFFSET
11632 +uae_u8 *mapped_malloc (size_t s, char *file)
11634 + return malloc (s);
11637 +void mapped_free (uae_u8 *p)
11643 +#include <sys/ipc.h>
11644 +#include <sys/shm.h>
11645 +#include <unistd.h>
11646 +#include <sys/mman.h>
11648 +shmpiece *shm_start = NULL;
11651 +static void dumplist (void)
11653 + shmpiece *x = shm_start;
11654 + printf ("Start Dump:\n");
11656 + printf (" this=%p, Native %p, id %d, prev=%p, next=%p, size=0x%08x\n",
11657 + x, x->native_address, x->id, x->prev, x->next, x->size);
11660 + printf ("End Dump:\n");
11663 +static shmpiece *find_shmpiece (uae_u8 *base)
11665 + shmpiece *x = shm_start;
11667 + while (x && x->native_address != base)
11670 + printf ("NATMEM: Failure to find mapping at %p\n", base);
11678 +static void delete_shmmaps (uae_u32 start, uae_u32 size)
11684 + uae_u8 *base = mem_banks[bankindex (start)]->baseaddr;
11687 + base = ((uae_u8 *) NATMEM_OFFSET) + start;
11689 + x = find_shmpiece (base);
11693 + if (x->size > size) {
11694 + printf ("NATMEM: Failure to delete mapping at %08x(size %08x, delsize %08x)\n", start, x->size, size);
11699 + shmdt (x->native_address);
11701 + start += x->size;
11703 + x->next->prev = x->prev; /* remove this one from the list */
11705 + x->prev->next = x->next;
11707 + shm_start = x->next;
11711 + start += 0x10000;
11716 +static void add_shmmaps (uae_u32 start, addrbank *what)
11718 + shmpiece *x = shm_start;
11720 + uae_u8 *base = what->baseaddr;
11727 + x = find_shmpiece (base);
11730 + y = malloc (sizeof (shmpiece));
11732 + base = ((uae_u8 *) NATMEM_OFFSET) + start;
11733 + y->native_address = shmat (y->id, base, 0);
11734 + if (y->native_address == (void *) -1) {
11735 + printf ("NATMEM: Failure to map existing at %08x(%p)\n", start, base);
11736 + perror ("shmat");
11741 + y->next = shm_start;
11744 + y->next->prev = y;
11748 +uae_u8 *mapped_malloc (size_t s, char *file)
11755 + return malloc (s);
11757 + id = shmget (IPC_PRIVATE, s, 0x1ff, file);
11760 + return mapped_malloc (s, file);
11762 + answer = shmat (id, 0, 0);
11763 + shmctl (id, IPC_RMID, NULL);
11764 + if (answer != (void *) -1) {
11765 + x = malloc (sizeof (shmpiece));
11766 + x->native_address = answer;
11769 + x->next = shm_start;
11772 + x->next->prev = x;
11778 + return mapped_malloc (s, file);
11781 +void mapped_free (uae_u8 *base)
11783 + shmpiece *x = find_shmpiece (base);
11786 + shmdt (x->native_address);
11791 +static void init_mem_banks (void)
11794 + for (i = 0; i < 65536; i++)
11795 + put_mem_bank (i << 16, &dummy_bank, 0);
11798 +static void allocate_memory (void)
11800 + if (allocated_chipmem != currprefs.chipmem_size) {
11802 + mapped_free (chipmemory);
11805 + allocated_chipmem = currprefs.chipmem_size;
11806 + chipmem_mask = allocated_chipmem - 1;
11808 + chipmemory = mapped_malloc (allocated_chipmem, "chip");
11809 + if (chipmemory == 0) {
11810 + write_log ("Fatal error: out of memory for chipmem.\n");
11811 + allocated_chipmem = 0;
11813 + do_put_mem_long ((uae_u32 *)(chipmemory + 4), 0);
11816 + if (allocated_bogomem != currprefs.bogomem_size) {
11818 + mapped_free (bogomemory);
11821 + allocated_bogomem = currprefs.bogomem_size;
11822 + bogomem_mask = allocated_bogomem - 1;
11824 + if (allocated_bogomem) {
11825 + bogomemory = mapped_malloc (allocated_bogomem, "bogo");
11826 + if (bogomemory == 0) {
11827 + write_log ("Out of memory for bogomem.\n");
11828 + allocated_bogomem = 0;
11832 + if (allocated_a3000mem != currprefs.a3000mem_size) {
11834 + mapped_free (a3000memory);
11837 + allocated_a3000mem = currprefs.a3000mem_size;
11838 + a3000mem_mask = allocated_a3000mem - 1;
11840 + if (allocated_a3000mem) {
11841 + a3000memory = mapped_malloc (allocated_a3000mem, "a3000");
11842 + if (a3000memory == 0) {
11843 + write_log ("Out of memory for a3000mem.\n");
11844 + allocated_a3000mem = 0;
11849 + if (savestate_state == STATE_RESTORE) {
11850 + fseek (savestate_file, chip_filepos, SEEK_SET);
11851 + fread (chipmemory, 1, allocated_chipmem, savestate_file);
11852 + if (allocated_bogomem > 0) {
11853 + fseek (savestate_file, bogo_filepos, SEEK_SET);
11854 + fread (bogomemory, 1, allocated_bogomem, savestate_file);
11857 + chipmem_bank.baseaddr = chipmemory;
11858 + bogomem_bank.baseaddr = bogomemory;
11861 +void memory_reset (void)
11863 + int i, custom_start;
11865 +#ifdef NATMEM_OFFSET
11866 + delete_shmmaps (0, 0xFFFF0000);
11868 + init_mem_banks ();
11870 + currprefs.chipmem_size = changed_prefs.chipmem_size;
11871 + currprefs.bogomem_size = changed_prefs.bogomem_size;
11872 + currprefs.a3000mem_size = changed_prefs.a3000mem_size;
11874 + allocate_memory ();
11876 + if (strcmp (currprefs.romfile, changed_prefs.romfile) != 0 || strcmp (currprefs.keyfile, changed_prefs.keyfile) != 0) {
11877 + ersatzkickfile = 0;
11878 + memcpy (currprefs.romfile, changed_prefs.romfile, sizeof currprefs.romfile);
11879 + memcpy (currprefs.keyfile, changed_prefs.keyfile, sizeof currprefs.keyfile);
11880 + /* Clear out whatever data remains across a reset. */
11881 + memset (chipmemory, 0, allocated_chipmem);
11882 + if (!load_kickstart ()) {
11883 + init_ersatz_rom (kickmemory);
11884 + ersatzkickfile = 1;
11887 + /* Map the chipmem into all of the lower 8MB */
11888 + i = allocated_chipmem > 0x200000 ? (allocated_chipmem >> 16) : 32;
11889 + map_banks (&chipmem_bank, 0x00, i, allocated_chipmem);
11891 + custom_start = 0xC0;
11893 + map_banks (&custom_bank, custom_start, 0xE0 - custom_start, 0);
11894 + map_banks (&cia_bank, 0xA0, 32, 0);
11895 + map_banks (&clock_bank, 0xDC, 1, 0);
11897 + /* @@@ Does anyone have a clue what should be in the 0x200000 - 0xA00000
11898 + * range on an Amiga without expansion memory? */
11899 + custom_start = allocated_chipmem >> 16;
11900 + if (custom_start < 0x20)
11901 + custom_start = 0x20;
11902 + map_banks (&dummy_bank, custom_start, 0xA0 - custom_start, 0);
11903 + /*map_banks (&mbres_bank, 0xDE, 1); */
11905 + if (bogomemory != 0) {
11906 + int t = allocated_bogomem >> 16;
11909 + map_banks (&bogomem_bank, 0xC0, t, allocated_bogomem);
11911 + if (a3000memory != 0)
11912 + map_banks (&a3000mem_bank, a3000mem_start >> 16, allocated_a3000mem >> 16, allocated_a3000mem);
11914 + map_banks (&rtarea_bank, RTAREA_BASE >> 16, 1, 0);
11916 + map_banks (&kickmem_bank, 0xF8, 8, 0);
11917 + if (a1000_bootrom)
11918 + a1000_handle_kickstart (1);
11919 + map_banks (&expamem_bank, 0xE8, 1, 0);
11921 + switch (extromtype ()) {
11922 + case EXTENDED_ROM_CDTV:
11923 + map_banks (&extendedkickmem_bank, 0xF0, 4, 0);
11925 + case EXTENDED_ROM_CD32:
11926 + map_banks (&extendedkickmem_bank, 0xE0, 8, 0);
11930 + map_banks (&kickmem_bank, 0xE0, 8, 0);
11934 +void memory_init (void)
11936 + allocated_chipmem = 0;
11937 + allocated_bogomem = 0;
11938 + allocated_a3000mem = 0;
11940 + extendedkickmemory = 0;
11945 + kickmemory = mapped_malloc (kickmem_size, "kick");
11946 + kickmem_bank.baseaddr = kickmemory;
11948 + load_extendedkickstart ();
11949 + if (!load_kickstart ()) {
11950 + init_ersatz_rom (kickmemory);
11951 + ersatzkickfile = 1;
11954 + init_mem_banks ();
11957 + kickmem_mask = kickmem_size - 1;
11958 + extendedkickmem_mask = extendedkickmem_size - 1;
11961 +void memory_cleanup (void)
11964 + mapped_free (a3000memory);
11966 + mapped_free (bogomemory);
11968 + mapped_free (kickmemory);
11969 + if (a1000_bootrom)
11970 + free (a1000_bootrom);
11972 + mapped_free (chipmemory);
11977 + a1000_bootrom = 0;
11981 +void map_banks (addrbank *bank, int start, int size, int realsize)
11984 + unsigned long int hioffs = 0, endhioffs = 0x100;
11985 + addrbank *orgbank = bank;
11986 + uae_u32 realstart = start;
11988 + flush_icache (1); /* Sure don't want to keep any old mappings around! */
11989 +#ifdef NATMEM_OFFSET
11990 + delete_shmmaps (start << 16, size << 16);
11994 + realsize = size << 16;
11996 + if ((size << 16) < realsize) {
11997 + write_log ("Please report to bmeyer@cs.monash.edu.au, and mention:\n");
11998 + write_log ("Broken mapping, size=%x, realsize=%x\n", size, realsize);
11999 + write_log ("Start is %x\n", start);
12000 + write_log ("Reducing memory sizes, especially chipmem, may fix this problem\n");
12004 + if (start >= 0x100) {
12005 + int real_left = 0;
12006 + for (bnr = start; bnr < start + size; bnr++) {
12007 + if (!real_left) {
12009 + real_left = realsize >> 16;
12010 +#ifdef NATMEM_OFFSET
12011 + add_shmmaps (realstart << 16, bank);
12014 + put_mem_bank (bnr << 16, bank, realstart << 16);
12019 + if (currprefs.address_space_24)
12020 + endhioffs = 0x10000;
12021 + for (hioffs = 0; hioffs < endhioffs; hioffs += 0x100) {
12022 + int real_left = 0;
12023 + for (bnr = start; bnr < start + size; bnr++) {
12024 + if (!real_left) {
12025 + realstart = bnr + hioffs;
12026 + real_left = realsize >> 16;
12027 +#ifdef NATMEM_OFFSET
12028 + add_shmmaps (realstart << 16, bank);
12031 + put_mem_bank ((bnr + hioffs) << 16, bank, realstart << 16);
12038 +/* memory save/restore code */
12040 +uae_u8 *save_cram (int *len)
12042 + *len = allocated_chipmem;
12043 + return chipmemory;
12046 +uae_u8 *save_bram (int *len)
12048 + *len = allocated_bogomem;
12049 + return bogomemory;
12052 +void restore_cram (int len, long filepos)
12054 + chip_filepos = filepos;
12055 + changed_prefs.chipmem_size = len;
12058 +void restore_bram (int len, long filepos)
12060 + bogo_filepos = filepos;
12061 + changed_prefs.bogomem_size = len;
12064 +uae_u8 *restore_rom (uae_u8 *src)
12075 +uae_u8 *save_rom (int first, int *len)
12077 + static int count;
12078 + uae_u8 *dst, *dstbak;
12079 + uae_u8 *mem_real_start;
12080 + int mem_start, mem_size, mem_type, i, saverom;
12086 + mem_type = count;
12088 + case 0: /* Kickstart ROM */
12089 + mem_start = 0xf80000;
12090 + mem_real_start = kickmemory;
12091 + mem_size = kickmem_size;
12092 + /* 256KB or 512KB ROM? */
12093 + for (i = 0; i < mem_size / 2 - 4; i++) {
12094 + if (longget (i + mem_start) != longget (i + mem_start + mem_size / 2))
12097 + if (i == mem_size / 2 - 4) {
12099 + mem_start += 262144;
12110 + dstbak = dst = malloc (4 + 4 + 4 + 4 + 4 + mem_size);
12111 + save_u32 (mem_start);
12112 + save_u32 (mem_size);
12113 + save_u32 (mem_type);
12114 + save_u32 (longget (mem_start + 12)); /* version+revision */
12116 + sprintf (dst, "Kickstart %d.%d", wordget (mem_start + 12), wordget (mem_start + 14));
12117 + dst += strlen (dst) + 1;
12119 + for (i = 0; i < mem_size; i++)
12120 + *dst++ = byteget (mem_start + i);
12122 + *len = dst - dstbak;
12125 diff -urN src-0.8.22/src/mmu.c src-0.8.22-mmu/src/mmu.c
12126 --- src-0.8.22/src/mmu.c 1970-01-01 01:00:00.000000000 +0100
12127 +++ src-0.8.22-mmu/src/mmu.c 2003-07-25 12:38:37.000000000 +0200
12129 +#include "sysconfig.h"
12130 +#include "sysdeps.h"
12132 +#include "config.h"
12133 +#include "options.h"
12134 +#include "events.h"
12136 +#include "memory.h"
12137 +#include "custom.h"
12138 +#include "newcpu.h"
12139 +#include "autoconf.h"
12140 +#include "ersatz.h"
12141 +#include "debug.h"
12142 +#include "compiler.h"
12144 +#include "savestate.h"
12146 +#define DBG_MMU_VERBOSE 1
12147 +#define DBG_MMU_SANITY 0
12149 +static void mmu_dump_ttr(const char * label, uae_u32 ttr)
12151 + uae_u32 from_addr, to_addr;
12153 + from_addr = ttr & MMU_TTR_LOGICAL_BASE;
12154 + to_addr = (ttr & MMU_TTR_LOGICAL_MASK) << 8;
12156 + printf("%s: [%08lx] %08lx - %08lx enabled=%d supervisor=%d wp=%d cm=%02d\n",
12158 + from_addr, to_addr,
12159 + ttr & MMU_TTR_BIT_ENABLED ? 1 : 0,
12160 + (ttr & (MMU_TTR_BIT_SFIELD_ENABLED | MMU_TTR_BIT_SFIELD_SUPER)) >> MMU_TTR_SFIELD_SHIFT,
12161 + ttr & MMU_TTR_BIT_WRITE_PROTECT ? 1 : 0,
12162 + (ttr & MMU_TTR_CACHE_MASK) >> MMU_TTR_CACHE_SHIFT
12166 +extern void mmu_make_transparent_region(uaecptr baseaddr, uae_u32 size, int datamode)
12169 + uae_u32 * ttr0 = datamode ? ®s.dtt0 : ®s.itt0;
12170 + uae_u32 * ttr1 = datamode ? ®s.dtt1 : ®s.itt1;
12172 + if ((*ttr1 & MMU_TTR_BIT_ENABLED) == 0)
12174 + else if ((*ttr0 & MMU_TTR_BIT_ENABLED) == 0)
12179 + *ttr = baseaddr & MMU_TTR_LOGICAL_BASE;
12180 + *ttr |= ((baseaddr + size - 1) & MMU_TTR_LOGICAL_BASE) >> 8;
12181 + *ttr |= MMU_TTR_BIT_ENABLED;
12183 + write_log("MMU: map transparent mapping of %08x\n", *ttr);
12186 +/* check if an address matches a ttr */
12187 +STATIC_INLINE int mmu_match_ttr(uae_u32 ttr, uaecptr addr, int write, int test)
12189 + if (ttr & MMU_TTR_BIT_ENABLED) { /* TTR enabled */
12190 + uae_u8 msb, match, mask;
12192 + msb = (addr & MMU_TTR_LOGICAL_BASE) >> 24;
12193 + match = (ttr & MMU_TTR_LOGICAL_BASE) >> 24;
12194 + mask = (ttr & MMU_TTR_LOGICAL_MASK) >> 16;
12196 + if ((msb & ~mask) == match) {
12198 + if ((ttr & MMU_TTR_BIT_SFIELD_ENABLED) == 0) {
12199 + if ((ttr & MMU_TTR_BIT_SFIELD_SUPER) && !regs.s) {
12200 + return TTR_NO_MATCH;
12202 + if ((ttr & MMU_TTR_BIT_SFIELD_SUPER) == 0 && regs.s) {
12203 + return TTR_NO_MATCH;
12208 + regs.mmusr = MMU_MMUSR_T | MMU_MMUSR_R;
12211 + if ((ttr & MMU_TTR_BIT_WRITE_PROTECT) && write)
12212 + return TTR_NO_WRITE;
12213 + return TTR_OK_MATCH;
12216 + return TTR_NO_MATCH;
12219 +struct mmu_atc_line atc[64];
12220 +static int atc_rand = 0;
12221 +static int atc_last_hit = -1;
12223 +/* {{{ mmu_dump_table */
12224 +static void mmu_dump_table(const char * label, uaecptr root_ptr)
12226 + const int ROOT_TABLE_SIZE = 128,
12227 + PTR_TABLE_SIZE = 128,
12228 + PAGE_TABLE_SIZE = 64,
12229 + ROOT_INDEX_SHIFT = 25,
12230 + PTR_INDEX_SHIFT = 18,
12231 + PAGE_INDEX_SHIFT = 12;
12232 + int root_idx, ptr_idx, page_idx;
12233 + uae_u32 root_des, ptr_des, page_des;
12234 + uaecptr ptr_des_addr, page_addr,
12235 + root_log, ptr_log, page_log;
12237 + printf("%s: root=%lx\n", label, root_ptr);
12239 + for (root_idx = 0; root_idx < ROOT_TABLE_SIZE; root_idx++) {
12240 + root_des = phys_get_long(root_ptr + root_idx);
12242 + if ((root_des & 2) == 0)
12243 + continue; /* invalid */
12245 + printf("ROOT: %03d U=%d W=%d UDT=%02d\n", root_idx,
12246 + root_des & 8 ? 1 : 0,
12247 + root_des & 4 ? 1 : 0,
12251 + root_log = root_idx << 25;
12253 + ptr_des_addr = root_des & MMU_ROOT_PTR_ADDR_MASK;
12255 + for (ptr_idx = 0; ptr_idx < PTR_TABLE_SIZE; ptr_idx++) {
12257 + uaecptr log, phys;
12258 + int start_idx, n_pages; /* number of pages covered by this entry */
12260 + } page_info[PAGE_TABLE_SIZE];
12261 + int n_pages_used;
12263 + ptr_des = phys_get_long(ptr_des_addr + ptr_idx);
12264 + ptr_log = root_log | (ptr_idx << 18);
12266 + if ((ptr_des & 2) == 0)
12267 + continue; /* invalid */
12269 + page_addr = ptr_des & (regs.mmu_pagesize ? MMU_PTR_PAGE_ADDR_MASK_8 : MMU_PTR_PAGE_ADDR_MASK_4);
12271 + n_pages_used = -1;
12272 + for (page_idx = 0; page_idx < PAGE_TABLE_SIZE; page_idx++) {
12274 + page_des = phys_get_long(page_addr + page_idx);
12275 + page_log = ptr_log | (page_idx << 2);
12277 + switch (page_des & 3) {
12278 + case 0: /* invalid */
12280 + case 1: case 3: /* resident */
12281 + case 2: /* indirect */
12282 + if (n_pages_used == -1 || page_info[n_pages_used].match != page_des) {
12283 + /* use the next entry */
12286 + page_info[n_pages_used].match = page_des;
12287 + page_info[n_pages_used].n_pages = 1;
12288 + page_info[n_pages_used].start_idx = page_idx;
12289 + page_info[n_pages_used].log = page_log;
12292 + page_info[n_pages_used].n_pages++;
12298 + if (n_pages_used == -1)
12301 + printf(" PTR: %03d U=%d W=%d UDT=%02d\n", ptr_idx,
12302 + ptr_des & 8 ? 1 : 0,
12303 + ptr_des & 4 ? 1 : 0,
12308 + for (page_idx = 0; page_idx <= n_pages_used; page_idx++) {
12309 + page_des = page_info[page_idx].match;
12311 + if ((page_des & MMU_PDT_MASK) == 2) {
12312 + printf(" PAGE: %03d-%03d log=%08lx INDIRECT --> addr=%08lx\n",
12313 + page_info[page_idx].start_idx,
12314 + page_info[page_idx].start_idx + page_info[page_idx].n_pages - 1,
12315 + page_info[page_idx].log,
12316 + page_des & MMU_PAGE_INDIRECT_MASK
12321 + printf(" PAGE: %03d-%03d log=%08lx addr=%08lx UR=%02d G=%d U1/0=%d S=%d CM=%d M=%d U=%d W=%d\n",
12322 + page_info[page_idx].start_idx,
12323 + page_info[page_idx].start_idx + page_info[page_idx].n_pages - 1,
12324 + page_info[page_idx].log,
12325 + page_des & (regs.mmu_pagesize ? MMU_PAGE_ADDR_MASK_8 : MMU_PAGE_ADDR_MASK_4),
12326 + (page_des & (regs.mmu_pagesize ? MMU_PAGE_UR_MASK_8 : MMU_PAGE_UR_MASK_4)) >> MMU_PAGE_UR_SHIFT,
12327 + page_des & MMU_DES_GLOBAL ? 1 : 0,
12328 + (page_des & MMU_TTR_UX_MASK) >> MMU_TTR_UX_SHIFT,
12329 + page_des & MMU_DES_SUPER ? 1 : 0,
12330 + (page_des & MMU_TTR_CACHE_MASK) >> MMU_TTR_CACHE_SHIFT,
12331 + page_des & MMU_DES_MODIFIED ? 1 : 0,
12332 + page_des & MMU_DES_USED ? 1 : 0,
12333 + page_des & MMU_DES_WP ? 1 : 0
12343 +/* {{{ mmu_dump_atc */
12344 +void mmu_dump_atc(void)
12347 + for (i = 0; i < 64; i++) {
12350 + printf("ATC[%02d] G=%d S=%d CM=%d M=%d W=%d R=%d FC2=%d log=%08x --> phys=%08x\n",
12351 + i, atc[i].g ? 1 : 0, atc[i].s, atc[i].cm, atc[i].m, atc[i].w, atc[i].r,
12352 + atc[i].fc2 ? 1 : 0,
12360 +/* {{{ mmu_dump_tables */
12361 +void mmu_dump_tables(void)
12363 + if (currprefs.cpu_level != 4) {
12364 + printf("This CPU has no MMU hardware\n");
12367 + printf("URP: %08x SRP: %08x MMUSR: %x TC: %x\n", regs.urp, regs.srp, regs.mmusr, regs.tc);
12368 + mmu_dump_ttr("DTT0", regs.dtt0);
12369 + mmu_dump_ttr("DTT1", regs.dtt1);
12370 + mmu_dump_ttr("ITT0", regs.itt0);
12371 + mmu_dump_ttr("ITT1", regs.itt1);
12373 + //mmu_dump_table("SRP", regs.srp);
12377 +static void phys_dump_mem (uaecptr addr, int lines)
12379 + for (;lines--;) {
12381 + printf ("%08lx ", addr);
12382 + for (i = 0; i < 16; i++) {
12383 + printf ("%04x ", phys_get_word(addr)); addr += 2;
12390 +uaecptr REGPARAM2 mmu_translate(uaecptr theaddr, int fc, int write, uaecptr pc, int size, int test)
12393 + atc_hit_addr = 0,
12395 + root_des, root_des_addr,
12396 + ptr_des = 0, ptr_des_addr = 0,
12397 + page_des = 0, page_des_addr = 0,
12400 + uae_u8 ri, pi, pgi, wp = 0;
12402 + uae_u32 page_frame;
12403 + int supervisor, datamode =0;
12404 + int i, atc_sel, atc_index = -1, n_table_searches = 0;
12406 +// if (theaddr == 0x40000000) test |= MMU_TEST_VERBOSE;
12408 + supervisor = fc & 4;
12411 + case 0: /* data cache push */
12424 + write_log("FC=%d should not happen\n", datamode);
12428 + root_ptr = supervisor ? regs.srp : regs.urp;
12432 + /* TTR operate independently from the enable bit, so we can just ignore it if the MMU
12433 + * is not enabled to get better performance.
12434 + * But AmigaOS depends on PTEST to operate when the MMU is disabled;
12435 + * it uses the result in the ssw to detect a working MMU and then enables the MMU */
12436 + if (regs.mmu_enabled || test) {
12437 + switch(mmu_match_ttr(datamode ? regs.dtt0 : regs.itt0, theaddr, write, test)) {
12438 + case TTR_NO_WRITE:
12439 + write_log("MMU: write protected (via ttr) %lx\n", theaddr);
12441 + case TTR_OK_MATCH:
12445 + switch(mmu_match_ttr(datamode ? regs.dtt1 : regs.itt1, theaddr, write, test)) {
12446 + case TTR_NO_WRITE:
12447 + write_log("MMU: write protected (via ttr) %lx\n", theaddr);
12449 + case TTR_OK_MATCH:
12454 + if (!regs.mmu_enabled)
12458 + ri = (theaddr & 0xfe000000) >> 25;
12459 + pi = (theaddr & 0x01fc0000) >> 18;
12460 + if (regs.mmu_pagesize == MMU_PAGE_8KB) {
12461 + pgi = (theaddr & 0x3e000) >> 13;
12462 + page_frame = theaddr & 0xffffe000;
12463 + atc_sel = ((theaddr & 0x1e000) >> 13) & 0xf;
12466 + pgi = (theaddr & 0x3f000) >> 12;
12467 + page_frame = theaddr & 0xfffff000;
12468 + atc_sel = ((theaddr & 0xf000) >> 12) & 0xf;
12472 + atc_rand++; /* for random replacement */
12474 + if (test & MMU_TEST_FORCE_TABLE_SEARCH)
12475 + goto table_search;
12477 + for (i = 0; i < 4; i++) {
12478 + atc_index = atc_sel + (4 * i);
12480 +#if DBG_MMU_VERBOSE
12481 + if (test & MMU_TEST_VERBOSE)
12482 + write_log("MMU: %lx checking atc %d\nv=%d log=%lx s=%d PHYS=%lx (frame=%lx s=%d)\n",
12483 + theaddr, atc_index,
12484 + atc[atc_index].v, atc[atc_index].log, atc[atc_index].s,
12485 + atc[atc_index].phys,
12486 + page_frame, regs.s);
12490 + if (atc[atc_index].v && (atc[atc_index].log == page_frame) && atc[atc_index].fc2 == (fc & 4))
12495 + if (atc_index != -1) {
12498 + /* it's a hit! */
12500 + if (!atc[atc_index].r) {
12501 +#if DBG_MMU_VERBOSE
12502 + write_log("MMU: non-resident page!\n");
12508 + wp = atc[atc_index].w;
12510 + atc_hit_addr = atc[atc_index].phys | ((regs.mmu_pagesize == MMU_PAGE_8KB)
12511 + ? (theaddr & 0x1fff)
12512 + : (theaddr & 0x0fff));
12515 + if (atc[atc_index].g)
12516 + regs.mmusr |= MMU_MMUSR_G;
12517 + if (atc[atc_index].s)
12518 + regs.mmusr |= MMU_MMUSR_S;
12519 + if (atc[atc_index].m)
12520 + regs.mmusr |= MMU_MMUSR_M;
12521 + if (atc[atc_index].w)
12522 + regs.mmusr |= MMU_MMUSR_W;
12523 + if (atc[atc_index].r)
12524 + regs.mmusr |= MMU_MMUSR_R;
12526 + regs.mmusr |= atc[atc_index].phys & MMU_MMUSR_ADDR_MASK;
12529 +#if DBG_MMU_VERBOSE
12530 + if (test & MMU_TEST_VERBOSE)
12531 + if (atc_last_hit != atc_index) {
12532 + atc_last_hit = atc_index;
12533 + write_log("MMU: ATC %d HIT! %lx --> %lx\n", atc_index, theaddr, atc_hit_addr);
12534 + write_log("MMU: ATC v=%d log=%lx s=%d PHYS=%lx (frame=%lx s=%d)\n",
12535 + atc[atc_index].v, atc[atc_index].log, atc[atc_index].s,
12536 + atc[atc_index].phys,
12537 + page_frame, regs.s);
12542 + if (atc[atc_index].s && !supervisor) {
12543 + write_log("MMU: Supervisor only\n");
12544 + fslw |= (1 << 8);
12547 + if (wp && write) {
12548 + write_log("MMU: write protected!\n");
12549 + fslw |= (1 << 7);
12553 + if (!atc[atc_index].m && write) {
12554 + /* we need to update the M bit of the final descriptor */
12555 + goto table_search;
12558 + goto table_search;
12560 + return atc_hit_addr;
12566 + if (n_table_searches++ > 3) {
12567 + write_log("MMU: apparently looping during table search.\n");
12571 + if (atc_index == -1) {
12572 + //write_log("MMU: replace atc: ");
12573 + for (i = 0; i < 4; i++) {
12574 + if (!atc[atc_sel + (4 * i)].v) {
12575 + atc_index = atc_sel + (4 * i);
12579 + /* random choice */
12580 + if (atc_index == -1) {
12581 + atc_index = atc_sel + (4 * (atc_rand & 2));
12585 + fslw |= (1 << 6); /* TWE: flag as being in table search */
12587 +#if DBG_MMU_VERBOSE
12588 + if (test & MMU_TEST_VERBOSE)
12589 + write_log("MMU: table search for logical=%08x ri=%02x pi=%02x pgi=%03x page_frame=%08x root_ptr=%08x\n",
12590 + theaddr, ri, pi, pgi, page_frame, root_ptr);
12593 + /* root descriptor */
12594 + root_des_addr = (root_ptr & MMU_ROOT_PTR_ADDR_MASK) | (ri << 2);
12596 +#if DBG_MMU_SANITY
12597 + if (!phys_valid_address(root_des_addr, sz_long))
12601 + root_des = phys_get_long(root_des_addr);
12603 +#if DBG_MMU_VERBOSE
12604 + if (test & MMU_TEST_VERBOSE) {
12605 + write_log("MMU: root_des_addr = %lx val=%08x\n", root_des_addr, root_des);
12606 + //phys_dump_mem(root_ptr, 128 / 16);
12610 + switch(root_des & MMU_UDT_MASK) {
12613 + write_log("MMU: invalid root descriptor for %lx\n", theaddr);
12614 + fslw |= (1 << 12); /* PTA */
12615 + goto make_non_resident_atc;
12618 + wp |= root_des & MMU_DES_WP;
12619 + /* touch the page */
12620 + if (!wp && (root_des & MMU_DES_USED) == 0) {
12621 + root_des |= MMU_DES_USED;
12622 + phys_put_long(root_des_addr, root_des);
12626 + ptr_des_addr = (root_des & MMU_ROOT_PTR_ADDR_MASK) | (pi << 2);
12627 +#if DBG_MMU_SANITY
12628 + if (!phys_valid_address(ptr_des_addr, sz_long))
12632 + ptr_des = phys_get_long(ptr_des_addr);
12633 +#if DBG_MMU_VERBOSE
12634 + if (test & MMU_TEST_VERBOSE)
12635 + write_log("MMU: ptr_des_addr = %lx val=%08x\n", ptr_des_addr, ptr_des);
12636 + //phys_dump_mem(ptr_des_addr, 128 / 16);
12639 + switch(ptr_des & MMU_UDT_MASK) {
12642 + write_log("MMU: invalid ptr descriptor for %lx\n", theaddr);
12643 + fslw |= (1 << 11); /* PTB */
12644 + goto make_non_resident_atc;
12646 + wp |= ptr_des & MMU_DES_WP;
12648 + if (!wp && (ptr_des & MMU_DES_USED) == 0) {
12649 + ptr_des |= MMU_DES_USED;
12650 + phys_put_long(ptr_des_addr, ptr_des);
12653 + if (regs.mmu_pagesize == MMU_PAGE_8KB)
12654 + page_des_addr = (ptr_des & MMU_PTR_PAGE_ADDR_MASK_8) | (pgi << 2);
12656 + page_des_addr = (ptr_des & MMU_PTR_PAGE_ADDR_MASK_4) | (pgi << 2);
12658 +get_page_descriptor:
12659 +#if DBG_MMU_SANITY
12660 + if (!phys_valid_address(page_des_addr, sz_long))
12664 + page_des = phys_get_long(page_des_addr);
12665 +#if DBG_MMU_VERBOSE
12666 + if (test & MMU_TEST_VERBOSE) {
12667 + write_log("MMU: page_des_addr = %lx val=%08x\n", page_des_addr, page_des);
12668 + phys_dump_mem(page_des_addr, 64 / 16);
12672 + switch(page_des & MMU_PDT_MASK) {
12674 + write_log("MMU: invalid page descriptor log=%08lx page_des=%08lx @%08lx\n", theaddr, page_des, page_des_addr);
12675 + fslw |= (1 << 9); /* PF */
12676 + goto make_non_resident_atc;
12679 + /* resident page */
12684 + if (fslw & (1 << 10)) {
12685 + write_log("MMU: double indirect descriptor log=%lx descriptor @ %lx\n", theaddr, page_des_addr);
12686 + goto make_non_resident_atc;
12688 + page_des_addr = page_des & MMU_PAGE_INDIRECT_MASK;
12689 + fslw |= (1 << 10); /* IL - in case a fault occurs later, tag it as indirect */
12690 + goto get_page_descriptor;
12693 + wp |= page_des & MMU_DES_WP;
12696 + if ((page_des & MMU_DES_USED) == 0) {
12697 + page_des |= MMU_DES_USED;
12700 + /* set the modified bit */
12701 + if (write && (page_des & MMU_DES_MODIFIED) == 0) {
12702 + page_des |= MMU_DES_MODIFIED;
12706 + phys_put_long(page_des_addr, page_des);
12709 + atc[atc_index].log = page_frame;
12710 + atc[atc_index].v = 1;
12711 + atc[atc_index].r = 1;
12712 + atc[atc_index].s = page_des & MMU_DES_SUPER; /* supervisor */
12713 + atc[atc_index].w = wp;
12714 + atc[atc_index].fc2 = fc & 4;
12715 + atc[atc_index].g = page_des & MMU_DES_GLOBAL;
12716 + atc[atc_index].phys = page_des & (regs.mmu_pagesize ? MMU_PAGE_ADDR_MASK_8 : MMU_PAGE_ADDR_MASK_4);
12718 + atc[atc_index].m = (page_des & MMU_DES_MODIFIED) ? 1 : 0;
12722 + if (atc_hit_addr != 0 && atc_hit_addr != phys_addr) {
12723 + write_log("MMU: ERROR! ATC hit does not match table search! for %lx --> %lx (atc gave %lx)\n",
12724 + theaddr, phys_addr, atc_hit_addr);
12725 + activate_debugger();
12728 + /* re-use the end of the atc code */
12729 + goto atc_matched;
12733 + ssw |= (1 << 10); /* ATC */
12737 + fslw |= (1 << (write ? 23 : 24));
12739 + fslw |= (1 << 15); /* IO */
12748 + fslw |= (1 << 19);
12750 + fslw |= (1 << 20);
12753 + ssw |= fc & 7; /* Copy TM */
12755 + regs.mmu_fault_addr = theaddr;
12756 + regs.mmu_fslw = fslw;
12757 + regs.mmu_ssw = ssw;
12760 + regs.mmusr |= MMU_MMUSR_B;
12762 + write_log("BUS ERROR: fc=%d w=%d log=%08x ssw=%04x fslw=%08x\n", fc, write, theaddr, ssw, fslw);
12764 + if ((test & MMU_TEST_NO_BUSERR) == 0) {
12765 + Exception(2, pc);
12766 + longjmp(m68k_exception, 0);
12770 +make_non_resident_atc:
12771 +#if DBG_MMU_VERBOSE
12772 + write_log("MMU: table search for logical=%08x FC=%d ri=%02x pi=%02x pgi=%03x page_frame=%08x root_ptr=%08x\n",
12773 + theaddr, fc, ri, pi, pgi, page_frame, root_ptr);
12774 + write_log("MMU: root_des_addr = %lx val=%08x\n", root_des_addr, root_des);
12775 + write_log("MMU: ptr_des_addr = %lx val=%08x\n", ptr_des_addr, ptr_des);
12776 + write_log("MMU: page_des_addr = %lx val=%08x\n", page_des_addr, page_des);
12777 + mmu_dump_ttr("DTT0", regs.dtt0);
12778 + mmu_dump_ttr("DTT1", regs.dtt1);
12779 + mmu_dump_ttr("ITT0", regs.itt0);
12780 + mmu_dump_ttr("ITT1", regs.itt1);
12783 + atc[atc_index].log = page_frame;
12784 + atc[atc_index].phys = 0;
12785 + atc[atc_index].v = 0;
12786 + atc[atc_index].r = 0;
12790 +void mmu_op(uae_u32 opcode, uae_u16 extra)
12792 + if ((opcode & 0xFE0) == 0x0500) {
12793 + int i, regno, didflush = 0;
12795 + mmu_set_mmusr(0);
12797 + regno = opcode & 7;
12799 + switch((opcode & 24) >> 3) {
12801 + /* PFLUSHN (An) flush page entry if not global */
12802 + write_log ("PFLUSHN (A%d) %08x DFC=%d\n", regno, m68k_areg(regs, regno), regs.dfc);
12803 + for (i = 0; i < 64; i++) {
12804 + if (atc[i].v && !atc[i].g && (atc[i].log == m68k_areg(regs, regno))
12805 + && (regs.dfc & 4) == atc[i].fc2)
12813 + /* PFLUSH (An) flush page entry */
12814 + write_log ("PFLUSH (A%d) %08x DFC=%d\n", regno, m68k_areg(regs, regno), regs.dfc);
12815 + for (i = 0; i < 64; i++) {
12816 + if (atc[i].v && (atc[i].log == m68k_areg(regs, regno))
12817 + && (regs.dfc & 4) == atc[i].fc2)
12827 + /* PFLUSHAN flush all except global */
12828 + write_log ("PFLUSHAN\n");
12829 + for (i = 0; i < 64; i++) {
12830 + if (atc[i].v && !atc[i].g && (atc[i].log == m68k_areg(regs, regno)))
12836 + /* PFLUSHA flush all entries */
12837 + write_log ("PFLUSHA\n");
12838 + for (i = 0; i < 64; i++) {
12843 + atc_last_hit = -1;
12847 + write_log(" -> flushed %d matching entries\n", didflush);
12849 + } else if ((opcode & 0x0FD8) == 0x548) {
12850 + int write, regno;
12851 + regno = opcode & 7;
12852 + write = opcode & 32;
12853 + write_log ("PTEST%c (A%d) %08x DFC=%d\n", write ? 'W' : 'R', regno, m68k_areg(regs, regno), regs.dfc);
12854 + mmu_set_mmusr(0);
12855 + mmu_translate(m68k_areg(regs, regno), regs.dfc, write, m68k_getpc(), sz_byte, 1);
12856 + write_log("PTEST result: mmusr %08x\n", regs.mmusr);
12858 + op_illg (opcode);
12862 diff -urN src-0.8.22/src/newcpu.c src-0.8.22-mmu/src/newcpu.c
12863 --- src-0.8.22/src/newcpu.c 2002-02-25 17:33:08.000000000 +0100
12864 +++ src-0.8.22-mmu/src/newcpu.c 2003-07-25 12:35:24.000000000 +0200
12866 #include "savestate.h"
12867 #include "blitter.h"
12869 +#define SANITY_CHECK_ATC 1
12870 +#define MMU_SETJMP_EXCEPTIONS 1
12872 +#if MMU_SETJMP_EXCEPTIONS
12873 +jmp_buf m68k_exception;
12877 /* Opcode of faulting instruction */
12878 uae_u16 last_op_for_exception_3;
12879 /* PC at fault time */
12882 #define COUNT_INSTRS 0
12885 +#if COUNT_INSTRS /* {{{ */
12886 static unsigned long int instrcount[65536];
12887 static uae_u16 opcodenums[65536];
12890 void dump_counts (void)
12898 @@ -106,6 +114,7 @@
12902 +/* {{{ CPU init/table building */
12903 static void build_cpufunctbl (void)
12906 @@ -176,6 +185,9 @@
12910 + memset(&atc, 0, sizeof(atc));
12911 + regs.mmu_enabled = 0;
12913 update_68k_cycles ();
12915 for (i = 0 ; i < 256 ; i++) {
12916 @@ -196,7 +208,7 @@
12917 fpp_movem_index2[i] = j;
12918 fpp_movem_next[i] = i & (~(1 << j));
12921 +#if COUNT_INSTRS /* {{{ */
12923 FILE *f = fopen (icountfilename (), "r");
12924 memset (instrcount, 0, sizeof instrcount);
12925 @@ -211,7 +223,7 @@
12931 write_log ("Building CPU table for configuration: 68");
12932 if (currprefs.address_space_24 && currprefs.cpu_level > 1)
12934 @@ -244,6 +256,7 @@
12936 build_cpufunctbl ();
12940 struct regstruct regs, lastint_regs;
12941 static struct regstruct regs_backup[16];
12942 @@ -251,10 +264,6 @@
12943 static long int m68kpc_offset;
12946 -#define get_ibyte_1(o) get_byte(regs.pc + (regs.pc_p - regs.pc_oldp) + (o) + 1)
12947 -#define get_iword_1(o) get_word(regs.pc + (regs.pc_p - regs.pc_oldp) + (o))
12948 -#define get_ilong_1(o) get_long(regs.pc + (regs.pc_p - regs.pc_oldp) + (o))
12950 uae_s32 ShowEA (FILE *f, int reg, amodes mode, wordsizes size, char *buf)
12953 @@ -681,6 +690,45 @@
12954 unset_special (SPCFLAG_TRACE);
12957 +/* for building exception frames */
12958 +STATIC_INLINE void exc_push_word(uae_u16 w)
12960 + m68k_areg(regs, 7) -= 2;
12961 + put_word(m68k_areg(regs, 7), w);
12963 +STATIC_INLINE void exc_push_long(uae_u32 l)
12965 + m68k_areg(regs, 7) -= 4;
12966 + put_long (m68k_areg(regs, 7), l);
12969 +STATIC_INLINE void exc_make_frame(
12980 + exc_push_long(x1);
12981 + exc_push_long(x0);
12985 + exc_push_long(x0);
12989 + exc_push_word((format << 12) + (nr * 4)); /* format | vector */
12990 + exc_push_long(currpc);
12991 + exc_push_word(sr);
12994 +int in_exception_2 = 0;
12996 void Exception(int nr, uaecptr oldpc)
12998 uae_u32 currpc = m68k_getpc ();
12999 @@ -696,56 +744,107 @@
13000 m68k_areg(regs, 7) = regs.isp;
13004 + if (nr == 2 && in_exception_2++) {
13005 + write_log("HALT: Double Bus Error means bad news!\n");
13009 if (currprefs.cpu_level > 0) {
13010 - if (nr == 2 || nr == 3) {
13012 - /* @@@ this is probably wrong (?) */
13013 - for (i = 0 ; i < 12 ; i++) {
13014 - m68k_areg(regs, 7) -= 2;
13015 - put_word (m68k_areg(regs, 7), 0);
13017 + write_log("Exception 2!!\n");
13018 + if (currprefs.cpu_level == 5) {
13020 + exc_make_frame(4,
13024 + regs.mmu_fault_addr, /* fault address */
13025 + regs.mmu_fslw /* fault status long-word */
13028 - m68k_areg(regs, 7) -= 2;
13029 - put_word (m68k_areg(regs, 7), 0xa000 + nr * 4);
13030 + else if (currprefs.cpu_level == 4) {
13032 + exc_push_long(0); /* PD3 */
13033 + exc_push_long(0); /* PD2 */
13034 + exc_push_long(0); /* PD1 */
13035 + exc_push_long(0); /* PD0/WB1D */
13036 + exc_push_long(0); /* WB1A */
13037 + exc_push_long(0); /* WB2D */
13038 + exc_push_long(0); /* WB2A */
13039 + exc_push_long(0); /* WB3D */
13040 + exc_push_long(0); /* WB3A */
13041 + exc_push_long(regs.mmu_fault_addr);
13042 + exc_push_word(0); /* WB1S */
13043 + exc_push_word(0); /* WB2S */
13044 + exc_push_word(0); /* WB3S */
13045 + exc_push_word(0); /* WB3S */
13046 + exc_push_word(regs.mmu_ssw);
13047 + exc_push_long(regs.mmu_fault_addr); /* EA */
13048 + exc_make_frame(7,
13056 + else if (nr == 3) {
13059 + exc_make_frame(2,
13061 + last_addr_for_exception_3,
13063 + last_fault_for_exception_3 & 0xfffffffe,
13067 } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) {
13068 - m68k_areg(regs, 7) -= 4;
13069 - put_long (m68k_areg(regs, 7), oldpc);
13070 - m68k_areg(regs, 7) -= 2;
13071 - put_word (m68k_areg(regs, 7), 0x2000 + nr * 4);
13072 + /* div by zero, CHK, TRAP or TRACE */
13073 + exc_make_frame(2,
13080 } else if (regs.m && nr >= 24 && nr < 32) {
13081 - m68k_areg(regs, 7) -= 2;
13082 - put_word (m68k_areg(regs, 7), nr * 4);
13083 - m68k_areg(regs, 7) -= 4;
13084 - put_long (m68k_areg(regs, 7), currpc);
13085 - m68k_areg(regs, 7) -= 2;
13086 - put_word (m68k_areg(regs, 7), regs.sr);
13087 + /* interrupts! */
13088 + exc_make_frame(0,
13093 regs.sr |= (1 << 13);
13094 regs.msp = m68k_areg(regs, 7);
13095 m68k_areg(regs, 7) = regs.isp;
13096 - m68k_areg(regs, 7) -= 2;
13097 - put_word (m68k_areg(regs, 7), 0x1000 + nr * 4);
13099 + exc_make_frame(1, /* throwaway */
13105 - m68k_areg(regs, 7) -= 2;
13106 - put_word (m68k_areg(regs, 7), nr * 4);
13107 + exc_make_frame(0,
13114 - if (nr == 2 || nr == 3) {
13115 - m68k_areg(regs, 7) -= 12;
13118 - put_long (m68k_areg(regs, 7), last_fault_for_exception_3);
13119 - put_word (m68k_areg(regs, 7)+4, last_op_for_exception_3);
13120 - put_long (m68k_areg(regs, 7)+8, last_addr_for_exception_3);
13122 - write_log ("Exception!\n");
13123 - goto kludge_me_do;
13124 + if (nr == 2 || nr == 3) {
13125 + write_log ("Exception %d! -- this code needs rewriting - good luck!\n", nr);
13127 + exc_push_long(last_fault_for_exception_3);
13128 + exc_push_word(last_op_for_exception_3);
13129 + exc_push_long(last_addr_for_exception_3);
13131 + exc_push_word(regs.sr);
13133 - m68k_areg(regs, 7) -= 4;
13134 - put_long (m68k_areg(regs, 7), currpc);
13136 - m68k_areg(regs, 7) -= 2;
13137 - put_word (m68k_areg(regs, 7), regs.sr);
13138 m68k_setpc (get_long (regs.vbr + 4*nr));
13139 + if (nr < 24 && nr >= 32)
13140 + write_log("EXCEPTION: %02d handler @ %lx SP=%lx\n", nr, m68k_getpc(), m68k_areg(regs, 7));
13141 fill_prefetch_0 ();
13142 regs.t1 = regs.t0 = regs.m = 0;
13143 unset_special (SPCFLAG_TRACE | SPCFLAG_DOTRACE);
13144 @@ -762,10 +861,10 @@
13145 set_special (SPCFLAG_INT);
13148 -static uae_u32 caar, cacr, itt0, itt1, dtt0, dtt1, tc, mmusr, urp, srp;
13150 int m68k_move2c (int regno, uae_u32 *regp)
13152 + /* 0x808 is the PCR on an '060 */
13153 if ((currprefs.cpu_level == 1 && (regno & 0x7FF) > 1)
13154 || (currprefs.cpu_level < 4 && (regno & 0x7FF) > 2)
13155 || (currprefs.cpu_level == 4 && regno == 0x802))
13156 @@ -774,25 +873,24 @@
13160 - case 0: regs.sfc = *regp & 7; break;
13161 - case 1: regs.dfc = *regp & 7; break;
13162 - case 2: cacr = *regp & (currprefs.cpu_level < 4 ? 0x3 : 0x80008000); break;
13163 - case 3: tc = *regp & 0xc000; break;
13164 + case 0: regs.sfc = *regp & 7; /*write_log("SFC set to %d\n", regs.sfc);*/ break;
13165 + case 1: regs.dfc = *regp & 7; /*write_log("DFC set to %d\n", regs.dfc);*/ break;
13166 + case 2: regs.cacr = *regp & (currprefs.cpu_level < 4 ? 0x3 : 0x80008000); break;
13167 + case 3: mmu_set_tc(*regp & 0xc000); break;
13168 /* Mask out fields that should be zero. */
13169 - case 4: itt0 = *regp & 0xffffe364; break;
13170 - case 5: itt1 = *regp & 0xffffe364; break;
13171 - case 6: dtt0 = *regp & 0xffffe364; break;
13172 - case 7: dtt1 = *regp & 0xffffe364; break;
13173 + case 4: case 5: case 6: case 7:
13174 + mmu_set_ttr(regno, *regp & 0xffffe364); break;
13176 case 0x800: regs.usp = *regp; break;
13177 case 0x801: regs.vbr = *regp; break;
13178 - case 0x802: caar = *regp & 0xfc; break;
13179 + case 0x802: regs.caar = *regp & 0xfc; break;
13180 case 0x803: regs.msp = *regp; if (regs.m == 1) m68k_areg(regs, 7) = regs.msp; break;
13181 case 0x804: regs.isp = *regp; if (regs.m == 0) m68k_areg(regs, 7) = regs.isp; break;
13182 - case 0x805: mmusr = *regp; break;
13183 - case 0x806: urp = *regp; break;
13184 - case 0x807: srp = *regp; break;
13185 + case 0x805: mmu_set_mmusr(*regp); break;
13186 + case 0x806: case 0x807:
13187 + mmu_set_root_pointer(regno, *regp); break;
13189 + write_log("move2x cpu=%d regno=%lx val=%lx\n", currprefs.cpu_level, regno, *regp);
13193 @@ -802,31 +900,34 @@
13195 int m68k_movec2 (int regno, uae_u32 *regp)
13197 + /* 0x808 is the PCR on an '060 */
13198 if ((currprefs.cpu_level == 1 && (regno & 0x7FF) > 1)
13199 || (currprefs.cpu_level < 4 && (regno & 0x7FF) > 2)
13200 || (currprefs.cpu_level == 4 && regno == 0x802))
13202 + write_log("movec2 cpu=%d regno=%lx\n", currprefs.cpu_level, regno);
13207 case 0: *regp = regs.sfc; break;
13208 case 1: *regp = regs.dfc; break;
13209 - case 2: *regp = cacr; break;
13210 - case 3: *regp = tc; break;
13211 - case 4: *regp = itt0; break;
13212 - case 5: *regp = itt1; break;
13213 - case 6: *regp = dtt0; break;
13214 - case 7: *regp = dtt1; break;
13215 + case 2: *regp = regs.cacr; break;
13216 + case 3: *regp = regs.tc; break;
13217 + case 4: *regp = regs.itt0; break;
13218 + case 5: *regp = regs.itt1; break;
13219 + case 6: *regp = regs.dtt0; break;
13220 + case 7: *regp = regs.dtt1; break;
13221 case 0x800: *regp = regs.usp; break;
13222 case 0x801: *regp = regs.vbr; break;
13223 - case 0x802: *regp = caar; break;
13224 + case 0x802: *regp = regs.caar; break;
13225 case 0x803: *regp = regs.m == 1 ? m68k_areg(regs, 7) : regs.msp; break;
13226 case 0x804: *regp = regs.m == 0 ? m68k_areg(regs, 7) : regs.isp; break;
13227 - case 0x805: *regp = mmusr; break;
13228 - case 0x806: *regp = urp; break;
13229 - case 0x807: *regp = srp; break;
13230 + case 0x805: *regp = regs.mmusr; break;
13231 + case 0x806: *regp = regs.urp; break;
13232 + case 0x807: *regp = regs.srp; break;
13234 + write_log("movec2 cpu=%d regno=%lx\n", currprefs.cpu_level, regno);
13238 @@ -1091,6 +1192,8 @@
13240 void m68k_reset (void)
13242 + write_log("M68K: RESET!\n");
13243 + mmu_set_tc(regs.tc & ~0x8000); /* disable mmu */
13244 regs.kick_mask = 0x00F80000;
13246 if (savestate_state == STATE_RESTORE) {
13247 @@ -1106,8 +1209,8 @@
13251 - m68k_areg (regs, 7) = get_long (0x00f80000);
13252 - m68k_setpc (get_long (0x00f80004));
13253 + m68k_areg (regs, 7) = phys_get_long (0x00f80000);
13254 + m68k_setpc (phys_get_long (0x00f80004));
13255 refill_prefetch (m68k_getpc (), 0);
13256 fill_prefetch_0 ();
13258 @@ -1137,7 +1240,7 @@
13261 compiler_flush_jsr_stack ();
13262 - if (opcode == 0x4E7B && get_long (0x10) == 0 && (pc & 0xF80000) == 0xF80000) {
13263 + if (opcode == 0x4E7B && phys_get_long (0x10) == 0 && (pc & 0xF80000) == 0xF80000) {
13264 write_log ("Your Kickstart requires a 68020 CPU. Giving up.\n");
13266 set_special (SPCFLAG_BRK);
13267 @@ -1185,19 +1288,6 @@
13271 -void mmu_op(uae_u32 opcode, uae_u16 extra)
13273 - if ((opcode & 0xFE0) == 0x0500) {
13276 - write_log ("PFLUSH\n");
13277 - } else if ((opcode & 0x0FD8) == 0x548) {
13279 - write_log ("PTEST\n");
13281 - op_illg (opcode);
13284 static int n_insns = 0, n_spcinsns = 0;
13286 static uaecptr last_trace_ad = 0;
13287 @@ -1410,6 +1500,10 @@
13288 reset_frame_rate_hack ();
13289 update_68k_cycles ();
13291 +#if MMU_SETJMP_EXCEPTIONS
13292 + setjmp(m68k_exception);
13297 if (quit_program > 0) {
13298 @@ -1557,13 +1651,14 @@
13299 if (currprefs.cpu_compatible)
13300 fprintf (f, "prefetch %08lx\n", (unsigned long)do_get_mem_long(®s.prefetch));
13302 + fprintf (f, "this PC: %08lx\n", m68k_getpc());
13303 m68k_disasm (f, m68k_getpc (), nextpc, 1);
13305 fprintf (f, "next PC: %08lx\n", *nextpc);
13309 -/* CPU save/restore code */
13310 +/* {{{ CPU save/restore code */
13312 #define CPUTYPE_EC 1
13313 #define CPUMODE_HALT 1
13314 @@ -1616,8 +1711,8 @@
13315 regs.vbr = restore_u32 ();
13317 if (model >= 68020) {
13318 - caar = restore_u32 ();
13319 - cacr = restore_u32 ();
13320 + regs.caar = restore_u32 ();
13321 + regs.cacr = restore_u32 ();
13322 regs.msp = restore_u32 ();
13324 write_log ("CPU %d%s%03d, PC=%08.8X\n",
13325 @@ -1651,10 +1746,13 @@
13326 save_u32 (regs.vbr); /* VBR */
13328 if(model >= 68020) {
13329 - save_u32 (caar); /* CAAR */
13330 - save_u32 (cacr); /* CACR */
13331 + save_u32 (regs.caar); /* CAAR */
13332 + save_u32 (regs.cacr); /* CACR */
13333 save_u32 (regs.msp); /* MSP */
13335 *len = dst - dstbak;
13341 diff -urN src-0.8.22/src/newcpu.c~ src-0.8.22-mmu/src/newcpu.c~
13342 --- src-0.8.22/src/newcpu.c~ 1970-01-01 01:00:00.000000000 +0100
13343 +++ src-0.8.22-mmu/src/newcpu.c~ 2003-07-25 12:11:11.000000000 +0200
13346 + * UAE - The Un*x Amiga Emulator
13348 + * MC68000 emulation
13350 + * (c) 1995 Bernd Schmidt
13353 +#include "sysconfig.h"
13354 +#include "sysdeps.h"
13356 +#include "config.h"
13357 +#include "options.h"
13358 +#include "events.h"
13360 +#include "memory.h"
13361 +#include "custom.h"
13362 +#include "newcpu.h"
13363 +#include "autoconf.h"
13364 +#include "ersatz.h"
13365 +#include "debug.h"
13366 +#include "compiler.h"
13368 +#include "savestate.h"
13369 +#include "blitter.h"
13371 +#define SANITY_CHECK_ATC 1
13372 +#define MMU_SETJMP_EXCEPTIONS 1
13374 +#if MMU_SETJMP_EXCEPTIONS
13375 +jmp_buf m68k_exception;
13379 +/* Opcode of faulting instruction */
13380 +uae_u16 last_op_for_exception_3;
13381 +/* PC at fault time */
13382 +uaecptr last_addr_for_exception_3;
13383 +/* Address that generated the exception */
13384 +uaecptr last_fault_for_exception_3;
13386 +int areg_byteinc[] = { 1,1,1,1,1,1,1,2 };
13387 +int imm8_table[] = { 8,1,2,3,4,5,6,7 };
13389 +int movem_index1[256];
13390 +int movem_index2[256];
13391 +int movem_next[256];
13393 +int fpp_movem_index1[256];
13394 +int fpp_movem_index2[256];
13395 +int fpp_movem_next[256];
13397 +cpuop_func *cpufunctbl[65536];
13399 +#define COUNT_INSTRS 0
13401 +#if COUNT_INSTRS /* {{{ */
13402 +static unsigned long int instrcount[65536];
13403 +static uae_u16 opcodenums[65536];
13405 +static int compfn (const void *el1, const void *el2)
13407 + return instrcount[*(const uae_u16 *)el1] < instrcount[*(const uae_u16 *)el2];
13410 +static char *icountfilename (void)
13412 + char *name = getenv ("INSNCOUNT");
13415 + return COUNT_INSTRS == 2 ? "frequent.68k" : "insncount";
13418 +void dump_counts (void)
13420 + FILE *f = fopen (icountfilename (), "w");
13421 + unsigned long int total;
13424 + write_log ("Writing instruction count file...\n");
13425 + for (i = 0; i < 65536; i++) {
13426 + opcodenums[i] = i;
13427 + total += instrcount[i];
13429 + qsort (opcodenums, 65536, sizeof(uae_u16), compfn);
13431 + fprintf (f, "Total: %lu\n", total);
13432 + for (i=0; i < 65536; i++) {
13433 + unsigned long int cnt = instrcount[opcodenums[i]];
13434 + struct instr *dp;
13435 + struct mnemolookup *lookup;
13438 + dp = table68k + opcodenums[i];
13439 + for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
13441 + fprintf (f, "%04x: %lu %s\n", opcodenums[i], cnt, lookup->name);
13446 +void dump_counts (void)
13453 +static unsigned long op_illg_1 (uae_u32 opcode) REGPARAM;
13455 +static unsigned long REGPARAM2 op_illg_1 (uae_u32 opcode)
13457 + op_illg (opcode);
13461 +/* {{{ CPU init/table building */
13462 +static void build_cpufunctbl (void)
13465 + unsigned long opcode;
13466 + struct cputbl *tbl = (currprefs.cpu_level == 4 ? op_smalltbl_0_ff
13467 + : currprefs.cpu_level == 3 ? op_smalltbl_1_ff
13468 + : currprefs.cpu_level == 2 ? op_smalltbl_2_ff
13469 + : currprefs.cpu_level == 1 ? op_smalltbl_3_ff
13470 + : ! currprefs.cpu_compatible ? op_smalltbl_4_ff
13471 + : op_smalltbl_5_ff);
13473 + write_log ("Building CPU function table (%d %d %d).\n",
13474 + currprefs.cpu_level, currprefs.cpu_compatible, currprefs.address_space_24);
13476 + for (opcode = 0; opcode < 65536; opcode++)
13477 + cpufunctbl[opcode] = op_illg_1;
13478 + for (i = 0; tbl[i].handler != NULL; i++) {
13479 + if (! tbl[i].specific)
13480 + cpufunctbl[tbl[i].opcode] = tbl[i].handler;
13482 + for (opcode = 0; opcode < 65536; opcode++) {
13485 + if (table68k[opcode].mnemo == i_ILLG || table68k[opcode].clev > currprefs.cpu_level)
13488 + if (table68k[opcode].handler != -1) {
13489 + f = cpufunctbl[table68k[opcode].handler];
13490 + if (f == op_illg_1)
13492 + cpufunctbl[opcode] = f;
13495 + for (i = 0; tbl[i].handler != NULL; i++) {
13496 + if (tbl[i].specific)
13497 + cpufunctbl[tbl[i].opcode] = tbl[i].handler;
13501 +unsigned long cycles_mask, cycles_val;
13503 +static void update_68k_cycles (void)
13506 + cycles_val = currprefs.m68k_speed;
13507 + if (currprefs.m68k_speed < 1) {
13508 + cycles_mask = 0xFFFFFFFF;
13513 +void check_prefs_changed_cpu (void)
13515 + if (currprefs.cpu_level != changed_prefs.cpu_level
13516 + || currprefs.cpu_compatible != changed_prefs.cpu_compatible) {
13517 + currprefs.cpu_level = changed_prefs.cpu_level;
13518 + currprefs.cpu_compatible = changed_prefs.cpu_compatible;
13519 + build_cpufunctbl ();
13521 + if (currprefs.m68k_speed != changed_prefs.m68k_speed) {
13522 + currprefs.m68k_speed = changed_prefs.m68k_speed;
13523 + reset_frame_rate_hack ();
13524 + update_68k_cycles ();
13528 +void init_m68k (void)
13532 + memset(&atc, 0, sizeof(atc));
13533 + regs.mmu_enabled = 0;
13535 + update_68k_cycles ();
13537 + for (i = 0 ; i < 256 ; i++) {
13539 + for (j = 0 ; j < 8 ; j++) {
13540 + if (i & (1 << j)) break;
13542 + movem_index1[i] = j;
13543 + movem_index2[i] = 7-j;
13544 + movem_next[i] = i & (~(1 << j));
13546 + for (i = 0 ; i < 256 ; i++) {
13548 + for (j = 7 ; j >= 0 ; j--) {
13549 + if (i & (1 << j)) break;
13551 + fpp_movem_index1[i] = 7-j;
13552 + fpp_movem_index2[i] = j;
13553 + fpp_movem_next[i] = i & (~(1 << j));
13555 +#if COUNT_INSTRS /* {{{ */
13557 + FILE *f = fopen (icountfilename (), "r");
13558 + memset (instrcount, 0, sizeof instrcount);
13560 + uae_u32 opcode, count, total;
13562 + write_log ("Reading instruction count file...\n");
13563 + fscanf (f, "Total: %lu\n", &total);
13564 + while (fscanf (f, "%lx: %lu %s\n", &opcode, &count, name) == 3) {
13565 + instrcount[opcode] = count;
13571 + write_log ("Building CPU table for configuration: 68");
13572 + if (currprefs.address_space_24 && currprefs.cpu_level > 1)
13573 + write_log ("EC");
13574 + switch (currprefs.cpu_level) {
13576 + write_log ("010");
13579 + write_log ("020");
13582 + write_log ("020/881");
13585 + /* Who is going to miss the MMU anyway...? :-) */
13586 + write_log ("040");
13589 + write_log ("000");
13592 + if (currprefs.cpu_compatible)
13593 + write_log (" (compatible mode)");
13594 + write_log ("\n");
13596 + read_table68k ();
13599 + write_log ("%d CPU functions\n", nr_cpuop_funcs);
13601 + build_cpufunctbl ();
13605 +struct regstruct regs, lastint_regs;
13606 +static struct regstruct regs_backup[16];
13607 +static int backup_pointer = 0;
13608 +static long int m68kpc_offset;
13611 +uae_s32 ShowEA (FILE *f, int reg, amodes mode, wordsizes size, char *buf)
13619 + uae_s32 offset = 0;
13624 + sprintf (buffer,"D%d", reg);
13627 + sprintf (buffer,"A%d", reg);
13630 + sprintf (buffer,"(A%d)", reg);
13633 + sprintf (buffer,"(A%d)+", reg);
13636 + sprintf (buffer,"-(A%d)", reg);
13639 + disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
13640 + addr = m68k_areg(regs,reg) + (uae_s16)disp16;
13641 + sprintf (buffer,"(A%d,$%04x) == $%08lx", reg, disp16 & 0xffff,
13642 + (unsigned long)addr);
13645 + dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
13646 + disp8 = dp & 0xFF;
13647 + r = (dp & 0x7000) >> 12;
13648 + dispreg = dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r);
13649 + if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
13650 + dispreg <<= (dp >> 9) & 3;
13652 + if (dp & 0x100) {
13653 + uae_s32 outer = 0, disp = 0;
13654 + uae_s32 base = m68k_areg(regs,reg);
13656 + sprintf (name,"A%d, ",reg);
13657 + if (dp & 0x80) { base = 0; name[0] = 0; }
13658 + if (dp & 0x40) dispreg = 0;
13659 + if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
13660 + if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
13663 + if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
13664 + if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
13666 + if (!(dp & 4)) base += dispreg;
13667 + if (dp & 3) base = get_long (base);
13668 + if (dp & 4) base += dispreg;
13670 + addr = base + outer;
13671 + sprintf (buffer,"(%s%c%d.%c*%d+%ld)+%ld == $%08lx", name,
13672 + dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
13673 + 1 << ((dp >> 9) & 3),
13675 + (unsigned long)addr);
13677 + addr = m68k_areg(regs,reg) + (uae_s32)((uae_s8)disp8) + dispreg;
13678 + sprintf (buffer,"(A%d, %c%d.%c*%d, $%02x) == $%08lx", reg,
13679 + dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
13680 + 1 << ((dp >> 9) & 3), disp8,
13681 + (unsigned long)addr);
13685 + addr = m68k_getpc () + m68kpc_offset;
13686 + disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
13687 + addr += (uae_s16)disp16;
13688 + sprintf (buffer,"(PC,$%04x) == $%08lx", disp16 & 0xffff,(unsigned long)addr);
13691 + addr = m68k_getpc () + m68kpc_offset;
13692 + dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
13693 + disp8 = dp & 0xFF;
13694 + r = (dp & 0x7000) >> 12;
13695 + dispreg = dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r);
13696 + if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
13697 + dispreg <<= (dp >> 9) & 3;
13699 + if (dp & 0x100) {
13700 + uae_s32 outer = 0,disp = 0;
13701 + uae_s32 base = addr;
13703 + sprintf (name,"PC, ");
13704 + if (dp & 0x80) { base = 0; name[0] = 0; }
13705 + if (dp & 0x40) dispreg = 0;
13706 + if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
13707 + if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
13710 + if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
13711 + if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
13713 + if (!(dp & 4)) base += dispreg;
13714 + if (dp & 3) base = get_long (base);
13715 + if (dp & 4) base += dispreg;
13717 + addr = base + outer;
13718 + sprintf (buffer,"(%s%c%d.%c*%d+%ld)+%ld == $%08lx", name,
13719 + dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
13720 + 1 << ((dp >> 9) & 3),
13722 + (unsigned long)addr);
13724 + addr += (uae_s32)((uae_s8)disp8) + dispreg;
13725 + sprintf (buffer,"(PC, %c%d.%c*%d, $%02x) == $%08lx", dp & 0x8000 ? 'A' : 'D',
13726 + (int)r, dp & 0x800 ? 'L' : 'W', 1 << ((dp >> 9) & 3),
13727 + disp8, (unsigned long)addr);
13731 + sprintf (buffer,"$%08lx", (unsigned long)(uae_s32)(uae_s16)get_iword_1 (m68kpc_offset));
13732 + m68kpc_offset += 2;
13735 + sprintf (buffer,"$%08lx", (unsigned long)get_ilong_1 (m68kpc_offset));
13736 + m68kpc_offset += 4;
13741 + sprintf (buffer,"#$%02x", (unsigned int)(get_iword_1 (m68kpc_offset) & 0xff));
13742 + m68kpc_offset += 2;
13745 + sprintf (buffer,"#$%04x", (unsigned int)(get_iword_1 (m68kpc_offset) & 0xffff));
13746 + m68kpc_offset += 2;
13749 + sprintf (buffer,"#$%08lx", (unsigned long)(get_ilong_1 (m68kpc_offset)));
13750 + m68kpc_offset += 4;
13757 + offset = (uae_s32)(uae_s8)get_iword_1 (m68kpc_offset);
13758 + m68kpc_offset += 2;
13759 + sprintf (buffer,"#$%02x", (unsigned int)(offset & 0xff));
13762 + offset = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
13763 + m68kpc_offset += 2;
13764 + sprintf (buffer,"#$%04x", (unsigned int)(offset & 0xffff));
13767 + offset = (uae_s32)get_ilong_1 (m68kpc_offset);
13768 + m68kpc_offset += 4;
13769 + sprintf (buffer,"#$%08lx", (unsigned long)offset);
13772 + offset = (uae_s32)(uae_s8)(reg & 0xff);
13773 + sprintf (buffer,"#$%08lx", (unsigned long)offset);
13779 + fprintf (f, "%s", buffer);
13781 + strcat (buf, buffer);
13785 +/* The plan is that this will take over the job of exception 3 handling -
13786 + * the CPU emulation functions will just do a longjmp to m68k_go whenever
13787 + * they hit an odd address. */
13788 +static int verify_ea (int reg, amodes mode, wordsizes size, uae_u32 *val)
13796 + uae_s32 offset = 0;
13800 + *val = m68k_dreg (regs, reg);
13803 + *val = m68k_areg (regs, reg);
13808 + addr = m68k_areg (regs, reg);
13811 + addr = m68k_areg (regs, reg);
13814 + disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
13815 + addr = m68k_areg(regs,reg) + (uae_s16)disp16;
13818 + addr = m68k_areg (regs, reg);
13820 + dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
13821 + disp8 = dp & 0xFF;
13822 + r = (dp & 0x7000) >> 12;
13823 + dispreg = dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r);
13824 + if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
13825 + dispreg <<= (dp >> 9) & 3;
13827 + if (dp & 0x100) {
13828 + uae_s32 outer = 0, disp = 0;
13829 + uae_s32 base = addr;
13830 + if (dp & 0x80) base = 0;
13831 + if (dp & 0x40) dispreg = 0;
13832 + if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
13833 + if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
13836 + if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
13837 + if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
13839 + if (!(dp & 4)) base += dispreg;
13840 + if (dp & 3) base = get_long (base);
13841 + if (dp & 4) base += dispreg;
13843 + addr = base + outer;
13845 + addr += (uae_s32)((uae_s8)disp8) + dispreg;
13849 + addr = m68k_getpc () + m68kpc_offset;
13850 + disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
13851 + addr += (uae_s16)disp16;
13854 + addr = m68k_getpc () + m68kpc_offset;
13857 + addr = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
13858 + m68kpc_offset += 2;
13861 + addr = get_ilong_1 (m68kpc_offset);
13862 + m68kpc_offset += 4;
13867 + *val = get_iword_1 (m68kpc_offset) & 0xff;
13868 + m68kpc_offset += 2;
13871 + *val = get_iword_1 (m68kpc_offset) & 0xffff;
13872 + m68kpc_offset += 2;
13875 + *val = get_ilong_1 (m68kpc_offset);
13876 + m68kpc_offset += 4;
13883 + *val = (uae_s32)(uae_s8)get_iword_1 (m68kpc_offset);
13884 + m68kpc_offset += 2;
13887 + *val = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
13888 + m68kpc_offset += 2;
13891 + *val = get_ilong_1 (m68kpc_offset);
13892 + m68kpc_offset += 4;
13895 + *val = (uae_s32)(uae_s8)(reg & 0xff);
13901 + if ((addr & 1) == 0)
13904 + last_addr_for_exception_3 = m68k_getpc () + m68kpc_offset;
13905 + last_fault_for_exception_3 = addr;
13909 +uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp)
13911 + int reg = (dp >> 12) & 15;
13912 + uae_s32 regd = regs.regs[reg];
13913 + if ((dp & 0x800) == 0)
13914 + regd = (uae_s32)(uae_s16)regd;
13915 + regd <<= (dp >> 9) & 3;
13916 + if (dp & 0x100) {
13917 + uae_s32 outer = 0;
13918 + if (dp & 0x80) base = 0;
13919 + if (dp & 0x40) regd = 0;
13921 + if ((dp & 0x30) == 0x20) base += (uae_s32)(uae_s16)next_iword();
13922 + if ((dp & 0x30) == 0x30) base += next_ilong();
13924 + if ((dp & 0x3) == 0x2) outer = (uae_s32)(uae_s16)next_iword();
13925 + if ((dp & 0x3) == 0x3) outer = next_ilong();
13927 + if ((dp & 0x4) == 0) base += regd;
13928 + if (dp & 0x3) base = get_long (base);
13929 + if (dp & 0x4) base += regd;
13931 + return base + outer;
13933 + return base + (uae_s32)((uae_s8)dp) + regd;
13937 +uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp)
13939 + int reg = (dp >> 12) & 15;
13940 + uae_s32 regd = regs.regs[reg];
13942 + if ((dp & 0x800) == 0)
13943 + regd = (uae_s32)(uae_s16)regd;
13944 + return base + (uae_s8)dp + regd;
13946 + /* Branch-free code... benchmark this again now that
13947 + * things are no longer inline. */
13950 + mask = ((dp & 0x800) >> 11) - 1;
13951 + regd16 = (uae_s32)(uae_s16)regd;
13954 + base += (uae_s8)dp;
13957 + return base + regd;
13961 +void MakeSR (void)
13964 + assert((regs.t1 & 1) == regs.t1);
13965 + assert((regs.t0 & 1) == regs.t0);
13966 + assert((regs.s & 1) == regs.s);
13967 + assert((regs.m & 1) == regs.m);
13968 + assert((XFLG & 1) == XFLG);
13969 + assert((NFLG & 1) == NFLG);
13970 + assert((ZFLG & 1) == ZFLG);
13971 + assert((VFLG & 1) == VFLG);
13972 + assert((CFLG & 1) == CFLG);
13974 + regs.sr = ((regs.t1 << 15) | (regs.t0 << 14)
13975 + | (regs.s << 13) | (regs.m << 12) | (regs.intmask << 8)
13976 + | (GET_XFLG << 4) | (GET_NFLG << 3) | (GET_ZFLG << 2) | (GET_VFLG << 1)
13980 +void MakeFromSR (void)
13982 + int oldm = regs.m;
13983 + int olds = regs.s;
13985 + regs.t1 = (regs.sr >> 15) & 1;
13986 + regs.t0 = (regs.sr >> 14) & 1;
13987 + regs.s = (regs.sr >> 13) & 1;
13988 + regs.m = (regs.sr >> 12) & 1;
13989 + regs.intmask = (regs.sr >> 8) & 7;
13990 + SET_XFLG ((regs.sr >> 4) & 1);
13991 + SET_NFLG ((regs.sr >> 3) & 1);
13992 + SET_ZFLG ((regs.sr >> 2) & 1);
13993 + SET_VFLG ((regs.sr >> 1) & 1);
13994 + SET_CFLG (regs.sr & 1);
13995 + if (currprefs.cpu_level >= 2) {
13996 + if (olds != regs.s) {
13999 + regs.msp = m68k_areg(regs, 7);
14001 + regs.isp = m68k_areg(regs, 7);
14002 + m68k_areg(regs, 7) = regs.usp;
14004 + regs.usp = m68k_areg(regs, 7);
14005 + m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp;
14007 + } else if (olds && oldm != regs.m) {
14009 + regs.msp = m68k_areg(regs, 7);
14010 + m68k_areg(regs, 7) = regs.isp;
14012 + regs.isp = m68k_areg(regs, 7);
14013 + m68k_areg(regs, 7) = regs.msp;
14017 + if (olds != regs.s) {
14019 + regs.isp = m68k_areg(regs, 7);
14020 + m68k_areg(regs, 7) = regs.usp;
14022 + regs.usp = m68k_areg(regs, 7);
14023 + m68k_areg(regs, 7) = regs.isp;
14028 + set_special (SPCFLAG_INT);
14029 + if (regs.t1 || regs.t0)
14030 + set_special (SPCFLAG_TRACE);
14032 + /* Keep SPCFLAG_DOTRACE, we still want a trace exception for
14033 + SR-modifying instructions (including STOP). */
14034 + unset_special (SPCFLAG_TRACE);
14037 +/* for building exception frames */
14038 +STATIC_INLINE void exc_push_word(uae_u16 w)
14040 + m68k_areg(regs, 7) -= 2;
14041 + put_word(m68k_areg(regs, 7), w);
14043 +STATIC_INLINE void exc_push_long(uae_u32 l)
14045 + m68k_areg(regs, 7) -= 4;
14046 + put_long (m68k_areg(regs, 7), l);
14049 +STATIC_INLINE void exc_make_frame(
14060 + exc_push_long(x1);
14061 + exc_push_long(x0);
14065 + exc_push_long(x0);
14069 + exc_push_word((format << 12) + (nr * 4)); /* format | vector */
14070 + exc_push_long(currpc);
14071 + exc_push_word(sr);
14074 +int in_exception_2 = 0;
14076 +void Exception(int nr, uaecptr oldpc)
14078 + uae_u32 currpc = m68k_getpc ();
14080 + compiler_flush_jsr_stack();
14084 + regs.usp = m68k_areg(regs, 7);
14085 + if (currprefs.cpu_level >= 2)
14086 + m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp;
14088 + m68k_areg(regs, 7) = regs.isp;
14092 + if (nr == 2 && in_exception_2++) {
14093 + write_log("HALT: Double Bus Error means bad news!\n");
14097 + if (currprefs.cpu_level > 0) {
14100 + write_log("Exception 2!!\n");
14102 + if (currprefs.cpu_level == 5) {
14104 + exc_make_frame(4,
14108 + regs.mmu_fault_addr, /* fault address */
14109 + regs.mmu_fslw /* fault status long-word */
14112 + else if (currprefs.cpu_level == 4) {
14114 + exc_push_long(0); /* PD3 */
14115 + exc_push_long(0); /* PD2 */
14116 + exc_push_long(0); /* PD1 */
14117 + exc_push_long(0); /* PD0/WB1D */
14118 + exc_push_long(0); /* WB1A */
14119 + exc_push_long(0); /* WB2D */
14120 + exc_push_long(0); /* WB2A */
14121 + exc_push_long(0); /* WB3D */
14122 + exc_push_long(0); /* WB3A */
14123 + exc_push_long(regs.mmu_fault_addr);
14124 + exc_push_word(0); /* WB1S */
14125 + exc_push_word(0); /* WB2S */
14126 + exc_push_word(0); /* WB3S */
14127 + exc_push_word(0); /* WB3S */
14128 + exc_push_word(regs.mmu_ssw);
14129 + exc_push_long(regs.mmu_fault_addr); /* EA */
14130 + exc_make_frame(7,
14138 + else if (nr == 3) {
14141 + exc_make_frame(2,
14143 + last_addr_for_exception_3,
14145 + last_fault_for_exception_3 & 0xfffffffe,
14149 + } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) {
14150 + /* div by zero, CHK, TRAP or TRACE */
14151 + exc_make_frame(2,
14158 + } else if (regs.m && nr >= 24 && nr < 32) {
14159 + /* interrupts! */
14160 + exc_make_frame(0,
14165 + regs.sr |= (1 << 13);
14166 + regs.msp = m68k_areg(regs, 7);
14167 + m68k_areg(regs, 7) = regs.isp;
14169 + exc_make_frame(1, /* throwaway */
14175 + exc_make_frame(0,
14182 + if (nr == 2 || nr == 3) {
14183 + write_log ("Exception %d! -- this code needs rewriting - good luck!\n", nr);
14185 + exc_push_long(last_fault_for_exception_3);
14186 + exc_push_word(last_op_for_exception_3);
14187 + exc_push_long(last_addr_for_exception_3);
14189 + exc_push_word(regs.sr);
14191 + m68k_setpc (get_long (regs.vbr + 4*nr));
14192 + if (nr < 24 && nr >= 32)
14193 + write_log("EXCEPTION: %02d handler @ %lx SP=%lx\n", nr, m68k_getpc(), m68k_areg(regs, 7));
14194 + fill_prefetch_0 ();
14195 + regs.t1 = regs.t0 = regs.m = 0;
14196 + unset_special (SPCFLAG_TRACE | SPCFLAG_DOTRACE);
14199 +static void Interrupt (int nr)
14201 + assert(nr < 8 && nr >= 0);
14202 + lastint_regs = regs;
14204 + Exception(nr+24, 0);
14206 + regs.intmask = nr;
14207 + set_special (SPCFLAG_INT);
14211 +int m68k_move2c (int regno, uae_u32 *regp)
14213 + /* 0x808 is the PCR on an '060 */
14214 + if ((currprefs.cpu_level == 1 && (regno & 0x7FF) > 1)
14215 + || (currprefs.cpu_level < 4 && (regno & 0x7FF) > 2)
14216 + || (currprefs.cpu_level == 4 && regno == 0x802))
14218 + op_illg (0x4E7B);
14222 + case 0: regs.sfc = *regp & 7; /*write_log("SFC set to %d\n", regs.sfc);*/ break;
14223 + case 1: regs.dfc = *regp & 7; /*write_log("DFC set to %d\n", regs.dfc);*/ break;
14224 + case 2: regs.cacr = *regp & (currprefs.cpu_level < 4 ? 0x3 : 0x80008000); break;
14225 + case 3: mmu_set_tc(*regp & 0xc000); break;
14226 + /* Mask out fields that should be zero. */
14227 + case 4: case 5: case 6: case 7:
14228 + mmu_set_ttr(regno, *regp & 0xffffe364); break;
14230 + case 0x800: regs.usp = *regp; break;
14231 + case 0x801: regs.vbr = *regp; break;
14232 + case 0x802: regs.caar = *regp & 0xfc; break;
14233 + case 0x803: regs.msp = *regp; if (regs.m == 1) m68k_areg(regs, 7) = regs.msp; break;
14234 + case 0x804: regs.isp = *regp; if (regs.m == 0) m68k_areg(regs, 7) = regs.isp; break;
14235 + case 0x805: mmu_set_mmusr(*regp); break;
14236 + case 0x806: case 0x807:
14237 + mmu_set_root_pointer(regno, *regp); break;
14239 + write_log("move2x cpu=%d regno=%lx val=%lx\n", currprefs.cpu_level, regno, *regp);
14240 + op_illg (0x4E7B);
14247 +int m68k_movec2 (int regno, uae_u32 *regp)
14249 + /* 0x808 is the PCR on an '060 */
14250 + if ((currprefs.cpu_level == 1 && (regno & 0x7FF) > 1)
14251 + || (currprefs.cpu_level < 4 && (regno & 0x7FF) > 2)
14252 + || (currprefs.cpu_level == 4 && regno == 0x802))
14254 + write_log("movec2 cpu=%d regno=%lx\n", currprefs.cpu_level, regno);
14255 + op_illg (0x4E7A);
14259 + case 0: *regp = regs.sfc; break;
14260 + case 1: *regp = regs.dfc; break;
14261 + case 2: *regp = regs.cacr; break;
14262 + case 3: *regp = regs.tc; break;
14263 + case 4: *regp = regs.itt0; break;
14264 + case 5: *regp = regs.itt1; break;
14265 + case 6: *regp = regs.dtt0; break;
14266 + case 7: *regp = regs.dtt1; break;
14267 + case 0x800: *regp = regs.usp; break;
14268 + case 0x801: *regp = regs.vbr; break;
14269 + case 0x802: *regp = regs.caar; break;
14270 + case 0x803: *regp = regs.m == 1 ? m68k_areg(regs, 7) : regs.msp; break;
14271 + case 0x804: *regp = regs.m == 0 ? m68k_areg(regs, 7) : regs.isp; break;
14272 + case 0x805: *regp = regs.mmusr; break;
14273 + case 0x806: *regp = regs.urp; break;
14274 + case 0x807: *regp = regs.srp; break;
14276 + write_log("movec2 cpu=%d regno=%lx\n", currprefs.cpu_level, regno);
14277 + op_illg (0x4E7A);
14285 +div_unsigned(uae_u32 src_hi, uae_u32 src_lo, uae_u32 div, uae_u32 *quot, uae_u32 *rem)
14287 + uae_u32 q = 0, cbit = 0;
14290 + if (div <= src_hi) {
14293 + for (i = 0 ; i < 32 ; i++) {
14294 + cbit = src_hi & 0x80000000ul;
14296 + if (src_lo & 0x80000000ul) src_hi++;
14299 + if (cbit || div <= src_hi) {
14309 +void m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra, uaecptr oldpc)
14311 +#if defined(uae_s64)
14313 + Exception (5, oldpc);
14316 + if (extra & 0x800) {
14317 + /* signed variant */
14318 + uae_s64 a = (uae_s64)(uae_s32)m68k_dreg(regs, (extra >> 12) & 7);
14319 + uae_s64 quot, rem;
14321 + if (extra & 0x400) {
14322 + a &= 0xffffffffu;
14323 + a |= (uae_s64)m68k_dreg(regs, extra & 7) << 32;
14325 + rem = a % (uae_s64)(uae_s32)src;
14326 + quot = a / (uae_s64)(uae_s32)src;
14327 + if ((quot & UVAL64(0xffffffff80000000)) != 0
14328 + && (quot & UVAL64(0xffffffff80000000)) != UVAL64(0xffffffff80000000))
14334 + if (((uae_s32)rem < 0) != ((uae_s64)a < 0)) rem = -rem;
14337 + SET_ZFLG (((uae_s32)quot) == 0);
14338 + SET_NFLG (((uae_s32)quot) < 0);
14339 + m68k_dreg(regs, extra & 7) = rem;
14340 + m68k_dreg(regs, (extra >> 12) & 7) = quot;
14344 + uae_u64 a = (uae_u64)(uae_u32)m68k_dreg(regs, (extra >> 12) & 7);
14345 + uae_u64 quot, rem;
14347 + if (extra & 0x400) {
14348 + a &= 0xffffffffu;
14349 + a |= (uae_u64)m68k_dreg(regs, extra & 7) << 32;
14351 + rem = a % (uae_u64)src;
14352 + quot = a / (uae_u64)src;
14353 + if (quot > 0xffffffffu) {
14360 + SET_ZFLG (((uae_s32)quot) == 0);
14361 + SET_NFLG (((uae_s32)quot) < 0);
14362 + m68k_dreg(regs, extra & 7) = rem;
14363 + m68k_dreg(regs, (extra >> 12) & 7) = quot;
14368 + Exception (5, oldpc);
14371 + if (extra & 0x800) {
14372 + /* signed variant */
14373 + uae_s32 lo = (uae_s32)m68k_dreg(regs, (extra >> 12) & 7);
14374 + uae_s32 hi = lo < 0 ? -1 : 0;
14375 + uae_s32 save_high;
14376 + uae_u32 quot, rem;
14379 + if (extra & 0x400) {
14380 + hi = (uae_s32)m68k_dreg(regs, extra & 7);
14383 + sign = (hi ^ src);
14387 + if (lo == 0) hi++;
14389 + if ((uae_s32)src < 0) src = -src;
14390 + if (div_unsigned(hi, lo, src, ", &rem) ||
14391 + (sign & 0x80000000) ? quot > 0x80000000 : quot > 0x7fffffff) {
14396 + if (sign & 0x80000000) quot = -quot;
14397 + if (((uae_s32)rem < 0) != (save_high < 0)) rem = -rem;
14400 + SET_ZFLG (((uae_s32)quot) == 0);
14401 + SET_NFLG (((uae_s32)quot) < 0);
14402 + m68k_dreg(regs, extra & 7) = rem;
14403 + m68k_dreg(regs, (extra >> 12) & 7) = quot;
14407 + uae_u32 lo = (uae_u32)m68k_dreg(regs, (extra >> 12) & 7);
14409 + uae_u32 quot, rem;
14411 + if (extra & 0x400) {
14412 + hi = (uae_u32)m68k_dreg(regs, extra & 7);
14414 + if (div_unsigned(hi, lo, src, ", &rem)) {
14421 + SET_ZFLG (((uae_s32)quot) == 0);
14422 + SET_NFLG (((uae_s32)quot) < 0);
14423 + m68k_dreg(regs, extra & 7) = rem;
14424 + m68k_dreg(regs, (extra >> 12) & 7) = quot;
14430 +STATIC_INLINE void
14431 +mul_unsigned(uae_u32 src1, uae_u32 src2, uae_u32 *dst_hi, uae_u32 *dst_lo)
14433 + uae_u32 r0 = (src1 & 0xffff) * (src2 & 0xffff);
14434 + uae_u32 r1 = ((src1 >> 16) & 0xffff) * (src2 & 0xffff);
14435 + uae_u32 r2 = (src1 & 0xffff) * ((src2 >> 16) & 0xffff);
14436 + uae_u32 r3 = ((src1 >> 16) & 0xffff) * ((src2 >> 16) & 0xffff);
14439 + lo = r0 + ((r1 << 16) & 0xffff0000ul);
14440 + if (lo < r0) r3++;
14442 + lo = r0 + ((r2 << 16) & 0xffff0000ul);
14443 + if (lo < r0) r3++;
14444 + r3 += ((r1 >> 16) & 0xffff) + ((r2 >> 16) & 0xffff);
14449 +void m68k_mull (uae_u32 opcode, uae_u32 src, uae_u16 extra)
14451 +#if defined(uae_s64)
14452 + if (extra & 0x800) {
14453 + /* signed variant */
14454 + uae_s64 a = (uae_s64)(uae_s32)m68k_dreg(regs, (extra >> 12) & 7);
14456 + a *= (uae_s64)(uae_s32)src;
14459 + SET_ZFLG (a == 0);
14460 + SET_NFLG (a < 0);
14461 + if (extra & 0x400)
14462 + m68k_dreg(regs, extra & 7) = a >> 32;
14463 + else if ((a & UVAL64(0xffffffff80000000)) != 0
14464 + && (a & UVAL64(0xffffffff80000000)) != UVAL64(0xffffffff80000000))
14468 + m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a;
14471 + uae_u64 a = (uae_u64)(uae_u32)m68k_dreg(regs, (extra >> 12) & 7);
14473 + a *= (uae_u64)src;
14476 + SET_ZFLG (a == 0);
14477 + SET_NFLG (((uae_s64)a) < 0);
14478 + if (extra & 0x400)
14479 + m68k_dreg(regs, extra & 7) = a >> 32;
14480 + else if ((a & UVAL64(0xffffffff00000000)) != 0) {
14483 + m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a;
14486 + if (extra & 0x800) {
14487 + /* signed variant */
14488 + uae_s32 src1,src2;
14489 + uae_u32 dst_lo,dst_hi;
14492 + src1 = (uae_s32)src;
14493 + src2 = (uae_s32)m68k_dreg(regs, (extra >> 12) & 7);
14494 + sign = (src1 ^ src2);
14495 + if (src1 < 0) src1 = -src1;
14496 + if (src2 < 0) src2 = -src2;
14497 + mul_unsigned((uae_u32)src1,(uae_u32)src2,&dst_hi,&dst_lo);
14498 + if (sign & 0x80000000) {
14499 + dst_hi = ~dst_hi;
14500 + dst_lo = -dst_lo;
14501 + if (dst_lo == 0) dst_hi++;
14505 + SET_ZFLG (dst_hi == 0 && dst_lo == 0);
14506 + SET_NFLG (((uae_s32)dst_hi) < 0);
14507 + if (extra & 0x400)
14508 + m68k_dreg(regs, extra & 7) = dst_hi;
14509 + else if ((dst_hi != 0 || (dst_lo & 0x80000000) != 0)
14510 + && ((dst_hi & 0xffffffff) != 0xffffffff
14511 + || (dst_lo & 0x80000000) != 0x80000000))
14515 + m68k_dreg(regs, (extra >> 12) & 7) = dst_lo;
14518 + uae_u32 dst_lo,dst_hi;
14520 + mul_unsigned(src,(uae_u32)m68k_dreg(regs, (extra >> 12) & 7),&dst_hi,&dst_lo);
14524 + SET_ZFLG (dst_hi == 0 && dst_lo == 0);
14525 + SET_NFLG (((uae_s32)dst_hi) < 0);
14526 + if (extra & 0x400)
14527 + m68k_dreg(regs, extra & 7) = dst_hi;
14528 + else if (dst_hi != 0) {
14531 + m68k_dreg(regs, (extra >> 12) & 7) = dst_lo;
14535 +static char* ccnames[] =
14536 +{ "T ","F ","HI","LS","CC","CS","NE","EQ",
14537 + "VC","VS","PL","MI","GE","LT","GT","LE" };
14539 +void m68k_reset (void)
14541 + write_log("M68K: RESET!\n");
14542 + mmu_set_tc(regs.tc & ~0x8000); /* disable mmu */
14543 + regs.kick_mask = 0x00F80000;
14544 + regs.spcflags = 0;
14545 + if (savestate_state == STATE_RESTORE) {
14546 + m68k_setpc (regs.pc);
14547 + /* MakeFromSR() must not swap stack pointer */
14548 + regs.s = (regs.sr >> 13) & 1;
14550 + /* set stack pointer */
14552 + m68k_areg(regs, 7) = regs.isp;
14554 + m68k_areg(regs, 7) = regs.usp;
14558 + m68k_areg (regs, 7) = phys_get_long (0x00f80000);
14559 + m68k_setpc (phys_get_long (0x00f80004));
14560 + refill_prefetch (m68k_getpc (), 0);
14561 + fill_prefetch_0 ();
14564 + regs.stopped = 0;
14572 + regs.intmask = 7;
14573 + regs.vbr = regs.sfc = regs.dfc = 0;
14574 + regs.fpcr = regs.fpsr = regs.fpiar = 0;
14577 +unsigned long REGPARAM2 op_illg (uae_u32 opcode)
14579 + uaecptr pc = m68k_getpc ();
14581 + if (cloanto_rom && (opcode & 0xF100) == 0x7100) {
14582 + m68k_dreg (regs, (opcode >> 9) & 7) = (uae_s8)(opcode & 0xFF);
14584 + fill_prefetch_0 ();
14588 + compiler_flush_jsr_stack ();
14589 + if (opcode == 0x4E7B && phys_get_long (0x10) == 0 && (pc & 0xF80000) == 0xF80000) {
14590 + write_log ("Your Kickstart requires a 68020 CPU. Giving up.\n");
14592 + set_special (SPCFLAG_BRK);
14593 + quit_program = 1;
14595 + if (opcode == 0xFF0D) {
14596 + if ((pc & 0xF80000) == 0xF80000) {
14597 + /* This is from the dummy Kickstart replacement */
14598 + uae_u16 arg = get_iword (2);
14600 + ersatz_perform (arg);
14601 + fill_prefetch_0 ();
14603 + } else if ((pc & 0xFFFF0000) == RTAREA_BASE) {
14604 + /* User-mode STOP replacement */
14605 + m68k_setstopped (1);
14610 + if ((opcode & 0xF000) == 0xA000 && (pc & 0xFFFF0000) == RTAREA_BASE) {
14613 + call_calltrap (opcode & 0xFFF);
14614 + fill_prefetch_0 ();
14618 + if ((opcode & 0xF000) == 0xF000) {
14619 + Exception(0xB,0);
14622 + if ((opcode & 0xF000) == 0xA000) {
14623 + if ((pc & 0xFFFF0000) == RTAREA_BASE) {
14625 + call_calltrap (opcode & 0xFFF);
14627 + Exception(0xA,0);
14631 + write_log ("Illegal instruction: %04x at %08lx\n", opcode, pc);
14639 +static int n_insns = 0, n_spcinsns = 0;
14641 +static uaecptr last_trace_ad = 0;
14643 +static void do_trace (void)
14645 + if (regs.t0 && currprefs.cpu_level >= 2) {
14647 + /* should also include TRAP, CHK, SR modification FPcc */
14648 + /* probably never used so why bother */
14649 + /* We can afford this to be inefficient... */
14650 + m68k_setpc (m68k_getpc ());
14651 + fill_prefetch_0 ();
14652 + opcode = get_word (regs.pc);
14653 + if (opcode == 0x4e72 /* RTE */
14654 + || opcode == 0x4e74 /* RTD */
14655 + || opcode == 0x4e75 /* RTS */
14656 + || opcode == 0x4e77 /* RTR */
14657 + || opcode == 0x4e76 /* TRAPV */
14658 + || (opcode & 0xffc0) == 0x4e80 /* JSR */
14659 + || (opcode & 0xffc0) == 0x4ec0 /* JMP */
14660 + || (opcode & 0xff00) == 0x6100 /* BSR */
14661 + || ((opcode & 0xf000) == 0x6000 /* Bcc */
14662 + && cctrue((opcode >> 8) & 0xf))
14663 + || ((opcode & 0xf0f0) == 0x5050 /* DBcc */
14664 + && !cctrue((opcode >> 8) & 0xf)
14665 + && (uae_s16)m68k_dreg(regs, opcode & 7) != 0))
14667 + last_trace_ad = m68k_getpc ();
14668 + unset_special (SPCFLAG_TRACE);
14669 + set_special (SPCFLAG_DOTRACE);
14671 + } else if (regs.t1) {
14672 + last_trace_ad = m68k_getpc ();
14673 + unset_special (SPCFLAG_TRACE);
14674 + set_special (SPCFLAG_DOTRACE);
14678 +static int do_specialties (int cycles)
14680 + if (regs.spcflags & SPCFLAG_COPPER)
14683 + /*n_spcinsns++;*/
14684 + while ((regs.spcflags & SPCFLAG_BLTNASTY) && cycles > 0) {
14685 + int c = blitnasty();
14687 + cycles -= 2 * CYCLE_UNIT;
14688 + if (cycles < CYCLE_UNIT)
14692 + do_cycles (c * CYCLE_UNIT);
14693 + if (regs.spcflags & SPCFLAG_COPPER)
14697 + run_compiled_code();
14698 + if (regs.spcflags & SPCFLAG_DOTRACE) {
14699 + Exception (9,last_trace_ad);
14701 + while (regs.spcflags & SPCFLAG_STOP) {
14702 + do_cycles (4 * CYCLE_UNIT);
14703 + if (regs.spcflags & SPCFLAG_COPPER)
14705 + if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)){
14706 + int intr = intlev ();
14707 + unset_special (SPCFLAG_INT | SPCFLAG_DOINT);
14708 + if (intr != -1 && intr > regs.intmask) {
14709 + Interrupt (intr);
14710 + regs.stopped = 0;
14711 + unset_special (SPCFLAG_STOP);
14715 + if (regs.spcflags & SPCFLAG_TRACE)
14718 + if (regs.spcflags & SPCFLAG_DOINT) {
14719 + int intr = intlev ();
14720 + unset_special (SPCFLAG_DOINT);
14721 + if (intr != -1 && intr > regs.intmask) {
14722 + Interrupt (intr);
14723 + regs.stopped = 0;
14726 + if (regs.spcflags & SPCFLAG_INT) {
14727 + unset_special (SPCFLAG_INT);
14728 + set_special (SPCFLAG_DOINT);
14730 + if (regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)) {
14731 + unset_special (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE);
14737 +/* It's really sad to have two almost identical functions for this, but we
14738 + do it all for performance... :( */
14739 +static void m68k_run_1 (void)
14741 +#ifdef DEBUG_PREFETCH
14742 + uae_u8 saved_bytes[20];
14747 + uae_u32 opcode = get_iword_prefetch (0);
14748 +#ifdef DEBUG_PREFETCH
14749 + if (get_ilong (0) != do_get_mem_long (®s.prefetch)) {
14750 + write_log ("Prefetch differs from memory.\n");
14754 + oldpcp = regs.pc_p;
14755 + memcpy (saved_bytes, regs.pc_p, 20);
14757 + /* assert (!regs.stopped && !(regs.spcflags & SPCFLAG_STOP)); */
14758 +/* regs_backup[backup_pointer = (backup_pointer + 1) % 16] = regs;*/
14759 +#if COUNT_INSTRS == 2
14760 + if (table68k[opcode].handler != -1)
14761 + instrcount[table68k[opcode].handler]++;
14762 +#elif COUNT_INSTRS == 1
14763 + instrcount[opcode]++;
14765 +#if defined X86_ASSEMBLY
14766 + __asm__ __volatile__("\tcall *%%ebx"
14767 + : "=&a" (cycles) : "b" (cpufunctbl[opcode]), "0" (opcode)
14768 + : "%edx", "%ecx",
14769 + "%esi", "%edi", "%ebp", "memory", "cc");
14771 + cycles = (*cpufunctbl[opcode])(opcode);
14773 +#ifdef DEBUG_PREFETCH
14774 + if (memcmp (saved_bytes, oldpcp, 20) != 0) {
14775 + write_log ("Self-modifying code detected.\n");
14776 + set_special (SPCFLAG_BRK);
14781 + cycles &= cycles_mask;
14782 + cycles |= cycles_val;
14783 + do_cycles (cycles);
14784 + if (regs.spcflags) {
14785 + if (do_specialties (cycles))
14791 +#define DEBUG_PREFETCH
14793 +/* Same thing, but don't use prefetch to get opcode. */
14794 +static void m68k_run_2 (void)
14798 + uae_u32 opcode = get_iword (0);
14800 + /* assert (!regs.stopped && !(regs.spcflags & SPCFLAG_STOP)); */
14801 +/* regs_backup[backup_pointer = (backup_pointer + 1) % 16] = regs;*/
14802 +#if COUNT_INSTRS == 2
14803 + if (table68k[opcode].handler != -1)
14804 + instrcount[table68k[opcode].handler]++;
14805 +#elif COUNT_INSTRS == 1
14806 + instrcount[opcode]++;
14808 +#if defined X86_ASSEMBLY
14809 + __asm__ __volatile__("\tcall *%%ebx"
14810 + : "=&a" (cycles) : "b" (cpufunctbl[opcode]), "0" (opcode)
14811 + : "%edx", "%ecx",
14812 + "%esi", "%edi", "%ebp", "memory", "cc");
14814 + cycles = (*cpufunctbl[opcode])(opcode);
14818 + cycles &= cycles_mask;
14819 + cycles |= cycles_val;
14820 + do_cycles (cycles);
14821 + if (regs.spcflags) {
14822 + if (do_specialties (cycles))
14828 +#ifdef X86_ASSEMBLY
14829 +STATIC_INLINE void m68k_run1 (void (*func)(void))
14831 + /* Work around compiler bug: GCC doesn't push %ebp in m68k_run_1. */
14832 + __asm__ __volatile__ ("pushl %%ebp\n\tcall *%0\n\tpopl %%ebp"
14833 + : : "r" (func) : "%eax", "%edx", "%ecx", "memory", "cc");
14836 +#define m68k_run1(F) (F) ()
14839 +int in_m68k_go = 0;
14841 +void m68k_go (int may_quit)
14843 + if (in_m68k_go || !may_quit) {
14844 + write_log ("Bug! m68k_go is not reentrant.\n");
14848 + reset_frame_rate_hack ();
14849 + update_68k_cycles ();
14851 +#if MMU_SETJMP_EXCEPTIONS
14852 + setjmp(m68k_exception);
14857 + if (quit_program > 0) {
14858 + if (quit_program == 1)
14860 + quit_program = 0;
14861 + if (savestate_state == STATE_RESTORE) {
14862 + restore_state (savestate_filename);
14864 + activate_debugger ();
14868 + reset_all_systems ();
14870 + /* We may have been restoring state, but we're done now. */
14871 + savestate_restore_finish ();
14872 + handle_active_events ();
14873 + if (regs.spcflags)
14874 + do_specialties (0);
14879 + m68k_run1 (currprefs.cpu_compatible ? m68k_run_1 : m68k_run_2);
14884 +static void m68k_verify (uaecptr addr, uaecptr *nextpc)
14886 + uae_u32 opcode, val;
14887 + struct instr *dp;
14889 + opcode = get_iword_1(0);
14890 + last_op_for_exception_3 = opcode;
14891 + m68kpc_offset = 2;
14893 + if (cpufunctbl[opcode] == op_illg_1) {
14896 + dp = table68k + opcode;
14899 + if (!verify_ea (dp->sreg, dp->smode, dp->size, &val)) {
14900 + Exception (3, 0);
14905 + if (!verify_ea (dp->dreg, dp->dmode, dp->size, &val)) {
14906 + Exception (3, 0);
14912 +void m68k_disasm (FILE *f, uaecptr addr, uaecptr *nextpc, int cnt)
14914 + uaecptr newpc = 0;
14915 + m68kpc_offset = addr - m68k_getpc ();
14916 + while (cnt-- > 0) {
14917 + char instrname[20],*ccpt;
14920 + struct mnemolookup *lookup;
14921 + struct instr *dp;
14923 + fprintf (f, "%08lx: ", m68k_getpc () + m68kpc_offset);
14924 + for (opwords = 0; opwords < 5; opwords++){
14925 + fprintf (f, "%04x ", get_iword_1 (m68kpc_offset + opwords*2));
14927 + opcode = get_iword_1 (m68kpc_offset);
14928 + m68kpc_offset += 2;
14929 + if (cpufunctbl[opcode] == op_illg_1) {
14932 + dp = table68k + opcode;
14933 + for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
14936 + strcpy (instrname, lookup->name);
14937 + ccpt = strstr (instrname, "cc");
14939 + strncpy (ccpt, ccnames[dp->cc], 2);
14941 + fprintf (f, "%s", instrname);
14942 + switch (dp->size){
14943 + case sz_byte: fprintf (f, ".B "); break;
14944 + case sz_word: fprintf (f, ".W "); break;
14945 + case sz_long: fprintf (f, ".L "); break;
14946 + default: fprintf (f, " "); break;
14950 + newpc = m68k_getpc () + m68kpc_offset;
14951 + newpc += ShowEA (f, dp->sreg, dp->smode, dp->size, 0);
14953 + if (dp->suse && dp->duse)
14954 + fprintf (f, ",");
14956 + newpc = m68k_getpc () + m68kpc_offset;
14957 + newpc += ShowEA (f, dp->dreg, dp->dmode, dp->size, 0);
14960 + if (cctrue(dp->cc))
14961 + fprintf (f, " == %08lx (TRUE)", newpc);
14963 + fprintf (f, " == %08lx (FALSE)", newpc);
14964 + } else if ((opcode & 0xff00) == 0x6100) /* BSR */
14965 + fprintf (f, " == %08lx", newpc);
14966 + fprintf (f, "\n");
14969 + *nextpc = m68k_getpc () + m68kpc_offset;
14972 +void m68k_dumpstate (FILE *f, uaecptr *nextpc)
14975 + for (i = 0; i < 8; i++){
14976 + fprintf (f, "D%d: %08lx ", i, m68k_dreg(regs, i));
14977 + if ((i & 3) == 3) fprintf (f, "\n");
14979 + for (i = 0; i < 8; i++){
14980 + fprintf (f, "A%d: %08lx ", i, m68k_areg(regs, i));
14981 + if ((i & 3) == 3) fprintf (f, "\n");
14983 + if (regs.s == 0) regs.usp = m68k_areg(regs, 7);
14984 + if (regs.s && regs.m) regs.msp = m68k_areg(regs, 7);
14985 + if (regs.s && regs.m == 0) regs.isp = m68k_areg(regs, 7);
14986 + fprintf (f, "USP=%08lx ISP=%08lx MSP=%08lx VBR=%08lx\n",
14987 + regs.usp,regs.isp,regs.msp,regs.vbr);
14988 + fprintf (f, "T=%d%d S=%d M=%d X=%d N=%d Z=%d V=%d C=%d IMASK=%d\n",
14989 + regs.t1, regs.t0, regs.s, regs.m,
14990 + GET_XFLG, GET_NFLG, GET_ZFLG, GET_VFLG, GET_CFLG, regs.intmask);
14991 + for (i = 0; i < 8; i++){
14992 + fprintf (f, "FP%d: %g ", i, regs.fp[i]);
14993 + if ((i & 3) == 3) fprintf (f, "\n");
14995 + fprintf (f, "N=%d Z=%d I=%d NAN=%d\n",
14996 + (regs.fpsr & 0x8000000) != 0,
14997 + (regs.fpsr & 0x4000000) != 0,
14998 + (regs.fpsr & 0x2000000) != 0,
14999 + (regs.fpsr & 0x1000000) != 0);
15000 + if (currprefs.cpu_compatible)
15001 + fprintf (f, "prefetch %08lx\n", (unsigned long)do_get_mem_long(®s.prefetch));
15003 + fprintf (f, "this PC: %08lx\n", m68k_getpc());
15004 + m68k_disasm (f, m68k_getpc (), nextpc, 1);
15006 + fprintf (f, "next PC: %08lx\n", *nextpc);
15010 +/* {{{ CPU save/restore code */
15012 +#define CPUTYPE_EC 1
15013 +#define CPUMODE_HALT 1
15015 +uae_u8 *restore_cpu (uae_u8 *src)
15017 + int i,model,flags;
15020 + model = restore_u32();
15023 + currprefs.cpu_level = 0;
15026 + currprefs.cpu_level = 1;
15029 + currprefs.cpu_level = 2;
15032 + write_log ("Unknown cpu type %d\n", model);
15036 + flags = restore_u32();
15037 + currprefs.address_space_24 = 0;
15038 + if (flags & CPUTYPE_EC)
15039 + currprefs.address_space_24 = 1;
15040 + for (i = 0; i < 15; i++)
15041 + regs.regs[i] = restore_u32 ();
15042 + regs.pc = restore_u32 ();
15043 + /* We don't actually use this - we deliberately set prefetch_pc to a
15044 + zero so that prefetch isn't used for the first insn after a state
15046 + regs.prefetch = restore_u32 ();
15047 + regs.prefetch_pc = regs.pc + 128;
15048 + regs.usp = restore_u32 ();
15049 + regs.isp = restore_u32 ();
15050 + regs.sr = restore_u16 ();
15051 + l = restore_u32();
15052 + if (l & CPUMODE_HALT) {
15053 + regs.stopped = 1;
15054 + set_special (SPCFLAG_STOP);
15056 + regs.stopped = 0;
15057 + if (model >= 68010) {
15058 + regs.dfc = restore_u32 ();
15059 + regs.sfc = restore_u32 ();
15060 + regs.vbr = restore_u32 ();
15062 + if (model >= 68020) {
15063 + regs.caar = restore_u32 ();
15064 + regs.cacr = restore_u32 ();
15065 + regs.msp = restore_u32 ();
15067 + write_log ("CPU %d%s%03d, PC=%08.8X\n",
15068 + model/1000, flags & 1 ? "EC" : "", model % 1000, regs.pc);
15073 +static int cpumodel[] = { 68000, 68010, 68020, 68020 };
15075 +uae_u8 *save_cpu (int *len)
15077 + uae_u8 *dstbak,*dst;
15080 + dstbak = dst = malloc(4+4+15*4+4+4+4+4+2+4+4+4+4+4+4+4);
15081 + model = cpumodel[currprefs.cpu_level];
15082 + save_u32 (model); /* MODEL */
15083 + save_u32 (currprefs.address_space_24 ? 1 : 0); /* FLAGS */
15084 + for(i = 0;i < 15; i++) save_u32 (regs.regs[i]); /* D0-D7 A0-A6 */
15085 + save_u32 (m68k_getpc ()); /* PC */
15086 + save_u32 (regs.prefetch); /* prefetch */
15088 + save_u32 (!regs.s ? regs.regs[15] : regs.usp); /* USP */
15089 + save_u32 (regs.s ? regs.regs[15] : regs.isp); /* ISP */
15090 + save_u16 (regs.sr); /* SR/CCR */
15091 + save_u32 (regs.stopped ? CPUMODE_HALT : 0); /* flags */
15092 + if(model >= 68010) {
15093 + save_u32 (regs.dfc); /* DFC */
15094 + save_u32 (regs.sfc); /* SFC */
15095 + save_u32 (regs.vbr); /* VBR */
15097 + if(model >= 68020) {
15098 + save_u32 (regs.caar); /* CAAR */
15099 + save_u32 (regs.cacr); /* CACR */
15100 + save_u32 (regs.msp); /* MSP */
15102 + *len = dst - dstbak;
15108 diff -urN src-0.8.22/src/picasso96.c src-0.8.22-mmu/src/picasso96.c
15109 --- src-0.8.22/src/picasso96.c 2002-02-27 14:08:18.000000000 +0100
15110 +++ src-0.8.22-mmu/src/picasso96.c 2003-07-25 12:36:00.000000000 +0200
15111 @@ -131,7 +131,7 @@
15114 uaecptr amigamodeinfoptr;
15115 - struct LibResolution *uaememptr = (struct LibResolution *) get_mem_bank (amigalibresptr).xlateaddr (amigalibresptr);
15116 + struct LibResolution *uaememptr = (struct LibResolution *)get_real_address(amigalibresptr);
15120 @@ -333,7 +333,7 @@
15121 char *uaememptr = 0;
15124 - uaememptr = gfxmem_xlate (amigamemptr); /* I know that amigamemptr is inside my gfxmem chunk, so I can just do the xlate() */
15125 + uaememptr = get_real_address(amigamemptr);
15126 memset (uaememptr, 0, PSSO_LibResolution_sizeof); /* zero out our LibResolution structure */
15127 strcpy (uaememptr + PSSO_LibResolution_P96ID, libres->P96ID);
15128 put_long (amigamemptr + PSSO_LibResolution_DisplayID, libres->DisplayID);
15129 @@ -767,7 +767,7 @@
15130 res->Modes[TRUEALPHA] = amigamemptr;
15133 - uaememptr = gfxmem_xlate (amigamemptr); /* I know that amigamemptr is inside my gfxmem chunk, so I can just do the xlate() */
15134 + uaememptr = get_real_address(amigamemptr);
15135 memset (uaememptr, 0, PSSO_ModeInfo_sizeof); /* zero out our ModeInfo struct */
15137 put_word (amigamemptr + PSSO_ModeInfo_Width, dm->res.width);
15138 @@ -839,6 +839,11 @@
15139 int ModeInfoStructureCount = 1, LibResolutionStructureCount = 0;
15140 uaecptr amigamemptr = 0;
15141 uaecptr AmigaBoardInfo = m68k_areg (regs, 2);
15143 + if (regs.mmu_enabled) {
15144 + mmu_make_transparent_region(gfxmem_start, allocated_gfxmem, 1);
15147 put_word (AmigaBoardInfo + PSSO_BoardInfo_BitsPerCannon, DX_BitsPerCannon ());
15148 put_word (AmigaBoardInfo + PSSO_BoardInfo_RGBFormats, picasso96_pixel_format);
15149 put_word (AmigaBoardInfo + PSSO_BoardInfo_SoftSpriteFlags, picasso96_pixel_format);
15150 diff -urN src-0.8.22/src/picasso96.c~ src-0.8.22-mmu/src/picasso96.c~
15151 --- src-0.8.22/src/picasso96.c~ 1970-01-01 01:00:00.000000000 +0100
15152 +++ src-0.8.22-mmu/src/picasso96.c~ 2003-07-25 12:11:11.000000000 +0200
15155 + * UAE - The U*nix Amiga Emulator
15157 + * Picasso96 Support Module
15159 + * Copyright 1997 Brian King <Brian_King@Mitel.com, Brian_King@Cloanto.com>
15161 + * Theory of operation:
15162 + * On the Amiga side, a Picasso card consists mainly of a memory area that
15163 + * contains the frame buffer. On the UAE side, we allocate a block of memory
15164 + * that will hold the frame buffer. This block is in normal memory, it is
15165 + * never directly on the graphics card. All graphics operations, which are
15166 + * mainly reads and writes into this block and a few basic operations like
15167 + * filling a rectangle, operate on this block of memory.
15168 + * Since the memory is not on the graphics card, some work must be done to
15169 + * synchronize the display with the data in the Picasso frame buffer. There
15170 + * are various ways to do this. One possibility is to allocate a second
15171 + * buffer of the same size, and perform all write operations twice. Since
15172 + * we never read from the second buffer, it can actually be placed in video
15173 + * memory. The X11 driver could be made to use the Picasso frame buffer as
15174 + * the data buffer of an XImage, which could then be XPutImage()d from time
15175 + * to time. Another possibility is to translate all Picasso accesses into
15176 + * Xlib (or GDI, or whatever your graphics system is) calls. This possibility
15177 + * is a bit tricky, since there is a risk of generating very many single pixel
15178 + * accesses which may be rather slow.
15181 + * - add panning capability
15182 + * - we want to add a manual switch to override SetSwitch for hardware banging
15183 + * programs started from a Picasso workbench.
15186 +#include "sysconfig.h"
15187 +#include "sysdeps.h"
15189 +#include "config.h"
15190 +#include "options.h"
15191 +#include "threaddep/thread.h"
15193 +#include "memory.h"
15194 +#include "custom.h"
15195 +#include "newcpu.h"
15197 +#include "picasso96.h"
15201 +#define P96TRACING_ENABLED 0
15202 +#if P96TRACING_ENABLED
15203 +#define P96TRACE(x) do { write_log x; } while(0)
15205 +#define P96TRACE(x)
15208 +static uae_u32 gfxmem_lget (uaecptr) REGPARAM;
15209 +static uae_u32 gfxmem_wget (uaecptr) REGPARAM;
15210 +static uae_u32 gfxmem_bget (uaecptr) REGPARAM;
15211 +static void gfxmem_lput (uaecptr, uae_u32) REGPARAM;
15212 +static void gfxmem_wput (uaecptr, uae_u32) REGPARAM;
15213 +static void gfxmem_bput (uaecptr, uae_u32) REGPARAM;
15214 +static int gfxmem_check (uaecptr addr, uae_u32 size) REGPARAM;
15215 +static uae_u8 *gfxmem_xlate (uaecptr addr) REGPARAM;
15217 +static void write_gfx_long (uaecptr addr, uae_u32 value);
15218 +static void write_gfx_word (uaecptr addr, uae_u16 value);
15219 +static void write_gfx_byte (uaecptr addr, uae_u8 value);
15221 +static uae_u8 all_ones_bitmap, all_zeros_bitmap;
15223 +struct picasso96_state_struct picasso96_state;
15224 +struct picasso_vidbuf_description picasso_vidinfo;
15226 +/* These are the maximum resolutions... They are filled in by GetSupportedResolutions() */
15227 +/* have to fill this in, otherwise problems occur
15228 + * @@@ ??? what problems?
15230 +struct ScreenResolution planar = { 320, 240 };
15231 +struct ScreenResolution chunky = { 640, 480 };
15232 +struct ScreenResolution hicolour = { 640, 480 };
15233 +struct ScreenResolution truecolour = { 640, 480 };
15234 +struct ScreenResolution alphacolour = { 640, 480 };
15236 +uae_u16 picasso96_pixel_format = RGBFF_CHUNKY;
15238 +struct PicassoResolution DisplayModes[MAX_PICASSO_MODES];
15240 +static int mode_count = 0;
15242 +static int set_gc_called = 0;
15243 +static int set_panning_called = 0;
15244 +/* Address of the screen in the Amiga frame buffer at the time of the last
15245 + SetPanning call. */
15246 +static uaecptr oldscr;
15248 +static uae_u32 p2ctab[256][2];
15251 + * Debugging dumps
15254 +static void DumpModeInfoStructure (uaecptr amigamodeinfoptr)
15256 + write_log ("ModeInfo Structure Dump:\n");
15257 + write_log (" Node.ln_Succ = 0x%x\n", get_long (amigamodeinfoptr));
15258 + write_log (" Node.ln_Pred = 0x%x\n", get_long (amigamodeinfoptr + 4));
15259 + write_log (" Node.ln_Type = 0x%x\n", get_byte (amigamodeinfoptr + 8));
15260 + write_log (" Node.ln_Pri = %d\n", get_byte (amigamodeinfoptr + 9));
15261 + /*write_log (" Node.ln_Name = %s\n", uaememptr->Node.ln_Name); */
15262 + write_log (" OpenCount = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_OpenCount));
15263 + write_log (" Active = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_Active));
15264 + write_log (" Width = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_Width));
15265 + write_log (" Height = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_Height));
15266 + write_log (" Depth = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_Depth));
15267 + write_log (" Flags = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_Flags));
15268 + write_log (" HorTotal = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_HorTotal));
15269 + write_log (" HorBlankSize = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_HorBlankSize));
15270 + write_log (" HorSyncStart = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_HorSyncStart));
15271 + write_log (" HorSyncSize = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_HorSyncSize));
15272 + write_log (" HorSyncSkew = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_HorSyncSkew));
15273 + write_log (" HorEnableSkew = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_HorEnableSkew));
15274 + write_log (" VerTotal = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_VerTotal));
15275 + write_log (" VerBlankSize = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_VerBlankSize));
15276 + write_log (" VerSyncStart = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_VerSyncStart));
15277 + write_log (" VerSyncSize = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_VerSyncSize));
15278 + write_log (" Clock = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_first_union));
15279 + write_log (" ClockDivide = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_second_union));
15280 + write_log (" PixelClock = %d\n", get_long (amigamodeinfoptr + PSSO_ModeInfo_PixelClock));
15283 +static void DumpLibResolutionStructure (uaecptr amigalibresptr)
15286 + uaecptr amigamodeinfoptr;
15287 + struct LibResolution *uaememptr = (struct LibResolution *)get_real_address(amigalibresptr);
15291 + write_log ("LibResolution Structure Dump:\n");
15293 + if (get_long (amigalibresptr + PSSO_LibResolution_DisplayID) == 0xFFFFFFFF) {
15294 + write_log (" Finished With LibResolutions...\n");
15296 + write_log (" Name = %s\n", uaememptr->P96ID);
15297 + write_log (" DisplayID = 0x%x\n", get_long (amigalibresptr + PSSO_LibResolution_DisplayID));
15298 + write_log (" Width = %d\n", get_word (amigalibresptr + PSSO_LibResolution_Width));
15299 + write_log (" Height = %d\n", get_word (amigalibresptr + PSSO_LibResolution_Height));
15300 + write_log (" Flags = %d\n", get_word (amigalibresptr + PSSO_LibResolution_Flags));
15301 + for (i = 0; i < MAXMODES; i++) {
15302 + amigamodeinfoptr = get_long (amigalibresptr + PSSO_LibResolution_Modes + i * 4);
15303 + write_log (" ModeInfo[%d] = 0x%x\n", i, amigamodeinfoptr);
15304 + if (amigamodeinfoptr)
15305 + DumpModeInfoStructure (amigamodeinfoptr);
15307 + write_log (" BoardInfo = 0x%x\n", get_long (amigalibresptr + PSSO_LibResolution_BoardInfo));
15311 +static char binary_byte[9];
15313 +static char *BuildBinaryString (uae_u8 value)
15316 + for (i = 0; i < 8; i++) {
15317 + binary_byte[i] = (value & (1 << (7 - i))) ? '#' : '.';
15319 + binary_byte[8] = '\0';
15320 + return binary_byte;
15323 +static void DumpPattern (struct Pattern *patt)
15327 + for (row = 0; row < (1 << patt->Size); row++) {
15328 + mem = patt->Memory + row * 2;
15329 + for (col = 0; col < 2; col++) {
15330 + write_log ("%s", BuildBinaryString (*mem++));
15332 + write_log ("\n");
15336 +static void DumpTemplate (struct Template *tmp, uae_u16 w, uae_u16 h)
15338 + uae_u8 *mem = tmp->Memory;
15339 + int row, col, width;
15340 + width = (w + 7) >> 3;
15341 + write_log ("xoffset = %d, bpr = %d\n", tmp->XOffset, tmp->BytesPerRow);
15342 + for (row = 0; row < h; row++) {
15343 + mem = tmp->Memory + row * tmp->BytesPerRow;
15344 + for (col = 0; col < width; col++) {
15345 + write_log ("%s", BuildBinaryString (*mem++));
15347 + write_log ("\n");
15351 +int picasso_nr_resolutions (void)
15353 + return mode_count;
15356 +static void ShowSupportedResolutions (void)
15362 + for (i = 0; i < mode_count; i++)
15363 + write_log ("%s\n", DisplayModes[i].name);
15366 +static uae_u8 GetBytesPerPixel (uae_u32 RGBfmt)
15368 + switch (RGBfmt) {
15372 + case RGBFB_A8R8G8B8:
15373 + case RGBFB_A8B8G8R8:
15374 + case RGBFB_R8G8B8A8:
15375 + case RGBFB_B8G8R8A8:
15378 + case RGBFB_B8G8R8:
15379 + case RGBFB_R8G8B8:
15382 + case RGBFB_R5G5B5:
15383 + case RGBFB_R5G6B5:
15384 + case RGBFB_R5G6B5PC:
15385 + case RGBFB_R5G5B5PC:
15386 + case RGBFB_B5G6R5PC:
15387 + case RGBFB_B5G5R5PC:
15390 + write_log ("ERROR - GetBytesPerPixel() was unsuccessful with 0x%x?!\n", RGBfmt);
15396 + * Amiga <-> native structure conversion functions
15399 +static int CopyRenderInfoStructureA2U (uaecptr amigamemptr, struct RenderInfo *ri)
15401 + uaecptr memp = get_long (amigamemptr + PSSO_RenderInfo_Memory);
15403 + if (valid_address (memp, PSSO_RenderInfo_sizeof)) {
15404 + ri->Memory = get_real_address (memp);
15405 + ri->BytesPerRow = get_word (amigamemptr + PSSO_RenderInfo_BytesPerRow);
15406 + ri->RGBFormat = get_long (amigamemptr + PSSO_RenderInfo_RGBFormat);
15409 + write_log ("ERROR - Invalid RenderInfo memory area...\n");
15413 +static int CopyPatternStructureA2U (uaecptr amigamemptr, struct Pattern *pattern)
15415 + uaecptr memp = get_long (amigamemptr + PSSO_Pattern_Memory);
15416 + if (valid_address (memp, PSSO_Pattern_sizeof)) {
15417 + pattern->Memory = get_real_address (memp);
15418 + pattern->XOffset = get_word (amigamemptr + PSSO_Pattern_XOffset);
15419 + pattern->YOffset = get_word (amigamemptr + PSSO_Pattern_YOffset);
15420 + pattern->FgPen = get_long (amigamemptr + PSSO_Pattern_FgPen);
15421 + pattern->BgPen = get_long (amigamemptr + PSSO_Pattern_BgPen);
15422 + pattern->Size = get_byte (amigamemptr + PSSO_Pattern_Size);
15423 + pattern->DrawMode = get_byte (amigamemptr + PSSO_Pattern_DrawMode);
15426 + write_log ("ERROR - Invalid Pattern memory area...\n");
15430 +static void CopyColorIndexMappingA2U (uaecptr amigamemptr, struct ColorIndexMapping *cim)
15433 + cim->ColorMask = get_long (amigamemptr);
15434 + for (i = 0; i < 256; i++, amigamemptr += 4)
15435 + cim->Colors[i] = get_long (amigamemptr + 4);
15438 +static int CopyBitMapStructureA2U (uaecptr amigamemptr, struct BitMap *bm)
15442 + bm->BytesPerRow = get_word (amigamemptr + PSSO_BitMap_BytesPerRow);
15443 + bm->Rows = get_word (amigamemptr + PSSO_BitMap_Rows);
15444 + bm->Flags = get_byte (amigamemptr + PSSO_BitMap_Flags);
15445 + bm->Depth = get_byte (amigamemptr + PSSO_BitMap_Depth);
15447 + for (i = 0; i < bm->Depth; i++) {
15448 + uaecptr plane = get_long (amigamemptr + PSSO_BitMap_Planes + i * 4);
15451 + bm->Planes[i] = &all_zeros_bitmap;
15454 + bm->Planes[i] = &all_ones_bitmap;
15457 + if (valid_address (plane, bm->BytesPerRow * bm->Rows))
15458 + bm->Planes[i] = get_real_address (plane);
15467 +static int CopyTemplateStructureA2U (uaecptr amigamemptr, struct Template *tmpl)
15469 + uaecptr memp = get_long (amigamemptr + PSSO_Template_Memory);
15471 + if (valid_address (memp, 1 /* FIXME */ )) {
15472 + tmpl->Memory = get_real_address (memp);
15473 + tmpl->BytesPerRow = get_word (amigamemptr + PSSO_Template_BytesPerRow);
15474 + tmpl->XOffset = get_byte (amigamemptr + PSSO_Template_XOffset);
15475 + tmpl->DrawMode = get_byte (amigamemptr + PSSO_Template_DrawMode);
15476 + tmpl->FgPen = get_long (amigamemptr + PSSO_Template_FgPen);
15477 + tmpl->BgPen = get_long (amigamemptr + PSSO_Template_BgPen);
15480 + write_log ("ERROR - Invalid Template memory area...\n");
15484 +static void CopyLibResolutionStructureU2A (struct LibResolution *libres, uaecptr amigamemptr)
15486 + char *uaememptr = 0;
15489 + uaememptr = get_real_address(amigamemptr);
15490 + memset (uaememptr, 0, PSSO_LibResolution_sizeof); /* zero out our LibResolution structure */
15491 + strcpy (uaememptr + PSSO_LibResolution_P96ID, libres->P96ID);
15492 + put_long (amigamemptr + PSSO_LibResolution_DisplayID, libres->DisplayID);
15493 + put_word (amigamemptr + PSSO_LibResolution_Width, libres->Width);
15494 + put_word (amigamemptr + PSSO_LibResolution_Height, libres->Height);
15495 + put_word (amigamemptr + PSSO_LibResolution_Flags, libres->Flags);
15496 + for (i = 0; i < MAXMODES; i++)
15497 + put_long (amigamemptr + PSSO_LibResolution_Modes + i * 4, libres->Modes[i]);
15499 + put_long (amigamemptr, libres->Node.ln_Succ);
15500 + put_long (amigamemptr + 4, libres->Node.ln_Pred);
15501 + put_byte (amigamemptr + 8, libres->Node.ln_Type);
15502 + put_byte (amigamemptr + 9, libres->Node.ln_Pri);
15504 + put_long (amigamemptr + 10, amigamemptr + PSSO_LibResolution_P96ID);
15505 + put_long (amigamemptr + PSSO_LibResolution_BoardInfo, libres->BoardInfo);
15508 +/* list is Amiga address of list, in correct endian format for UAE
15509 + * node is Amiga address of node, in correct endian format for UAE */
15510 +static void AmigaListAddTail (uaecptr list, uaecptr node)
15512 + uaecptr amigamemptr = 0;
15514 + if (get_long (list + 8) == list) {
15515 + /* Empty list - set it up */
15516 + put_long (list, node); /* point the lh_Head to our new node */
15517 + put_long (list + 4, 0); /* set the lh_Tail to NULL */
15518 + put_long (list + 8, node); /* point the lh_TailPred to our new node */
15520 + /* Adjust the new node - don't rely on it being zeroed out */
15521 + put_long (node, 0); /* ln_Succ */
15522 + put_long (node + 4, 0); /* ln_Pred */
15524 + amigamemptr = get_long (list + 8); /* get the lh_TailPred contents */
15526 + put_long (list + 8, node); /* point the lh_TailPred to our new node */
15528 + /* Adjust the previous lh_TailPred node */
15529 + put_long (amigamemptr, node); /* point the ln_Succ to our new node */
15531 + /* Adjust the new node - don't rely on it being zeroed out */
15532 + put_long (node, 0); /* ln_Succ */
15533 + put_long (node + 4, amigamemptr); /* ln_Pred */
15538 + * Functions to perform an action on the real screen
15542 + * Fill a rectangle on the screen. src points to the start of a line of the
15543 + * filled rectangle in the frame buffer; it can be used as a memcpy source if
15544 + * there is no OS specific function to fill the rectangle.
15547 +static void do_fillrect (uae_u8 * src, int x, int y, int width, int height,
15548 + uae_u32 pen, int Bpp, RGBFTYPE rgbtype)
15553 + x -= picasso96_state.XOffset;
15554 + y -= picasso96_state.YOffset;
15563 + if (x + width > picasso96_state.Width)
15564 + width = picasso96_state.Width - x;
15565 + if (y + height > picasso96_state.Height)
15566 + height = picasso96_state.Height - y;
15568 + if (width <= 0 || height <= 0)
15571 + /* Try OS specific fillrect function here; and return if successful. */
15573 + DX_Invalidate (y, y + height - 1);
15574 + if (!picasso_vidinfo.extra_mem)
15577 + width *= picasso96_state.BytesPerPixel;
15578 + dst = gfx_lock_picasso ();
15582 + dst += y * picasso_vidinfo.rowbytes + x * picasso_vidinfo.pixbytes;
15583 + if (picasso_vidinfo.rgbformat == picasso96_state.RGBFormat) {
15585 + while (height-- > 0) {
15586 + memset (dst, pen, width);
15587 + dst += picasso_vidinfo.rowbytes;
15590 + while (height-- > 0) {
15591 + memcpy (dst, src, width);
15592 + dst += picasso_vidinfo.rowbytes;
15596 + int psiz = GetBytesPerPixel (picasso_vidinfo.rgbformat);
15597 + if (picasso96_state.RGBFormat != RGBFB_CHUNKY)
15600 + while (height-- > 0) {
15604 + for (i = 0; i < width; i++)
15605 + *((uae_u16 *) dst + i) = picasso_vidinfo.clut[src[i]];
15608 + for (i = 0; i < width; i++)
15609 + *((uae_u32 *) dst + i) = picasso_vidinfo.clut[src[i]];
15614 + dst += picasso_vidinfo.rowbytes;
15618 + gfx_unlock_picasso ();
15622 + * This routine modifies the real screen buffer after a blit has been
15623 + * performed in the save area. If can_do_blit is nonzero, the blit can
15624 + * be performed within the real screen buffer; otherwise, this routine
15625 + * must do it by hand using the data in the save area, pointed to by
15629 +static void do_blit (struct RenderInfo *ri, int Bpp, int srcx, int srcy,
15630 + int dstx, int dsty, int width, int height,
15631 + BLIT_OPCODE opcode, int can_do_blit)
15633 + int xoff = picasso96_state.XOffset;
15634 + int yoff = picasso96_state.YOffset;
15635 + uae_u8 *srcp, *dstp;
15640 + if (srcy < yoff || srcx < xoff
15641 + || srcx - xoff + width > picasso96_state.Width
15642 + || srcy - yoff + height > picasso96_state.Height)
15656 + if (dstx + width > picasso96_state.Width)
15657 + width = picasso96_state.Width - dstx;
15658 + if (dsty + height > picasso96_state.Height)
15659 + height = picasso96_state.Height - dsty;
15660 + if (width <= 0 || height <= 0)
15663 + /* If this RenderInfo points at something else than the currently visible
15664 + * screen, we must ignore the blit. */
15665 + if (can_do_blit) {
15667 + * Call OS blitting function that can do it in video memory.
15668 + * Should return if it was successful
15672 + /* If no OS blit available, we do a copy from the P96 framebuffer in Amiga
15673 + memory to the host's frame buffer. */
15674 + DX_Invalidate (dsty, dsty + height - 1);
15675 + if (!picasso_vidinfo.extra_mem)
15678 + dstp = gfx_lock_picasso ();
15681 + dstp += dsty * picasso_vidinfo.rowbytes + dstx * picasso_vidinfo.pixbytes;
15682 + P96TRACE(("do_blit with srcp 0x%x, dstp 0x%x, dst_rowbytes %d, srcx %d, srcy %d, dstx %d, dsty %d, w %d, h %d, dst_pixbytes %d\n",
15683 + srcp, dstp, picasso_vidinfo.rowbytes, srcx, srcy, dstx, dsty, width, height, picasso_vidinfo.pixbytes));
15684 + P96TRACE(("gfxmem is at 0x%x\n",gfxmemory));
15686 + srcp = ri->Memory + srcx * Bpp + srcy * ri->BytesPerRow;
15687 + if (picasso_vidinfo.rgbformat == picasso96_state.RGBFormat) {
15689 + while (height-- > 0) {
15690 + memcpy (dstp, srcp, width);
15691 + srcp += ri->BytesPerRow;
15692 + dstp += picasso_vidinfo.rowbytes;
15695 + int psiz = GetBytesPerPixel (picasso_vidinfo.rgbformat);
15696 + if (picasso96_state.RGBFormat != RGBFB_CHUNKY)
15699 + while (height-- > 0) {
15703 + for (i = 0; i < width; i++)
15704 + *((uae_u16 *) dstp + i) = picasso_vidinfo.clut[srcp[i]];
15707 + for (i = 0; i < width; i++)
15708 + *((uae_u32 *) dstp + i) = picasso_vidinfo.clut[srcp[i]];
15713 + srcp += ri->BytesPerRow;
15714 + dstp += picasso_vidinfo.rowbytes;
15718 + gfx_unlock_picasso ();
15722 + * Invert a rectangle on the screen.
15725 +static void do_invertrect (struct RenderInfo *ri, int Bpp, int x, int y, int width, int height)
15729 + x -= picasso96_state.XOffset;
15730 + y -= picasso96_state.YOffset;
15739 + if (x + width > picasso96_state.Width)
15740 + width = picasso96_state.Width - x;
15741 + if (y + height > picasso96_state.Height)
15742 + height = picasso96_state.Height - y;
15744 + if (width <= 0 || height <= 0)
15748 + /* TODO: Try OS specific invertrect function here; and return if successful. */
15750 + do_blit (ri, Bpp, x, y, x, y, width, height, BLIT_SRC, 0);
15753 +static uaecptr wgfx_linestart;
15754 +static uaecptr wgfx_lineend;
15755 +static uaecptr wgfx_min, wgfx_max;
15756 +static long wgfx_y;
15758 +static void wgfx_do_flushline (void)
15760 + int src_y = wgfx_y;
15761 + long x0, x1, width;
15762 + uae_u8 *src, *dstp;
15763 + int Bpp = GetBytesPerPixel (picasso_vidinfo.rgbformat);
15764 + int fb_bpp = picasso96_state.BytesPerPixel;
15766 + wgfx_y -= picasso96_state.YOffset;
15767 + if (wgfx_y < 0 || wgfx_y >= picasso96_state.Height)
15770 + DX_Invalidate (wgfx_y, wgfx_y);
15771 + if (!picasso_vidinfo.extra_mem)
15774 + x0 = wgfx_min - wgfx_linestart;
15775 + width = wgfx_max - wgfx_min;
15776 + x0 -= picasso96_state.XOffset * fb_bpp;
15782 + if (x0 + width > picasso96_state.Width * fb_bpp)
15783 + width = picasso96_state.Width * fb_bpp - x0;
15785 + dstp = gfx_lock_picasso ();
15789 + P96TRACE(("flushing %d\n", wgfx_y));
15790 + src = gfxmemory + wgfx_min;
15792 + if (picasso_vidinfo.rgbformat == picasso96_state.RGBFormat) {
15793 + dstp += wgfx_y * picasso_vidinfo.rowbytes + x0;
15794 + memcpy (dstp, src, width);
15798 + if (picasso96_state.RGBFormat != RGBFB_CHUNKY)
15801 + dstp += wgfx_y * picasso_vidinfo.rowbytes + x0 * Bpp;
15804 + for (i = 0; i < width; i++)
15805 + *((uae_u16 *) dstp + i) = picasso_vidinfo.clut[src[i]];
15808 + for (i = 0; i < width; i++)
15809 + *((uae_u32 *) dstp + i) = picasso_vidinfo.clut[src[i]];
15817 + gfx_unlock_picasso ();
15819 + wgfx_linestart = 0xFFFFFFFF;
15822 +STATIC_INLINE void wgfx_flushline (void)
15824 + if (wgfx_linestart == 0xFFFFFFFF || !picasso_on)
15826 + wgfx_do_flushline ();
15829 +static int renderinfo_is_current_screen (struct RenderInfo *ri)
15833 + if (ri->Memory != gfxmemory + (picasso96_state.Address - gfxmem_start))
15839 +/* Clear our screen, since we've got a new Picasso screen-mode, and refresh with the proper contents
15840 + * This is called on several occasions:
15841 + * 1. Amiga-->Picasso transition, via SetSwitch()
15842 + * 2. Picasso-->Picasso transition, via SetPanning().
15843 + * 3. whenever the graphics code notifies us that the screen contents have been lost.
15845 +void picasso_refresh (void)
15847 + struct RenderInfo ri;
15852 + /* Make sure that the first time we show a Picasso video mode, we don't blit any crap.
15853 + * We can do this by checking if we have an Address yet. */
15854 + if (picasso96_state.Address) {
15855 + unsigned int width, height;
15856 + /* blit the stuff from our static frame-buffer to the gfx-card */
15857 + ri.Memory = gfxmemory + (picasso96_state.Address - gfxmem_start);
15858 + ri.BytesPerRow = picasso96_state.BytesPerRow;
15859 + ri.RGBFormat = picasso96_state.RGBFormat;
15861 + if (set_panning_called) {
15862 + width = picasso96_state.VirtualWidth;
15863 + height = picasso96_state.VirtualHeight;
15865 + width = picasso96_state.Width;
15866 + height = picasso96_state.Height;
15869 + do_blit (&ri, picasso96_state.BytesPerPixel, 0, 0, 0, 0, width, height, BLIT_SRC, 0);
15871 + write_log ("ERROR - picasso_refresh() can't refresh!\n");
15875 + * BOOL FindCard(struct BoardInfo *bi); and
15877 + * FindCard is called in the first stage of the board initialisation and
15878 + * configuration and is used to look if there is a free and unconfigured
15879 + * board of the type the driver is capable of managing. If it finds one,
15880 + * it immediately reserves it for use by Picasso96, usually by clearing
15881 + * the CDB_CONFIGME bit in the flags field of the ConfigDev struct of
15882 + * this expansion card. But this is only a common example, a driver can
15883 + * do whatever it wants to mark this card as used by the driver. This
15884 + * mechanism is intended to ensure that a board is only configured and
15885 + * used by one driver. FindBoard also usually fills some fields of the
15886 + * BoardInfo struct supplied by the caller, the rtg.library, for example
15887 + * the MemoryBase, MemorySize and RegisterBase fields.
15889 +uae_u32 picasso_FindCard (void)
15891 + uaecptr AmigaBoardInfo = m68k_areg (regs, 0);
15892 + /* NOTES: See BoardInfo struct definition in Picasso96 dev info */
15894 + if (allocated_gfxmem && !picasso96_state.CardFound) {
15895 + /* Fill in MemoryBase, MemorySize */
15896 + put_long (AmigaBoardInfo + PSSO_BoardInfo_MemoryBase, gfxmem_start);
15897 + /* size of memory, minus a 32K chunk: 16K for pattern bitmaps, 16K for resolution list */
15898 + put_long (AmigaBoardInfo + PSSO_BoardInfo_MemorySize, allocated_gfxmem - 32768);
15900 + picasso96_state.CardFound = 1; /* mark our "card" as being found */
15906 +static void FillBoardInfo (uaecptr amigamemptr, struct LibResolution *res, struct PicassoResolution *dm)
15909 + switch (dm->depth) {
15911 + res->Modes[CHUNKY] = amigamemptr;
15914 + res->Modes[HICOLOR] = amigamemptr;
15917 + res->Modes[TRUECOLOR] = amigamemptr;
15920 + res->Modes[TRUEALPHA] = amigamemptr;
15923 + uaememptr = get_real_address(amigamemptr);
15924 + memset (uaememptr, 0, PSSO_ModeInfo_sizeof); /* zero out our ModeInfo struct */
15926 + put_word (amigamemptr + PSSO_ModeInfo_Width, dm->res.width);
15927 + put_word (amigamemptr + PSSO_ModeInfo_Height, dm->res.height);
15928 + put_byte (amigamemptr + PSSO_ModeInfo_Depth, dm->depth * 8);
15929 + put_byte (amigamemptr + PSSO_ModeInfo_Flags, 0);
15930 + put_word (amigamemptr + PSSO_ModeInfo_HorTotal, dm->res.width);
15931 + put_word (amigamemptr + PSSO_ModeInfo_HorBlankSize, 0);
15932 + put_word (amigamemptr + PSSO_ModeInfo_HorSyncStart, 0);
15933 + put_word (amigamemptr + PSSO_ModeInfo_HorSyncSize, 0);
15934 + put_byte (amigamemptr + PSSO_ModeInfo_HorSyncSkew, 0);
15935 + put_byte (amigamemptr + PSSO_ModeInfo_HorEnableSkew, 0);
15937 + put_word (amigamemptr + PSSO_ModeInfo_VerTotal, dm->res.height);
15938 + put_word (amigamemptr + PSSO_ModeInfo_VerBlankSize, 0);
15939 + put_word (amigamemptr + PSSO_ModeInfo_VerSyncStart, 0);
15940 + put_word (amigamemptr + PSSO_ModeInfo_VerSyncSize, 0);
15942 + put_byte (amigamemptr + PSSO_ModeInfo_first_union, 98);
15943 + put_byte (amigamemptr + PSSO_ModeInfo_second_union, 14);
15945 + put_long (amigamemptr + PSSO_ModeInfo_PixelClock, dm->res.width * dm->res.height * dm->refresh);
15948 +static uae_u32 AssignModeID (int i, int count)
15950 + if (DisplayModes[i].res.width == 320 && DisplayModes[i].res.height == 200)
15951 + return 0x50001000;
15952 + else if (DisplayModes[i].res.width == 320 && DisplayModes[i].res.height == 240)
15953 + return 0x50011000;
15954 + else if (DisplayModes[i].res.width == 640 && DisplayModes[i].res.height == 400)
15955 + return 0x50021000;
15956 + else if (DisplayModes[i].res.width == 640 && DisplayModes[i].res.height == 480)
15957 + return 0x50031000;
15958 + else if (DisplayModes[i].res.width == 800 && DisplayModes[i].res.height == 600)
15959 + return 0x50041000;
15960 + else if (DisplayModes[i].res.width == 1024 && DisplayModes[i].res.height == 768)
15961 + return 0x50051000;
15962 + else if (DisplayModes[i].res.width == 1152 && DisplayModes[i].res.height == 864)
15963 + return 0x50061000;
15964 + else if (DisplayModes[i].res.width == 1280 && DisplayModes[i].res.height == 1024)
15965 + return 0x50071000;
15966 + else if (DisplayModes[i].res.width == 1600 && DisplayModes[i].res.height == 1280)
15967 + return 0x50081000;
15969 + return 0x50091000 + count * 0x10000;
15972 +/****************************************
15975 +* a2: BoardInfo structure ptr - Amiga-based address in Intel endian-format
15977 +* Job - fill in the following structure members:
15978 +* gbi_RGBFormats: the pixel formats that the host-OS of UAE supports
15979 +* If UAE is running in a window, it should ONLY report the pixel format of the host-OS desktop
15980 +* If UAE is running full-screen, it should report ALL pixel formats that the host-OS can handle in full-screen
15981 +* NOTE: If full-screen, and the user toggles to windowed-mode, all hell will break loose visually. Must inform
15982 +* user that they're doing something stupid (unless their desktop and full-screen colour modes match).
15983 +* gbi_SoftSpriteFlags: should be the same as above for now, until actual cursor support is added
15984 +* gbi_BitsPerCannon: could be 6 or 8 or ???, depending on the host-OS gfx-card
15985 +* gbi_MaxHorResolution: fill this in for all modes (even if you don't support them)
15986 +* gbi_MaxVerResolution: fill this in for all modes (even if you don't support them)
15988 +uae_u32 picasso_InitCard (void)
15990 + struct LibResolution res;
15992 + int ModeInfoStructureCount = 1, LibResolutionStructureCount = 0;
15993 + uaecptr amigamemptr = 0;
15994 + uaecptr AmigaBoardInfo = m68k_areg (regs, 2);
15996 + if (regs.mmu_enabled) {
15997 + mmu_make_transparent_region(gfxmem_start, allocated_gfxmem, 1);
16000 + put_word (AmigaBoardInfo + PSSO_BoardInfo_BitsPerCannon, DX_BitsPerCannon ());
16001 + put_word (AmigaBoardInfo + PSSO_BoardInfo_RGBFormats, picasso96_pixel_format);
16002 + put_word (AmigaBoardInfo + PSSO_BoardInfo_SoftSpriteFlags, picasso96_pixel_format);
16003 + put_long (AmigaBoardInfo + PSSO_BoardInfo_BoardType, BT_uaegfx);
16004 + put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxHorResolution + 0, planar.width);
16005 + put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxHorResolution + 2, chunky.width);
16006 + put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxHorResolution + 4, hicolour.width);
16007 + put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxHorResolution + 6, truecolour.width);
16008 + put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxHorResolution + 8, alphacolour.width);
16009 + put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxVerResolution + 0, planar.height);
16010 + put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxVerResolution + 2, chunky.height);
16011 + put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxVerResolution + 4, hicolour.height);
16012 + put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxVerResolution + 6, truecolour.height);
16013 + put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxVerResolution + 8, alphacolour.height);
16015 + for (i = 0; i < mode_count;) {
16017 + /* Add a LibResolution structure to the ResolutionsList MinList in our BoardInfo */
16018 + res.DisplayID = AssignModeID (i, LibResolutionStructureCount);
16019 + res.BoardInfo = AmigaBoardInfo;
16020 + res.Width = DisplayModes[i].res.width;
16021 + res.Height = DisplayModes[i].res.height;
16022 + res.Flags = P96F_PUBLIC;
16023 + res.P96ID[0] = 'P';
16024 + res.P96ID[1] = '9';
16025 + res.P96ID[2] = '6';
16026 + res.P96ID[3] = '-';
16027 + res.P96ID[4] = '0';
16028 + res.P96ID[5] = ':';
16029 + strcpy (res.Name, "uaegfx:");
16030 + strncat (res.Name, DisplayModes[i].name, strchr (DisplayModes[i].name, ',') - DisplayModes[i].name);
16031 + res.Modes[PLANAR] = 0;
16032 + res.Modes[CHUNKY] = 0;
16033 + res.Modes[HICOLOR] = 0;
16034 + res.Modes[TRUECOLOR] = 0;
16035 + res.Modes[TRUEALPHA] = 0;
16038 + /* Handle this display mode's depth */
16039 + /* Only add the modes when there is enough P96 RTG memory to hold the bitmap */
16040 + long required = DisplayModes[i].res.width * DisplayModes[i].res.height * DisplayModes[i].depth;
16041 + if (allocated_gfxmem - 32768 > required) {
16042 + amigamemptr = gfxmem_start + allocated_gfxmem - (PSSO_ModeInfo_sizeof * ModeInfoStructureCount++);
16043 + FillBoardInfo (amigamemptr, &res, &DisplayModes[i]);
16046 + } while (i < mode_count
16047 + && DisplayModes[i].res.width == DisplayModes[j].res.width
16048 + && DisplayModes[i].res.height == DisplayModes[j].res.height);
16050 + amigamemptr = gfxmem_start + allocated_gfxmem - 16384 + (PSSO_LibResolution_sizeof * LibResolutionStructureCount++);
16051 + CopyLibResolutionStructureU2A (&res, amigamemptr);
16052 + DumpLibResolutionStructure (amigamemptr);
16053 + AmigaListAddTail (AmigaBoardInfo + PSSO_BoardInfo_ResolutionsList, amigamemptr);
16059 +extern int x_size, y_size;
16063 + * a0: struct BoardInfo
16064 + * d0.w: BOOL state
16065 + * this function should set a board switch to let the Amiga signal pass
16066 + * through when supplied with a 0 in d0 and to show the board signal if
16067 + * a 1 is passed in d0. You should remember the current state of the
16068 + * switch to avoid unneeded switching. If your board has no switch, then
16069 + * simply supply a function that does nothing except a RTS.
16071 + * NOTE: Return the opposite of the switch-state. BDK
16073 +uae_u32 picasso_SetSwitch (void)
16075 + uae_u16 flag = m68k_dreg (regs, 0) & 0xFFFF;
16077 + /* Do not switch immediately. Tell the custom chip emulation about the
16078 + * desired state, and wait for custom.c to call picasso_enablescreen
16079 + * whenever it is ready to change the screen state. */
16080 + picasso_requested_on = !!flag;
16082 + write_log ("SetSwitch() - trying to show %s screen\n", flag ? "picasso96" : "amiga");
16084 + /* Put old switch-state in D0 */
16088 +void picasso_enablescreen (int on)
16090 + wgfx_linestart = 0xFFFFFFFF;
16091 + picasso_refresh ();
16093 + write_log ("SetSwitch() - showing %s screen\n", on ? "picasso96" : "amiga");
16097 +static int first_color_changed = 256;
16098 +static int last_color_changed = -1;
16100 +void picasso_handle_vsync (void)
16102 + if (first_color_changed < last_color_changed) {
16103 + DX_SetPalette (first_color_changed, last_color_changed - first_color_changed);
16104 + /* If we're emulating a CLUT mode, we need to redraw the entire screen. */
16105 + if (picasso_vidinfo.rgbformat != picasso96_state.RGBFormat)
16106 + picasso_refresh ();
16109 + first_color_changed = 256;
16110 + last_color_changed = -1;
16113 +void picasso_clip_mouse (int *px, int *py)
16115 + int xoff = picasso96_state.XOffset;
16116 + int yoff = picasso96_state.YOffset;
16119 + if (*px + xoff > picasso_vidinfo.width)
16120 + *px = picasso_vidinfo.width - xoff;
16123 + if (*py + yoff > picasso_vidinfo.height)
16124 + *py = picasso_vidinfo.height - yoff;
16129 + * a0: struct BoardInfo
16130 + * d0.w: startindex
16132 + * when this function is called, your driver has to fetch "count" color
16133 + * values starting at "startindex" from the CLUT field of the BoardInfo
16134 + * structure and write them to the hardware. The color values are always
16135 + * between 0 and 255 for each component regardless of the number of bits
16136 + * per cannon your board has. So you might have to shift the colors
16137 + * before writing them to the hardware.
16139 +uae_u32 picasso_SetColorArray (void)
16141 + /* Fill in some static UAE related structure about this new CLUT setting
16142 + * We need this for CLUT-based displays, and for mapping CLUT to hi/true colour */
16143 + uae_u16 start = m68k_dreg (regs, 0);
16144 + uae_u16 count = m68k_dreg (regs, 1);
16146 + uaecptr boardinfo = m68k_areg (regs, 0);
16147 + uaecptr clut = boardinfo + PSSO_BoardInfo_CLUT + start * 3;
16150 + for (i = start; i < start + count; i++) {
16151 + int r = get_byte (clut);
16152 + int g = get_byte (clut + 1);
16153 + int b = get_byte (clut + 2);
16155 + changed |= (picasso96_state.CLUT[i].Red != r || picasso96_state.CLUT[i].Green != g || picasso96_state.CLUT[i].Blue != b);
16157 + picasso96_state.CLUT[i].Red = r;
16158 + picasso96_state.CLUT[i].Green = g;
16159 + picasso96_state.CLUT[i].Blue = b;
16163 + if (start < first_color_changed)
16164 + first_color_changed = start;
16165 + if (start + count > last_color_changed)
16166 + last_color_changed = start + count;
16168 + /*write_log ("SetColorArray(%d,%d)\n", start, count); */
16174 + * a0: struct BoardInfo
16175 + * d7: RGBFTYPE RGBFormat
16176 + * This function is called whenever the RGB format of the display changes,
16177 + * e.g. from chunky to TrueColor. Usually, all you have to do is to set
16178 + * the RAMDAC of your board accordingly.
16180 +uae_u32 picasso_SetDAC (void)
16182 + /* Fill in some static UAE related structure about this new DAC setting
16183 + * Lets us keep track of what pixel format the Amiga is thinking about in our frame-buffer */
16185 + write_log ("SetDAC()\n");
16189 +static void init_picasso_screen (void)
16191 + int width = picasso96_state.Width;
16192 + int height = picasso96_state.Height;
16193 + int vwidth = picasso96_state.VirtualWidth;
16194 + int vheight = picasso96_state.VirtualHeight;
16198 + if (!set_gc_called)
16201 + if (set_panning_called) {
16202 + picasso96_state.Extent = picasso96_state.Address + (picasso96_state.BytesPerRow * vheight);
16203 + xoff = picasso96_state.XOffset;
16204 + yoff = picasso96_state.YOffset;
16207 + gfx_set_picasso_modeinfo (width, height, picasso96_state.GC_Depth, picasso96_state.RGBFormat);
16208 + DX_SetPalette (0, 256);
16210 + wgfx_linestart = 0xFFFFFFFF;
16211 + picasso_refresh ();
16216 + * a0: struct BoardInfo
16217 + * a1: struct ModeInfo
16218 + * d0: BOOL Border
16219 + * This function is called whenever another ModeInfo has to be set. This
16220 + * function simply sets up the CRTC and TS registers to generate the
16221 + * timing used for that screen mode. You should not set the DAC, clocks
16222 + * or linear start adress. They will be set when appropriate by their
16225 +uae_u32 picasso_SetGC (void)
16227 + /* Fill in some static UAE related structure about this new ModeInfo setting */
16228 + uaecptr modeinfo = m68k_areg (regs, 1);
16230 + picasso96_state.Width = get_word (modeinfo + PSSO_ModeInfo_Width);
16231 + picasso96_state.VirtualWidth = picasso96_state.Width; /* in case SetPanning doesn't get called */
16233 + picasso96_state.Height = get_word (modeinfo + PSSO_ModeInfo_Height);
16234 + picasso96_state.VirtualHeight = picasso96_state.Height;
16236 + picasso96_state.GC_Depth = get_byte (modeinfo + PSSO_ModeInfo_Depth);
16237 + picasso96_state.GC_Flags = get_byte (modeinfo + PSSO_ModeInfo_Flags);
16239 + P96TRACE (("SetGC(%d,%d,%d)\n", picasso96_state.Width, picasso96_state.Height, picasso96_state.GC_Depth));
16241 + set_gc_called = 1; /* @@@ when do we need to reset this? */
16242 + init_picasso_screen ();
16248 + * a0: struct BoardInfo
16249 + * a1: UBYTE *Memory
16250 + * d0: uae_u16 Width
16251 + * d1: WORD XOffset
16252 + * d2: WORD YOffset
16253 + * d7: RGBFTYPE RGBFormat
16254 + * This function sets the view origin of a display which might also be
16255 + * overscanned. In register a1 you get the start address of the screen
16256 + * bitmap on the Amiga side. You will have to subtract the starting
16257 + * address of the board memory from that value to get the memory start
16258 + * offset within the board. Then you get the offset in pixels of the
16259 + * left upper edge of the visible part of an overscanned display. From
16260 + * these values you will have to calculate the LinearStartingAddress
16261 + * fields of the CRTC registers.
16263 + * NOTE: SetPanning() can be used to know when a Picasso96 screen is
16264 + * being opened. Better to do the appropriate clearing of the
16265 + * background here than in SetSwitch() derived functions,
16266 + * because SetSwitch() is not called for subsequent Picasso screens.
16268 +uae_u32 picasso_SetPanning (void)
16270 + uae_u16 Width = m68k_dreg (regs, 0);
16271 + uaecptr start_of_screen = m68k_areg (regs, 1);
16272 + uaecptr bi = m68k_areg (regs, 0);
16273 + uaecptr bmeptr = get_long (bi + PSSO_BoardInfo_BitMapExtra); /* Get our BoardInfo ptr's BitMapExtra ptr */
16274 + int oldxoff = picasso96_state.XOffset;
16275 + int oldyoff = picasso96_state.YOffset;
16277 + /* @@@ This is in WinUAE, but it breaks things. */
16278 + if (oldscr == 0) {
16279 + oldscr = start_of_screen;
16281 + if ((oldscr != start_of_screen)) {
16282 + set_gc_called = 0;
16283 + oldscr = start_of_screen;
16287 + picasso96_state.Address = start_of_screen; /* Amiga-side address */
16288 + picasso96_state.XOffset = (uae_s16) m68k_dreg (regs, 1);
16289 + picasso96_state.YOffset = (uae_s16) m68k_dreg (regs, 2);
16290 + picasso96_state.VirtualWidth = get_word (bmeptr + PSSO_BitMapExtra_Width);
16291 + picasso96_state.VirtualHeight = get_word (bmeptr + PSSO_BitMapExtra_Height);
16292 + picasso96_state.RGBFormat = m68k_dreg (regs, 7);
16293 + picasso96_state.BytesPerPixel = GetBytesPerPixel (picasso96_state.RGBFormat);
16294 + picasso96_state.BytesPerRow = Width * picasso96_state.BytesPerPixel;
16296 + set_panning_called = 1;
16297 + P96TRACE (("SetPanning(%d, %d, %d) Start 0x%x, BPR %d\n",
16298 + Width, picasso96_state.XOffset, picasso96_state.YOffset, start_of_screen, picasso96_state.BytesPerRow));
16300 + init_picasso_screen ();
16302 + lastmx += oldxoff - picasso96_state.XOffset;
16303 + lastmy += oldyoff - picasso96_state.YOffset;
16308 +static void do_xor8 (uae_u8 * ptr, long len, uae_u32 val)
16311 +#if 0 && defined ALIGN_POINTER_TO32
16312 + int align_adjust = ALIGN_POINTER_TO32 (ptr);
16315 + len -= align_adjust;
16316 + while (align_adjust) {
16322 + len -= len2 << 2;
16323 + for (i = 0; i < len2; i++, ptr += 4) {
16324 + *(uae_u32 *) ptr ^= val;
16333 + for (i = 0; i < len; i++, ptr++) {
16334 + do_put_mem_byte (ptr, do_get_mem_byte (ptr) ^ val);
16342 + * a0:struct BoardInfo *bi
16343 + * a1:struct RenderInfo *ri
16351 + * This function is used to invert a rectangular area on the board. It is called by BltBitMap,
16352 + * BltPattern and BltTemplate.
16354 +uae_u32 picasso_InvertRect (void)
16356 + uaecptr renderinfo = m68k_areg (regs, 1);
16357 + unsigned long X = (uae_u16) m68k_dreg (regs, 0);
16358 + unsigned long Y = (uae_u16) m68k_dreg (regs, 1);
16359 + unsigned long Width = (uae_u16) m68k_dreg (regs, 2);
16360 + unsigned long Height = (uae_u16) m68k_dreg (regs, 3);
16361 + uae_u32 mask = m68k_dreg (regs, 4);
16362 + int Bpp = GetBytesPerPixel (m68k_dreg (regs, 7));
16364 + unsigned int lines;
16365 + struct RenderInfo ri;
16367 + unsigned long width_in_bytes;
16369 + wgfx_flushline ();
16371 + if (!CopyRenderInfoStructureA2U (renderinfo, &ri))
16374 + P96TRACE (("InvertRect: X %d Y %d Width %d Height %d\n", X, Y, Width, Height));
16375 + /*write_log ("InvertRect %d %lx\n", Bpp, (long)mask); */
16377 + /* ??? Brian? mask used to be 32 bit, but it appears that only 8 bit
16378 + * values are passed to this function. This code here seems to work
16379 + * much better... */
16380 + if (mask != 0xFF && Bpp > 1) {
16381 + write_log ("InvertRect: not obeying mask 0x%x properly with Bpp %d.\n", mask, Bpp);
16384 + if ((mask & ~0xFF) != 0) {
16385 + write_log ("InvertRect: mask has high bits set!\n");
16387 + xorval = 0x01010101 * (mask & 0xFF);
16388 + width_in_bytes = Bpp * Width;
16389 + uae_mem = ri.Memory + Y * ri.BytesPerRow + X * Bpp;
16391 + for (lines = 0; lines < Height; lines++, uae_mem += ri.BytesPerRow)
16392 + do_xor8 (uae_mem, width_in_bytes, xorval);
16394 + if (renderinfo_is_current_screen (&ri)) {
16395 + if (mask == 0xFF)
16396 + do_invertrect (&ri, Bpp, X, Y, Width, Height);
16398 + do_blit (&ri, Bpp, X, Y, X, Y, Width, Height, BLIT_SRC, 0);
16401 + return 1; /* 1 if supported, 0 otherwise */
16404 +/* Fill a rectangle in the Amiga-memory frame buffer. */
16406 +STATIC_INLINE void do_fillrect_frame_buffer (struct RenderInfo *ri, int X, int Y,
16407 + int Width, int Height, uae_u32 Pen, int Bpp,
16408 + RGBFTYPE RGBFormat)
16410 + uae_u8 *start, *oldstart, *dst;
16411 + long lines, cols;
16413 + /* Do our virtual frame-buffer memory. First, we do a single line fill by hand */
16414 + oldstart = start = ri->Memory + Y * ri->BytesPerRow + X * Bpp;
16417 + memset (start, Pen, Width);
16420 + for (cols = 0; cols < Width; cols++) {
16421 + do_put_mem_word ((uae_u16 *) start, Pen);
16426 + for (cols = 0; cols < Width; cols++) {
16427 + do_put_mem_byte (start, Pen & 0x000000FF);
16429 + *(uae_u16 *) (start) = (Pen & 0x00FFFF00) >> 8;
16434 + for (cols = 0; cols < Width; cols++) {
16435 + /**start = Pen; */
16436 + do_put_mem_long ((uae_u32 *) start, Pen);
16442 + dst = oldstart + ri->BytesPerRow;
16443 + /* next, we do the remaining line fills via memcpy() for > 1 BPP, otherwise some more memset() calls */
16445 + for (lines = 0; lines < (Height - 1); lines++, dst += ri->BytesPerRow)
16446 + memcpy (dst, oldstart, Width * Bpp);
16448 + for (lines = 0; lines < (Height - 1); lines++, dst += ri->BytesPerRow)
16449 + memset (dst, Pen, Width);
16454 +/***********************************************************
16456 +***********************************************************
16457 +* a0: struct BoardInfo *
16458 +* a1: struct RenderInfo *
16465 +* d7: uae_u32 RGBFormat
16466 +***********************************************************/
16467 +uae_u32 picasso_FillRect (void)
16469 + uaecptr renderinfo = m68k_areg (regs, 1);
16470 + unsigned long X = (uae_u16) m68k_dreg (regs, 0);
16471 + unsigned long Y = (uae_u16) m68k_dreg (regs, 1);
16472 + unsigned long Width = (uae_u16) m68k_dreg (regs, 2);
16473 + unsigned long Height = (uae_u16) m68k_dreg (regs, 3);
16474 + uae_u32 Pen = m68k_dreg (regs, 4);
16475 + uae_u8 Mask = (uae_u8) m68k_dreg (regs, 5);
16476 + uae_u32 RGBFormat = m68k_dreg (regs, 7);
16479 + struct RenderInfo ri;
16481 + wgfx_flushline ();
16483 + if (!CopyRenderInfoStructureA2U (renderinfo, &ri) || Y == 0xFFFF)
16486 + P96TRACE(("FillRect(%d, %d, %d, %d) Pen 0x%x BPP %d BPR %d Mask 0x%x\n",
16487 + X, Y, Width, Height, Pen, Bpp, ri.BytesPerRow, Mask));
16489 + if (ri.RGBFormat != RGBFormat)
16490 + write_log ("Weird Stuff!\n");
16492 + Bpp = GetBytesPerPixel (RGBFormat);
16494 + /* write_log ("FillRect(%d, %d, %d, %d) Pen 0x%x BPP %d BPR %d Mask 0x%x\n",
16495 + X, Y, Width, Height, Pen, Bpp, ri.BytesPerRow, Mask); */
16497 + if (Mask == 0xFF) {
16498 + do_fillrect_frame_buffer (&ri, X, Y, Width, Height, Pen, Bpp, RGBFormat);
16500 + if (renderinfo_is_current_screen (&ri))
16501 + do_fillrect (ri.Memory + Y * ri.BytesPerRow + X * Bpp, X, Y,
16502 + Width, Height, Pen, Bpp, RGBFormat);
16507 + /* We get here only if Mask != 0xFF */
16509 + write_log ("Picasso: mask != 0xFF in truecolor mode!\n");
16516 + uae_u8 *start = ri.Memory + Y * ri.BytesPerRow + X * Bpp;
16517 + uae_u8 *end = start + Height * ri.BytesPerRow;
16518 + for (; start != end; start += ri.BytesPerRow) {
16519 + uae_u8 *p = start;
16520 + unsigned long cols;
16521 + for (cols = 0; cols < Width; cols++) {
16522 + uae_u32 tmpval = do_get_mem_byte (p + cols) & Mask;
16523 + do_put_mem_byte (p + cols, Pen | tmpval);
16528 + if (renderinfo_is_current_screen (&ri))
16529 + do_blit (&ri, Bpp, X, Y, X, Y, Width, Height, BLIT_SRC, 0);
16535 + * BlitRect() is a generic (any chunky pixel format) rectangle copier
16536 + * NOTE: If dstri is NULL, then we're only dealing with one RenderInfo area, and called from picasso_BlitRect()
16538 +static void BlitRect (struct RenderInfo *ri, struct RenderInfo *dstri,
16539 + unsigned long srcx, unsigned long srcy, unsigned long dstx, unsigned long dsty,
16540 + unsigned long width, unsigned long height, uae_u8 mask, BLIT_OPCODE opcode)
16542 + uae_u8 *src, *dst, *tmp, *tmp2, *tmp3;
16543 + unsigned long lines;
16544 + uae_u8 Bpp = GetBytesPerPixel (ri->RGBFormat);
16546 + unsigned long total_width = width * Bpp;
16547 + unsigned long linewidth = (total_width + 15) & ~15;
16548 + int cant_blit = 1;
16551 + * If we have no destination RenderInfo, then we're dealing with a single-buffer action, called
16552 + * from picasso_BlitRect(). The code up to the DX_xxxxx() functions deals with the frame-buffer,
16553 + * while the DX_ functions actually deal with the visible screen.
16555 + * If we have a destination RenderInfo, then we've been called from picasso_BlitRectNoMaskComplete()
16556 + * and we need to put the results on the screen from the frame-buffer.
16558 + if (dstri == NULL) {
16563 + /* Do our virtual frame-buffer memory first */
16564 + src = ri->Memory + srcx * Bpp + srcy * ri->BytesPerRow;
16565 + dst = dstri->Memory + dstx * Bpp + dsty * dstri->BytesPerRow;
16567 + if (mask != 0xFF && Bpp > 1)
16568 + write_log ("ERROR - not obeying BlitRect() mask 0x%x properly with Bpp %d.\n", mask, Bpp);
16570 + if (mask == 0xFF || Bpp > 1) {
16571 + /* handle normal case efficiently */
16572 + if (ri->Memory == dstri->Memory && dsty == srcy) {
16574 + for (i = 0; i < height; i++, src += ri->BytesPerRow, dst += dstri->BytesPerRow)
16575 + memmove (dst, src, total_width);
16576 + } else if (dsty < srcy) {
16578 + for (i = 0; i < height; i++, src += ri->BytesPerRow, dst += dstri->BytesPerRow)
16579 + memcpy (dst, src, total_width);
16582 + src += (height - 1) * ri->BytesPerRow;
16583 + dst += (height - 1) * dstri->BytesPerRow;
16584 + for (i = 0; i < height; i++, src -= ri->BytesPerRow, dst -= dstri->BytesPerRow)
16585 + memcpy (dst, src, total_width);
16588 + srcx = dstx, srcy = dsty;
16589 + if (renderinfo_is_current_screen (dstri))
16590 + do_blit (dstri, Bpp, srcx, srcy, dstx, dsty, width, height, opcode, !cant_blit);
16594 + tmp3 = tmp2 = tmp = xmalloc (linewidth * height); /* allocate enough memory for the src-rect */
16598 + /* copy the src-rect into our temporary buffer space */
16599 + for (lines = 0; lines < height; lines++, src += ri->BytesPerRow, tmp2 += linewidth) {
16600 + memcpy (tmp2, src, total_width);
16603 + /* copy the temporary buffer to the destination */
16604 + for (lines = 0; lines < height; lines++, dst += dstri->BytesPerRow, tmp += linewidth) {
16605 + unsigned long cols;
16606 + for (cols = 0; cols < width; cols++) {
16607 + dst[cols] &= ~mask;
16608 + dst[cols] |= tmp[cols] & mask;
16611 + if (renderinfo_is_current_screen (dstri))
16612 + do_blit (dstri, Bpp, dstx, dsty, dstx, dsty, width, height, opcode, 0);
16614 + /* free the temp-buf */
16619 +/***********************************************************
16621 +***********************************************************
16622 +* a0: struct BoardInfo
16623 +* a1: struct RenderInfo
16631 +* d7: uae_u32 RGBFormat
16632 +***********************************************************/
16633 +uae_u32 picasso_BlitRect (void)
16635 + uaecptr renderinfo = m68k_areg (regs, 1);
16636 + unsigned long srcx = (uae_u16) m68k_dreg (regs, 0);
16637 + unsigned long srcy = (uae_u16) m68k_dreg (regs, 1);
16638 + unsigned long dstx = (uae_u16) m68k_dreg (regs, 2);
16639 + unsigned long dsty = (uae_u16) m68k_dreg (regs, 3);
16640 + unsigned long width = (uae_u16) m68k_dreg (regs, 4);
16641 + unsigned long height = (uae_u16) m68k_dreg (regs, 5);
16642 + uae_u8 Mask = (uae_u8) m68k_dreg (regs, 6);
16644 + struct RenderInfo ri;
16646 + wgfx_flushline ();
16648 + if (!CopyRenderInfoStructureA2U (renderinfo, &ri))
16651 + P96TRACE(("BlitRect(%d, %d, %d, %d, %d, %d, 0x%x)\n", srcx, srcy, dstx, dsty, width, height, Mask));
16652 + BlitRect (&ri, NULL, srcx, srcy, dstx, dsty, width, height, Mask, BLIT_SRC);
16653 + /*write_log ("BlitRect(%d, %d, %d, %d, %d, %d, 0x%x)\n", srcx, srcy, dstx, dsty, width, height, Mask); */
16658 +/***********************************************************
16659 +BlitRectNoMaskComplete:
16660 +***********************************************************
16661 +* a0: struct BoardInfo
16662 +* a1: struct RenderInfo (src)
16663 +* a2: struct RenderInfo (dst)
16670 +* d6: UBYTE OpCode
16671 +* d7: uae_u32 RGBFormat
16672 +* NOTE: MUST return 0 in D0 if we're not handling this operation
16673 +* because the RGBFormat or opcode aren't supported.
16674 +* OTHERWISE return 1
16675 +***********************************************************/
16676 +uae_u32 picasso_BlitRectNoMaskComplete (void)
16678 + uaecptr srcri = m68k_areg (regs, 1);
16679 + uaecptr dstri = m68k_areg (regs, 2);
16680 + unsigned long srcx = (uae_u16) m68k_dreg (regs, 0);
16681 + unsigned long srcy = (uae_u16) m68k_dreg (regs, 1);
16682 + unsigned long dstx = (uae_u16) m68k_dreg (regs, 2);
16683 + unsigned long dsty = (uae_u16) m68k_dreg (regs, 3);
16684 + unsigned long width = (uae_u16) m68k_dreg (regs, 4);
16685 + unsigned long height = (uae_u16) m68k_dreg (regs, 5);
16686 + uae_u8 OpCode = m68k_dreg (regs, 6);
16687 + uae_u32 RGBFmt = m68k_dreg (regs, 7);
16688 + struct RenderInfo src_ri, dst_ri;
16690 + wgfx_flushline ();
16692 + if (!CopyRenderInfoStructureA2U (srcri, &src_ri)
16693 + || !CopyRenderInfoStructureA2U (dstri, &dst_ri))
16696 + P96TRACE(("BlitRectNoMaskComplete() op 0x%2x, xy(%4d,%4d) --> xy(%4d,%4d), wh(%4d,%4d)\n",
16697 + OpCode, srcx, srcy, dstx, dsty, width, height));
16699 + switch (OpCode) {
16701 + BlitRect (&src_ri, &dst_ri, srcx, srcy, dstx, dsty, width, height, 0xFF, OpCode);
16710 +/* This utility function is used both by BlitTemplate() and BlitPattern() */
16711 +STATIC_INLINE void PixelWrite1 (uae_u8 * mem, int bits, uae_u32 fgpen, uae_u32 mask)
16713 + if (mask != 0xFF)
16714 + fgpen = (fgpen & mask) | (do_get_mem_byte (mem + bits) & ~mask);
16715 + do_put_mem_byte (mem + bits, fgpen);
16718 +STATIC_INLINE void PixelWrite2 (uae_u8 * mem, int bits, uae_u32 fgpen)
16720 + do_put_mem_word (((uae_u16 *) mem) + bits, fgpen);
16723 +STATIC_INLINE void PixelWrite3 (uae_u8 * mem, int bits, uae_u32 fgpen)
16725 + do_put_mem_byte (mem + bits * 3, fgpen & 0x000000FF);
16726 + *(uae_u16 *) (mem + bits * 3 + 1) = (fgpen & 0x00FFFF00) >> 8;
16729 +STATIC_INLINE void PixelWrite4 (uae_u8 * mem, int bits, uae_u32 fgpen)
16731 + do_put_mem_long (((uae_u32 *) mem) + bits, fgpen);
16734 +STATIC_INLINE void PixelWrite (uae_u8 * mem, int bits, uae_u32 fgpen, uae_u8 Bpp, uae_u32 mask)
16738 + if (mask != 0xFF)
16739 + fgpen = (fgpen & mask) | (do_get_mem_byte (mem + bits) & ~mask);
16740 + do_put_mem_byte (mem + bits, fgpen);
16743 + do_put_mem_word (((uae_u16 *) mem) + bits, fgpen);
16746 + do_put_mem_byte (mem + bits * 3, fgpen & 0x000000FF);
16747 + *(uae_u16 *) (mem + bits * 3 + 1) = (fgpen & 0x00FFFF00) >> 8;
16750 + do_put_mem_long (((uae_u32 *) mem) + bits, fgpen);
16758 + * Synopsis:BlitPattern(bi, ri, pattern, X, Y, Width, Height, Mask, RGBFormat);
16760 + * a0:struct BoardInfo *bi
16761 + * a1:struct RenderInfo *ri
16762 + * a2:struct Pattern *pattern
16770 + * This function is used to paint a pattern on the board memory using the blitter. It is called by
16771 + * BltPattern, if a AreaPtrn is used with positive AreaPtSz. The pattern consists of a b/w image
16772 + * using a single plane of image data which will be expanded repeatedly to the destination RGBFormat
16773 + * using ForeGround and BackGround pens as well as draw modes. The width of the pattern data is
16774 + * always 16 pixels (one word) and the height is calculated as 2^Size. The data must be shifted up
16775 + * and to the left by XOffset and YOffset pixels at the beginning.
16777 +uae_u32 picasso_BlitPattern (void)
16779 + uaecptr rinf = m68k_areg (regs, 1);
16780 + uaecptr pinf = m68k_areg (regs, 2);
16781 + unsigned long X = (uae_u16) m68k_dreg (regs, 0);
16782 + unsigned long Y = (uae_u16) m68k_dreg (regs, 1);
16783 + unsigned long W = (uae_u16) m68k_dreg (regs, 2);
16784 + unsigned long H = (uae_u16) m68k_dreg (regs, 3);
16785 + uae_u8 Mask = (uae_u8) m68k_dreg (regs, 4);
16786 + uae_u32 RGBFmt = m68k_dreg (regs, 7);
16788 + uae_u8 Bpp = GetBytesPerPixel (RGBFmt);
16789 + int inversion = 0;
16790 + struct RenderInfo ri;
16791 + struct Pattern pattern;
16792 + unsigned long rows;
16796 + unsigned long ysize_mask;
16798 + wgfx_flushline ();
16800 + if (! CopyRenderInfoStructureA2U (rinf, &ri)
16801 + || !CopyPatternStructureA2U (pinf, &pattern))
16804 + Bpp = GetBytesPerPixel (ri.RGBFormat);
16805 + uae_mem = ri.Memory + Y * ri.BytesPerRow + X * Bpp; /* offset with address */
16807 + if (pattern.DrawMode & INVERS)
16810 + pattern.DrawMode &= 0x03;
16811 + if (Mask != 0xFF) {
16813 + write_log ("ERROR - not obeying BlitPattern() mask 0x%x properly with Bpp %d.\n", Mask, Bpp);
16814 + else if (pattern.DrawMode == COMP) {
16815 + write_log ("ERROR - Unsupported Mask value 0x%x with COMP Draw in BlitPattern(), using fallback method.\n", Mask);
16820 + P96TRACE (("BlitPattern() xy(%d,%d), wh(%d,%d) draw 0x%x, off(%d,%d), ph %d\n",
16821 + X, Y, W, H, pattern.DrawMode, pattern.XOffset, pattern.YOffset, 1 << pattern.Size));
16823 + DumpPattern (&pattern);
16825 + ysize_mask = (1 << pattern.Size) - 1;
16826 + xshift = pattern.XOffset & 15;
16828 + for (rows = 0; rows < H; rows++, uae_mem += ri.BytesPerRow) {
16829 + unsigned long prow = (rows + pattern.YOffset) & ysize_mask;
16830 + unsigned int d = do_get_mem_word (((uae_u16 *) pattern.Memory) + prow);
16831 + uae_u8 *uae_mem2 = uae_mem;
16832 + unsigned long cols;
16835 + d = (d << xshift) | (d >> (16 - xshift));
16837 + for (cols = 0; cols < W; cols += 16, uae_mem2 += Bpp << 4) {
16839 + long max = W - cols;
16840 + unsigned int data = d;
16845 + for (bits = 0; bits < max; bits++) {
16846 + int bit_set = data & 0x8000;
16848 + switch (pattern.DrawMode) {
16851 + bit_set = !bit_set;
16853 + PixelWrite (uae_mem2, bits, pattern.FgPen, Bpp, Mask);
16857 + bit_set = !bit_set;
16859 + PixelWrite (uae_mem2, bits, pattern.FgPen, Bpp, Mask);
16861 + PixelWrite (uae_mem2, bits, pattern.BgPen, Bpp, Mask);
16865 + fgpen = pattern.FgPen;
16870 + uae_u8 *addr = uae_mem2 + bits;
16871 + do_put_mem_byte (addr, do_get_mem_byte (addr) ^ fgpen);
16876 + uae_u16 *addr = ((uae_u16 *) uae_mem2) + bits;
16877 + do_put_mem_word (addr, do_get_mem_word (addr) ^ fgpen);
16882 + uae_u32 *addr = (uae_u32 *) (uae_mem2 + bits * 3);
16883 + do_put_mem_long (addr, do_get_mem_long (addr) ^ (fgpen & 0x00FFFFFF));
16888 + uae_u32 *addr = ((uae_u32 *) uae_mem2) + bits;
16889 + do_put_mem_long (addr, do_get_mem_long (addr) ^ fgpen);
16900 + if (renderinfo_is_current_screen (&ri))
16901 + do_blit (&ri, Bpp, X, Y, X, Y, W, H, BLIT_SRC, 0);
16906 +/*************************************************
16908 +**************************************************
16909 +* Synopsis: BlitTemplate(bi, ri, template, X, Y, Width, Height, Mask, RGBFormat);
16910 +* a0: struct BoardInfo *bi
16911 +* a1: struct RenderInfo *ri
16912 +* a2: struct Template *template
16920 +* This function is used to paint a template on the board memory using the blitter.
16921 +* It is called by BltPattern and BltTemplate. The template consists of a b/w image
16922 +* using a single plane of image data which will be expanded to the destination RGBFormat
16923 +* using ForeGround and BackGround pens as well as draw modes.
16924 +***********************************************************************************/
16925 +uae_u32 picasso_BlitTemplate (void)
16927 + uae_u8 inversion = 0;
16928 + uaecptr rinf = m68k_areg (regs, 1);
16929 + uaecptr tmpl = m68k_areg (regs, 2);
16930 + unsigned long X = (uae_u16) m68k_dreg (regs, 0);
16931 + unsigned long Y = (uae_u16) m68k_dreg (regs, 1);
16932 + unsigned long W = (uae_u16) m68k_dreg (regs, 2);
16933 + unsigned long H = (uae_u16) m68k_dreg (regs, 3);
16934 + uae_u16 Mask = (uae_u16) m68k_dreg (regs, 4);
16935 + struct Template tmp;
16936 + struct RenderInfo ri;
16937 + unsigned long rows;
16940 + uae_u8 *uae_mem, Bpp;
16941 + uae_u8 *tmpl_base;
16943 + wgfx_flushline ();
16945 + if (!CopyRenderInfoStructureA2U (rinf, &ri)
16946 + || !CopyTemplateStructureA2U (tmpl, &tmp))
16949 + Bpp = GetBytesPerPixel (ri.RGBFormat);
16950 + uae_mem = ri.Memory + Y * ri.BytesPerRow + X * Bpp; /* offset into address */
16952 + if (tmp.DrawMode & INVERS)
16955 + tmp.DrawMode &= 0x03;
16956 + if (Mask != 0xFF) {
16958 + write_log ("ERROR - not obeying BlitTemplate() mask 0x%x properly with Bpp %d.\n", Mask, Bpp);
16959 + else if (tmp.DrawMode == COMP) {
16960 + write_log ("ERROR - Unsupported Mask value 0x%x with COMP Draw in BlitTemplate(), using fallback method.\n", Mask);
16965 + P96TRACE (("BlitTemplate() xy(%d,%d), wh(%d,%d) draw 0x%x fg 0x%x bg 0x%x \n",
16966 + X, Y, W, H, tmp.DrawMode, tmp.FgPen, tmp.BgPen));
16968 + bitoffset = tmp.XOffset % 8;
16971 + DumpTemplate (&tmp, W, H);
16974 + tmpl_base = tmp.Memory + tmp.XOffset / 8;
16976 + for (rows = 0; rows < H; rows++, uae_mem += ri.BytesPerRow, tmpl_base += tmp.BytesPerRow) {
16977 + unsigned long cols;
16978 + uae_u8 *tmpl_mem = tmpl_base;
16979 + uae_u8 *uae_mem2 = uae_mem;
16980 + unsigned int data = *tmpl_mem;
16982 + for (cols = 0; cols < W; cols += 8, uae_mem2 += Bpp << 3) {
16983 + unsigned int byte;
16985 + long max = W - cols;
16991 + data |= *++tmpl_mem;
16993 + byte = data >> (8 - bitoffset);
16995 + for (bits = 0; bits < max; bits++) {
16996 + int bit_set = (byte & 0x80);
16998 + switch (tmp.DrawMode) {
17001 + bit_set = !bit_set;
17003 + fgpen = tmp.FgPen;
17004 + PixelWrite (uae_mem2, bits, fgpen, Bpp, Mask);
17009 + bit_set = !bit_set;
17010 + fgpen = tmp.BgPen;
17012 + fgpen = tmp.FgPen;
17014 + PixelWrite (uae_mem2, bits, fgpen, Bpp, Mask);
17018 + fgpen = tmp.FgPen;
17023 + uae_u8 *addr = uae_mem2 + bits;
17024 + do_put_mem_byte (addr, do_get_mem_byte (addr) ^ fgpen);
17029 + uae_u16 *addr = ((uae_u16 *) uae_mem2) + bits;
17030 + do_put_mem_word (addr, do_get_mem_word (addr) ^ fgpen);
17035 + uae_u32 *addr = (uae_u32 *) (uae_mem2 + bits * 3);
17036 + do_put_mem_long (addr, do_get_mem_long (addr) ^ (fgpen & 0x00FFFFFF));
17041 + uae_u32 *addr = ((uae_u32 *) uae_mem2) + bits;
17042 + do_put_mem_long (addr, do_get_mem_long (addr) ^ fgpen);
17053 + if (renderinfo_is_current_screen (&ri))
17054 + do_blit (&ri, Bpp, X, Y, X, Y, W, H, BLIT_SRC, 0);
17060 + * CalculateBytesPerRow:
17061 + * a0: struct BoardInfo
17062 + * d0: uae_u16 Width
17063 + * d7: RGBFTYPE RGBFormat
17064 + * This function calculates the amount of bytes needed for a line of
17065 + * "Width" pixels in the given RGBFormat.
17067 +uae_u32 picasso_CalculateBytesPerRow (void)
17069 + uae_u16 width = m68k_dreg (regs, 0);
17070 + uae_u32 type = m68k_dreg (regs, 7);
17072 + width = GetBytesPerPixel (type) * width;
17073 + P96TRACE (("CalculateBytesPerRow() = %d\n", width));
17080 + * a0: struct BoardInfo
17082 + * This function enables and disables the video display.
17084 + * NOTE: return the opposite of the state
17086 +uae_u32 picasso_SetDisplay (void)
17088 + uae_u32 state = m68k_dreg (regs, 0);
17089 + P96TRACE (("SetDisplay(%d)\n", state));
17094 + * WaitVerticalSync:
17095 + * a0: struct BoardInfo
17096 + * This function waits for the next horizontal retrace.
17098 +uae_u32 picasso_WaitVerticalSync (void)
17100 + /*write_log ("WaitVerticalSync()\n"); */
17104 +/* NOTE: Watch for those planeptrs of 0x00000000 and 0xFFFFFFFF for all zero / all one bitmaps !!!! */
17105 +static void PlanarToChunky (struct RenderInfo *ri, struct BitMap *bm,
17106 + unsigned long srcx, unsigned long srcy,
17107 + unsigned long dstx, unsigned long dsty, unsigned long width, unsigned long height, uae_u8 mask)
17111 + uae_u8 *PLANAR[8], *image = ri->Memory + dstx * GetBytesPerPixel (ri->RGBFormat) + dsty * ri->BytesPerRow;
17112 + int Depth = bm->Depth;
17113 + unsigned long rows, bitoffset = srcx & 7;
17116 + /* if (mask != 0xFF)
17117 + write_log ("P2C - pixel-width = %d, bit-offset = %d\n", width, bitoffset); */
17119 + /* Set up our bm->Planes[] pointers to the right horizontal offset */
17120 + for (j = 0; j < Depth; j++) {
17121 + uae_u8 *p = bm->Planes[j];
17122 + if (p != &all_zeros_bitmap && p != &all_ones_bitmap)
17123 + p += srcx / 8 + srcy * bm->BytesPerRow;
17125 + if ((mask & (1 << j)) == 0)
17126 + PLANAR[j] = &all_zeros_bitmap;
17128 + eol_offset = (long) bm->BytesPerRow - (long) ((width + 7) >> 3);
17129 + for (rows = 0; rows < height; rows++, image += ri->BytesPerRow) {
17130 + unsigned long cols;
17132 + for (cols = 0; cols < width; cols += 8) {
17134 + uae_u32 a = 0, b = 0;
17135 + unsigned int msk = 0xFF;
17136 + long tmp = cols + 8 - width;
17139 + b = do_get_mem_long ((uae_u32 *) (image + cols + 4));
17141 + b &= 0xFFFFFFFF >> (32 - tmp * 8);
17142 + else if (tmp > 4) {
17143 + a = do_get_mem_long ((uae_u32 *) (image + cols));
17144 + a &= 0xFFFFFFFF >> (64 - tmp * 8);
17147 + for (k = 0; k < Depth; k++) {
17148 + unsigned int data;
17149 + if (PLANAR[k] == &all_zeros_bitmap)
17151 + else if (PLANAR[k] == &all_ones_bitmap)
17154 + data = (uae_u8) (do_get_mem_word ((uae_u16 *) PLANAR[k]) >> (8 - bitoffset));
17158 + a |= p2ctab[data][0] << k;
17159 + b |= p2ctab[data][1] << k;
17161 + do_put_mem_long ((uae_u32 *) (image + cols), a);
17162 + do_put_mem_long ((uae_u32 *) (image + cols + 4), b);
17164 + for (j = 0; j < Depth; j++) {
17165 + if (PLANAR[j] != &all_zeros_bitmap && PLANAR[j] != &all_ones_bitmap) {
17166 + PLANAR[j] += eol_offset;
17173 + * BlitPlanar2Chunky:
17174 + * a0: struct BoardInfo *bi
17175 + * a1: struct BitMap *bm - source containing planar information and assorted details
17176 + * a2: struct RenderInfo *ri - dest area and its details
17183 + * d6.b: MinTerm - uh oh!
17184 + * d7.b: Mask - uh oh!
17186 + * This function is currently used to blit from planar bitmaps within system memory to chunky bitmaps
17187 + * on the board. Watch out for plane pointers that are 0x00000000 (represents a plane with all bits "0")
17188 + * or 0xffffffff (represents a plane with all bits "1").
17190 +uae_u32 picasso_BlitPlanar2Chunky (void)
17192 + uaecptr bm = m68k_areg (regs, 1);
17193 + uaecptr ri = m68k_areg (regs, 2);
17194 + unsigned long srcx = (uae_u16) m68k_dreg (regs, 0);
17195 + unsigned long srcy = (uae_u16) m68k_dreg (regs, 1);
17196 + unsigned long dstx = (uae_u16) m68k_dreg (regs, 2);
17197 + unsigned long dsty = (uae_u16) m68k_dreg (regs, 3);
17198 + unsigned long width = (uae_u16) m68k_dreg (regs, 4);
17199 + unsigned long height = (uae_u16) m68k_dreg (regs, 5);
17200 + uae_u8 minterm = m68k_dreg (regs, 6) & 0xFF;
17201 + uae_u8 mask = m68k_dreg (regs, 7) & 0xFF;
17202 + struct RenderInfo local_ri;
17203 + struct BitMap local_bm;
17205 + wgfx_flushline ();
17207 + if (minterm != 0x0C) {
17208 + write_log ("ERROR - BlitPlanar2Chunky() has minterm 0x%x, which I don't handle. Using fall-back routine.\n", minterm);
17211 + if (!CopyRenderInfoStructureA2U (ri, &local_ri)
17212 + || !CopyBitMapStructureA2U (bm, &local_bm))
17215 + P96TRACE (("BlitPlanar2Chunky(%d, %d, %d, %d, %d, %d) Minterm 0x%x, Mask 0x%x, Depth %d\n",
17216 + srcx, srcy, dstx, dsty, width, height, minterm, mask, local_bm.Depth));
17217 + P96TRACE (("P2C - BitMap has %d BPR, %d rows\n", local_bm.BytesPerRow, local_bm.Rows));
17218 + PlanarToChunky (&local_ri, &local_bm, srcx, srcy, dstx, dsty, width, height, mask);
17219 + if (renderinfo_is_current_screen (&local_ri))
17220 + do_blit (&local_ri, GetBytesPerPixel (local_ri.RGBFormat), dstx, dsty, dstx, dsty, width, height, BLIT_SRC, 0);
17225 +static void PlanarToDirect (struct RenderInfo *ri, struct BitMap *bm,
17226 + unsigned long srcx, unsigned long srcy,
17227 + unsigned long dstx, unsigned long dsty,
17228 + unsigned long width, unsigned long height, uae_u8 mask, struct ColorIndexMapping *cim)
17231 + int bpp = GetBytesPerPixel (ri->RGBFormat);
17232 + uae_u8 *PLANAR[8];
17233 + uae_u8 *image = ri->Memory + dstx * bpp + dsty * ri->BytesPerRow;
17234 + int Depth = bm->Depth;
17235 + unsigned long rows;
17238 + /* Set up our bm->Planes[] pointers to the right horizontal offset */
17239 + for (j = 0; j < Depth; j++) {
17240 + uae_u8 *p = bm->Planes[j];
17241 + if (p != &all_zeros_bitmap && p != &all_ones_bitmap)
17242 + p += srcx / 8 + srcy * bm->BytesPerRow;
17244 + if ((mask & (1 << j)) == 0)
17245 + PLANAR[j] = &all_zeros_bitmap;
17248 + eol_offset = (long) bm->BytesPerRow - (long) ((width + (srcx & 7)) >> 3);
17249 + for (rows = 0; rows < height; rows++, image += ri->BytesPerRow) {
17250 + unsigned long cols;
17251 + uae_u8 *image2 = image;
17252 + unsigned int bitoffs = 7 - (srcx & 7);
17255 + for (cols = 0; cols < width; cols++) {
17257 + for (k = 0; k < Depth; k++) {
17258 + if (PLANAR[k] == &all_ones_bitmap)
17260 + else if (PLANAR[k] != &all_zeros_bitmap) {
17261 + v |= ((*PLANAR[k] >> bitoffs) & 1) << k;
17267 + do_put_mem_word ((uae_u16 *) image2, cim->Colors[v]);
17271 + do_put_mem_byte (image2++, cim->Colors[v] & 0x000000FF);
17272 + do_put_mem_word ((uae_u16 *) image2, (cim->Colors[v] & 0x00FFFF00) >> 8);
17276 + do_put_mem_long ((uae_u32 *) image2, cim->Colors[v]);
17282 + if (bitoffs == 7) {
17284 + for (k = 0; k < Depth; k++) {
17285 + if (PLANAR[k] != &all_zeros_bitmap && PLANAR[k] != &all_ones_bitmap) {
17292 + for (i = 0; i < Depth; i++) {
17293 + if (PLANAR[i] != &all_zeros_bitmap && PLANAR[i] != &all_ones_bitmap) {
17294 + PLANAR[i] += eol_offset;
17301 + * BlitPlanar2Direct:
17304 + * BlitPlanar2Direct(bi, bm, ri, cim, SrcX, SrcY, DstX, DstY, SizeX, SizeY, MinTerm, Mask);
17306 + * a0:struct BoardInfo *bi
17307 + * a1:struct BitMap *bm
17308 + * a2:struct RenderInfo *ri
17309 + * a3:struct ColorIndexMapping *cmi
17319 + * This function is currently used to blit from planar bitmaps within system memory to direct color
17320 + * bitmaps (15, 16, 24 or 32 bit) on the board. Watch out for plane pointers that are 0x00000000 (represents
17321 + * a plane with all bits "0") or 0xffffffff (represents a plane with all bits "1"). The ColorIndexMapping is
17322 + * used to map the color index of each pixel formed by the bits in the bitmap's planes to a direct color value
17323 + * which is written to the destination RenderInfo. The color mask and all colors within the mapping are words,
17324 + * triple bytes or longwords respectively similar to the color values used in FillRect(), BlitPattern() or
17325 + * BlitTemplate().
17327 +uae_u32 picasso_BlitPlanar2Direct (void)
17329 + uaecptr bm = m68k_areg (regs, 1);
17330 + uaecptr ri = m68k_areg (regs, 2);
17331 + uaecptr cim = m68k_areg (regs, 3);
17332 + unsigned long srcx = (uae_u16) m68k_dreg (regs, 0);
17333 + unsigned long srcy = (uae_u16) m68k_dreg (regs, 1);
17334 + unsigned long dstx = (uae_u16) m68k_dreg (regs, 2);
17335 + unsigned long dsty = (uae_u16) m68k_dreg (regs, 3);
17336 + unsigned long width = (uae_u16) m68k_dreg (regs, 4);
17337 + unsigned long height = (uae_u16) m68k_dreg (regs, 5);
17338 + uae_u8 minterm = m68k_dreg (regs, 6);
17339 + uae_u8 Mask = m68k_dreg (regs, 7);
17340 + struct RenderInfo local_ri;
17341 + struct BitMap local_bm;
17342 + struct ColorIndexMapping local_cim;
17344 + wgfx_flushline ();
17346 + if (minterm != 0x0C) {
17347 + write_log ("ERROR - BlitPlanar2Direct() has op-code 0x%x, which I don't handle. Using fall-back routine.\n", minterm);
17350 + if (Mask != 0xFF) {
17351 + write_log ("ERROR - Unsupported Mask value 0x%x in BlitPlanar2Direct(), using fallback method.\n", Mask);
17354 + if (!CopyRenderInfoStructureA2U (ri, &local_ri)
17355 + || !CopyBitMapStructureA2U (bm, &local_bm))
17358 + CopyColorIndexMappingA2U (cim, &local_cim);
17359 + P96TRACE (("BlitPlanar2Direct(%d, %d, %d, %d, %d, %d) Minterm 0x%x, Mask 0x%x, Depth %d\n",
17360 + srcx, srcy, dstx, dsty, width, height, minterm, Mask, local_bm.Depth));
17361 + PlanarToDirect (&local_ri, &local_bm, srcx, srcy, dstx, dsty, width, height, Mask, &local_cim);
17362 + if (renderinfo_is_current_screen (&local_ri))
17363 + do_blit (&local_ri, GetBytesPerPixel (local_ri.RGBFormat), dstx, dsty, dstx, dsty, width, height, BLIT_SRC, 0);
17367 +/* @@@ - Work to be done here!
17369 + * The address is the offset into our Picasso96 frame-buffer (pointed to by gfxmem_start)
17370 + * where the value was put.
17372 + * Porting work: on some machines you may not need these functions, ie. if the memory for the
17373 + * Picasso96 frame-buffer is directly viewable or directly blittable. On Win32 with DirectX,
17374 + * this is not the case. So I provide some write-through functions (as per Mathias' orders!)
17376 +static void write_gfx_long (uaecptr addr, uae_u32 value)
17378 + uaecptr oldaddr = addr;
17379 + int x, xbytes, y;
17386 + * Several writes to successive memory locations are a common access pattern.
17387 + * Try to optimize it.
17389 + if (addr >= wgfx_linestart && addr + 4 <= wgfx_lineend) {
17390 + if (addr < wgfx_min)
17392 + if (addr + 4 > wgfx_max)
17393 + wgfx_max = addr + 4;
17396 + wgfx_flushline ();
17398 + addr += gfxmem_start;
17399 + /* Check to see if this needs to be written through to the display, or was it an "offscreen" area? */
17400 + if (addr < picasso96_state.Address || addr + 4 > picasso96_state.Extent)
17403 + addr -= picasso96_state.Address;
17404 + y = addr / picasso96_state.BytesPerRow;
17406 + if (y >= picasso96_state.VirtualHeight)
17408 + wgfx_linestart = picasso96_state.Address - gfxmem_start + y * picasso96_state.BytesPerRow;
17409 + wgfx_lineend = wgfx_linestart + picasso96_state.BytesPerRow;
17411 + wgfx_min = oldaddr;
17412 + wgfx_max = oldaddr + 4;
17415 +static void write_gfx_word (uaecptr addr, uae_u16 value)
17417 + uaecptr oldaddr = addr;
17418 + int x, xbytes, y;
17425 + * Several writes to successive memory locations are a common access pattern.
17426 + * Try to optimize it.
17428 + if (addr >= wgfx_linestart && addr + 2 <= wgfx_lineend) {
17429 + if (addr < wgfx_min)
17431 + if (addr + 2 > wgfx_max)
17432 + wgfx_max = addr + 2;
17435 + wgfx_flushline ();
17437 + addr += gfxmem_start;
17438 + /* Check to see if this needs to be written through to the display, or was it an "offscreen" area? */
17439 + if (addr < picasso96_state.Address || addr + 2 > picasso96_state.Extent)
17442 + addr -= picasso96_state.Address;
17443 + y = addr / picasso96_state.BytesPerRow;
17445 + if (y >= picasso96_state.VirtualHeight)
17447 + wgfx_linestart = picasso96_state.Address - gfxmem_start + y * picasso96_state.BytesPerRow;
17448 + wgfx_lineend = wgfx_linestart + picasso96_state.BytesPerRow;
17450 + wgfx_min = oldaddr;
17451 + wgfx_max = oldaddr + 2;
17454 +static void write_gfx_byte (uaecptr addr, uae_u8 value)
17456 + uaecptr oldaddr = addr;
17457 + int x, xbytes, y;
17464 + * Several writes to successive memory locations are a common access pattern.
17465 + * Try to optimize it.
17467 + if (addr >= wgfx_linestart && addr + 4 <= wgfx_lineend) {
17468 + if (addr < wgfx_min)
17470 + if (addr + 1 > wgfx_max)
17471 + wgfx_max = addr + 1;
17474 + wgfx_flushline ();
17476 + addr += gfxmem_start;
17477 + /* Check to see if this needs to be written through to the display, or was it an "offscreen" area? */
17478 + if (addr < picasso96_state.Address || addr + 1 > picasso96_state.Extent)
17481 + addr -= picasso96_state.Address;
17482 + y = addr / picasso96_state.BytesPerRow;
17484 + if (y >= picasso96_state.VirtualHeight)
17486 + wgfx_linestart = picasso96_state.Address - gfxmem_start + y * picasso96_state.BytesPerRow;
17487 + wgfx_lineend = wgfx_linestart + picasso96_state.BytesPerRow;
17489 + wgfx_min = oldaddr;
17490 + wgfx_max = oldaddr + 1;
17493 +static uae_u32 REGPARAM2 gfxmem_lget (uaecptr addr)
17496 + addr -= gfxmem_start & gfxmem_mask;
17497 + addr &= gfxmem_mask;
17498 + m = (uae_u32 *) (gfxmemory + addr);
17499 + return do_get_mem_long (m);
17502 +static uae_u32 REGPARAM2 gfxmem_wget (uaecptr addr)
17505 + addr -= gfxmem_start & gfxmem_mask;
17506 + addr &= gfxmem_mask;
17507 + m = (uae_u16 *) (gfxmemory + addr);
17508 + return do_get_mem_word (m);
17511 +static uae_u32 REGPARAM2 gfxmem_bget (uaecptr addr)
17513 + addr -= gfxmem_start & gfxmem_mask;
17514 + addr &= gfxmem_mask;
17515 + return gfxmemory[addr];
17518 +static void REGPARAM2 gfxmem_lput (uaecptr addr, uae_u32 l)
17521 + addr -= gfxmem_start & gfxmem_mask;
17522 + addr &= gfxmem_mask;
17523 + m = (uae_u32 *) (gfxmemory + addr);
17524 + do_put_mem_long (m, l);
17526 + /* write the long-word to our displayable memory */
17527 + write_gfx_long (addr, l);
17530 +static void REGPARAM2 gfxmem_wput (uaecptr addr, uae_u32 w)
17533 + addr -= gfxmem_start & gfxmem_mask;
17534 + addr &= gfxmem_mask;
17535 + m = (uae_u16 *) (gfxmemory + addr);
17536 + do_put_mem_word (m, (uae_u16) w);
17538 + /* write the word to our displayable memory */
17539 + write_gfx_word (addr, (uae_u16) w);
17542 +static void REGPARAM2 gfxmem_bput (uaecptr addr, uae_u32 b)
17544 + addr -= gfxmem_start & gfxmem_mask;
17545 + addr &= gfxmem_mask;
17546 + gfxmemory[addr] = b;
17548 + /* write the byte to our displayable memory */
17549 + write_gfx_byte (addr, (uae_u8) b);
17552 +static int REGPARAM2 gfxmem_check (uaecptr addr, uae_u32 size)
17554 + addr -= gfxmem_start & gfxmem_mask;
17555 + addr &= gfxmem_mask;
17556 + return (addr + size) < allocated_gfxmem;
17559 +static uae_u8 REGPARAM2 *gfxmem_xlate (uaecptr addr)
17561 + addr -= gfxmem_start & gfxmem_mask;
17562 + addr &= gfxmem_mask;
17563 + return gfxmemory + addr;
17566 +addrbank gfxmem_bank = {
17567 + gfxmem_lget, gfxmem_wget, gfxmem_bget,
17568 + gfxmem_lput, gfxmem_wput, gfxmem_bput,
17569 + gfxmem_xlate, gfxmem_check, NULL
17572 +int picasso_display_mode_index (uae_u32 x, uae_u32 y, uae_u32 d)
17575 + for (i = 0; i < mode_count; i++) {
17576 + if (DisplayModes[i].res.width == x
17577 + && DisplayModes[i].res.height == y
17578 + && DisplayModes[i].depth == d)
17581 + if (i == mode_count)
17586 +static int resolution_compare (const void *a, const void *b)
17588 + struct PicassoResolution *ma = (struct PicassoResolution *) a;
17589 + struct PicassoResolution *mb = (struct PicassoResolution *) b;
17590 + if (ma->res.width > mb->res.width)
17592 + if (ma->res.width < mb->res.width)
17594 + if (ma->res.height > mb->res.height)
17596 + if (ma->res.height < mb->res.height)
17598 + return ma->depth - mb->depth;
17601 +/* Call this function first, near the beginning of code flow
17602 + * NOTE: Don't stuff it in InitGraphics() which seems reasonable...
17603 + * Instead, put it in customreset() for safe-keeping. */
17604 +void InitPicasso96 (void)
17606 + static int first_time = 1;
17608 + memset (&picasso96_state, 0, sizeof (struct picasso96_state_struct));
17610 + if (first_time) {
17613 + for (i = 0; i < 256; i++) {
17614 + p2ctab[i][0] = (((i & 128) ? 0x01000000 : 0)
17615 + | ((i & 64) ? 0x010000 : 0)
17616 + | ((i & 32) ? 0x0100 : 0)
17617 + | ((i & 16) ? 0x01 : 0));
17618 + p2ctab[i][1] = (((i & 8) ? 0x01000000 : 0)
17619 + | ((i & 4) ? 0x010000 : 0)
17620 + | ((i & 2) ? 0x0100 : 0)
17621 + | ((i & 1) ? 0x01 : 0));
17623 + mode_count = DX_FillResolutions (&picasso96_pixel_format);
17624 + qsort (DisplayModes, mode_count, sizeof (struct PicassoResolution), resolution_compare);
17626 + for (i = 0; i < mode_count; i++) {
17627 + sprintf (DisplayModes[i].name, "%dx%d, %d-bit, %d Hz",
17628 + DisplayModes[i].res.width, DisplayModes[i].res.height, DisplayModes[i].depth * 8, DisplayModes[i].refresh);
17629 + switch (DisplayModes[i].depth) {
17631 + if (DisplayModes[i].res.width > chunky.width)
17632 + chunky.width = DisplayModes[i].res.width;
17633 + if (DisplayModes[i].res.height > chunky.height)
17634 + chunky.height = DisplayModes[i].res.height;
17637 + if (DisplayModes[i].res.width > hicolour.width)
17638 + hicolour.width = DisplayModes[i].res.width;
17639 + if (DisplayModes[i].res.height > hicolour.height)
17640 + hicolour.height = DisplayModes[i].res.height;
17643 + if (DisplayModes[i].res.width > truecolour.width)
17644 + truecolour.width = DisplayModes[i].res.width;
17645 + if (DisplayModes[i].res.height > truecolour.height)
17646 + truecolour.height = DisplayModes[i].res.height;
17649 + if (DisplayModes[i].res.width > alphacolour.width)
17650 + alphacolour.width = DisplayModes[i].res.width;
17651 + if (DisplayModes[i].res.height > alphacolour.height)
17652 + alphacolour.height = DisplayModes[i].res.height;
17656 + ShowSupportedResolutions ();
17663 diff -urN src-0.8.22/src/sdlgfx.c~ src-0.8.22-mmu/src/sdlgfx.c~
17664 --- src-0.8.22/src/sdlgfx.c~ 1970-01-01 01:00:00.000000000 +0100
17665 +++ src-0.8.22-mmu/src/sdlgfx.c~ 2002-02-20 19:33:39.000000000 +0100
17668 + * UAE - The Un*x Amiga Emulator
17672 + * Copyright 2001 Bernd Lachner (EMail: dev@lachner-net.de)
17674 + * Partialy based on the UAE X interface (xwin.c)
17676 + * Copyright 1995, 1996 Bernd Schmidt
17677 + * Copyright 1996 Ed Hanway, Andre Beck, Samuel Devulder, Bruno Coste
17678 + * Copyright 1998 Marcus Sundberg
17679 + * DGA support by Kai Kollmorgen
17680 + * X11/DGA merge, hotkeys and grabmouse by Marcus Sundberg
17683 +#include "sysconfig.h"
17684 +#include "sysdeps.h"
17686 +#include <unistd.h>
17687 +#include <signal.h>
17689 +#include <SDL/SDL.h>
17690 +#include <SDL/SDL_endian.h>
17692 +#include "config.h"
17693 +#include "options.h"
17695 +#include "memory.h"
17697 +#include "custom.h"
17698 +#include "drawing.h"
17699 +#include "newcpu.h"
17700 +#include "keyboard.h"
17701 +#include "keybuf.h"
17703 +#include "debug.h"
17704 +#include "picasso96.h"
17706 +/* Uncomment for debugging output */
17707 +/* #define DEBUG */
17709 +#ifdef __cplusplus
17710 +static RETSIGTYPE sigbrkhandler(...)
17712 +static RETSIGTYPE sigbrkhandler (int foo)
17715 + activate_debugger();
17716 +#if !defined(__unix) || defined(__NeXT__)
17717 + signal (SIGINT, sigbrkhandler);
17721 +void setup_brkhandler (void)
17723 +#if defined(__unix) && !defined(__NeXT__)
17724 + struct sigaction sa;
17725 + sa.sa_handler = sigbrkhandler;
17728 + sa.sa_flags = SA_RESTART;
17730 + sigemptyset (&sa.sa_mask);
17731 + sigaction (SIGINT, &sa, NULL);
17733 + signal (SIGINT, sigbrkhandler);
17737 +/* SDL variable for output surface */
17738 +static SDL_Surface *prSDLScreen = NULL;
17739 +/* Possible screen modes (x and y resolutions) */
17740 +#define MAX_SCREEN_MODES 11
17741 +static int x_size_table[MAX_SCREEN_MODES] = { 320, 320, 320, 320, 640, 640, 640, 800, 1024, 1152, 1280 };
17742 +static int y_size_table[MAX_SCREEN_MODES] = { 200, 240, 256, 400, 350, 480, 512, 600, 768, 864, 1024 };
17743 +/* Possible screen depth (0 terminated) */
17744 +static int aScreenDepth[] = {16, 15, 12, 0};
17746 +static int red_bits, green_bits, blue_bits;
17747 +static int red_shift, green_shift, blue_shift;
17749 +static int screen_is_picasso;
17750 +static char picasso_invalid_lines[1201];
17751 +static int picasso_has_invalid_lines;
17752 +static int picasso_invalid_start, picasso_invalid_stop;
17753 +static int picasso_maxw = 0, picasso_maxh = 0;
17755 +static int bitdepth, bit_unit;
17757 +static int current_width, current_height;
17758 +static SDL_Color arSDLColors[256];
17759 +static int ncolors = 0;
17761 +/* Keyboard and mouse */
17762 +static int keystate[256];
17764 +static void handle_mousegrab(void);
17765 +static void handle_inhibit(void);
17766 +static void framerate_up(void);
17767 +static void framerate_down(void);
17768 +static void togglefullscreen(void)
17770 + SDL_WM_ToggleFullScreen(prSDLScreen);
17773 +static void handle_interpol (void);
17777 + SDLKey aHotKeys[2];
17778 + void (*pfHandler)(void);
17779 + long aPressedKeys[2];
17783 +static struct SDLHotKey arHotKeys[] =
17785 + {{ SDLK_F12, SDLK_s}, togglefullscreen, {0, 0} },
17786 + {{ SDLK_F12, SDLK_q}, uae_quit, {0, 0} },
17787 + {{ SDLK_F12, SDLK_m}, togglemouse, {0, 0} },
17788 + {{ SDLK_F12, SDLK_g}, handle_mousegrab, {0, 0} },
17789 + {{ SDLK_F12, SDLK_i}, handle_inhibit, {0, 0} },
17790 + {{ SDLK_F12, SDLK_p}, handle_interpol, {0, 0} },
17791 + {{ SDLK_F12, SDLK_KP_PLUS}, framerate_up, {0, 0} },
17792 + {{ SDLK_F12, SDLK_KP_MINUS}, framerate_down, {0, 0} },
17793 + {{ 0, 0 }, NULL, {0, 0} } /* List must be terminated */
17796 +void flush_line (int y)
17798 + /* Not implemented for SDL output */
17800 + fprintf(stderr, "Function: flush_line\n");
17804 +void flush_block (int ystart, int ystop)
17807 + fprintf(stderr, "Function: flush_block %d %d\n", ystart, ystop);
17809 + SDL_UnlockSurface (prSDLScreen);
17810 + SDL_UpdateRect(prSDLScreen, 0, ystart, current_width, ystop-ystart+1);
17811 + SDL_LockSurface (prSDLScreen);
17814 +void flush_screen (int ystart, int ystop)
17817 + fprintf(stderr, "Function: flush_screen\n");
17821 + SDL_UpdateRect(prSDLScreen, 0, 0, current_width, current_height);
17825 +STATIC_INLINE int bitsInMask (unsigned long mask)
17827 + /* count bits in mask */
17837 +STATIC_INLINE int maskShift (unsigned long mask)
17839 + /* determine how far mask is shifted */
17841 + while (!(mask & 1))
17849 +static int get_color (int r, int g, int b, xcolnr *cnp)
17852 + fprintf(stderr, "Function: get_color\n");
17855 + *cnp = SDL_MapRGB(prSDLScreen->format, r, g, b);
17856 + arSDLColors[ncolors].r = r;
17857 + arSDLColors[ncolors].g = g;
17858 + arSDLColors[ncolors].b = b;
17864 +static int init_colors (void)
17869 + fprintf(stderr, "Function: init_colors\n");
17872 + if (bitdepth > 8)
17875 + red_bits = bitsInMask(prSDLScreen->format->Rmask);
17876 + green_bits = bitsInMask(prSDLScreen->format->Gmask);
17877 + blue_bits = bitsInMask(prSDLScreen->format->Bmask);
17878 + red_shift = maskShift(prSDLScreen->format->Rmask);
17879 + green_shift = maskShift(prSDLScreen->format->Gmask);
17880 + blue_shift = maskShift(prSDLScreen->format->Bmask);
17881 + alloc_colors64k (red_bits, green_bits, blue_bits, red_shift, green_shift, blue_shift);
17885 + alloc_colors256 (get_color);
17886 + SDL_SetColors(prSDLScreen, arSDLColors, 0, 256);
17889 + switch (gfxvidinfo.pixbytes)
17892 + for (i = 0; i < 4096; i++)
17893 + xcolors[i] = xcolors[i] * 0x00010001;
17894 + gfxvidinfo.can_double = 1;
17897 + for (i = 0; i < 4096; i++)
17898 + xcolors[i] = xcolors[i] * 0x01010101;
17899 + gfxvidinfo.can_double = 1;
17902 + gfxvidinfo.can_double = 0;
17905 + if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
17907 + switch (gfxvidinfo.pixbytes)
17910 + for(i = 0; i < 4096; i++)
17911 + SDL_Swap32(xcolors[i]);
17914 + for (i = 0; i < 4096; i++)
17915 + SDL_Swap16(xcolors[i]);
17922 +int graphics_setup (void)
17925 + fprintf(stderr, "Function: graphics_setup\n");
17928 + /* Initialize the SDL library */
17929 + if ( SDL_Init(SDL_INIT_VIDEO) < 0 )
17931 + fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
17939 +static void graphics_subinit (void)
17941 + Uint32 uiSDLVidModFlags;
17944 + fprintf(stderr, "Function: graphics_subinit\n");
17947 + /* Open SDL Window in current mode */
17948 + uiSDLVidModFlags = SDL_SWSURFACE;
17949 + if (bitdepth == 8)
17951 + uiSDLVidModFlags |= SDL_HWPALETTE;
17953 + if (currprefs.gfx_afullscreen || currprefs.gfx_pfullscreen)
17955 + uiSDLVidModFlags |= SDL_FULLSCREEN;
17957 + fprintf(stderr, "Resolution: %d x %d x %d\n", current_width, current_height, bitdepth);
17959 + prSDLScreen = SDL_SetVideoMode(current_width, current_height, bitdepth, uiSDLVidModFlags);
17960 + if (prSDLScreen == NULL)
17962 + fprintf(stderr, "Unable to set video mode: %s\n", SDL_GetError());
17968 + fprintf(stderr, "Bytes per Pixel: %d\n", prSDLScreen->format->BytesPerPixel);
17969 + fprintf(stderr, "Bytes per Line: %d\n", prSDLScreen->pitch);
17971 + SDL_LockSurface(prSDLScreen);
17972 + memset(prSDLScreen->pixels, 0, current_width * current_height * prSDLScreen->format->BytesPerPixel);
17973 + SDL_UnlockSurface(prSDLScreen);
17974 + SDL_UpdateRect(prSDLScreen, 0, 0, current_width, current_height);
17975 + /* Set UAE window title and icon name */
17976 + SDL_WM_SetCaption("UAE","UAE");
17977 + /* Hide mouse cursor */
17978 + SDL_ShowCursor(SDL_DISABLE);
17979 + /* Initialize structure for Amiga video modes */
17980 + gfxvidinfo.bufmem = prSDLScreen->pixels;
17981 + gfxvidinfo.linemem = 0;
17982 + gfxvidinfo.emergmem = 0;
17983 + gfxvidinfo.pixbytes = prSDLScreen->format->BytesPerPixel;
17984 + bit_unit = prSDLScreen->format->BytesPerPixel * 8;
17985 + gfxvidinfo.rowbytes = prSDLScreen->pitch;
17986 + gfxvidinfo.maxblocklines = 100;
17987 + gfxvidinfo.can_double = 0;
17988 + /* Initialize structure for Picasso96 video modes */
17989 + picasso_vidinfo.rowbytes = current_width * gfxvidinfo.pixbytes;
17990 + picasso_vidinfo.extra_mem = 1;
17991 + picasso_vidinfo.depth = bitdepth;
17992 + picasso_has_invalid_lines = 0;
17993 + picasso_invalid_start = picasso_vidinfo.height + 1;
17994 + picasso_invalid_stop = -1;
17995 + memset (picasso_invalid_lines, 0, sizeof picasso_invalid_lines);
17997 + lastmx = lastmy = 0;
17998 + newmousecounters = 0;
18002 +int graphics_init (void)
18007 + fprintf(stderr, "Function: graphics_init\n");
18010 + if (currprefs.color_mode > 5)
18011 + fprintf (stderr, "Bad color mode selected. Using default.\n"), currprefs.color_mode = 0;
18013 + screen_is_picasso = 0;
18015 + fixup_prefs_dimensions (&currprefs);
18018 + gfxvidinfo.width = currprefs.gfx_width;
18019 + gfxvidinfo.height = currprefs.gfx_height;
18020 + current_width = currprefs.gfx_width;
18021 + current_height = currprefs.gfx_height;
18023 + /* Find a SDL video mode with exact width and height */
18024 + for (i = 0; aScreenDepth[i] != 0; i++)
18026 + bitdepth = SDL_VideoModeOK(current_width, current_height, aScreenDepth[i], SDL_SWSURFACE);
18030 + fprintf(stderr, "Bit depth: %d\n", bitdepth);
18036 + fprintf(stderr, "Video mode %dx%d@%d not available\n", current_width, current_height, aScreenDepth[i]);
18039 + if (bitdepth == 0)
18041 + /* Find a SDL video mode from standard resolutions */
18042 + for (j = 0; j < MAX_SCREEN_MODES && !bitdepth; j++)
18044 + if (x_size_table[j] < current_width || y_size_table[j] < current_height)
18046 + for (i = 0; aScreenDepth[i] != 0 && !bitdepth; i++)
18048 + bitdepth = SDL_VideoModeOK(x_size_table[j], y_size_table[j], aScreenDepth[i], SDL_SWSURFACE);
18052 + fprintf(stderr, "Bit depth: %d\n", bitdepth);
18054 + gfxvidinfo.width = current_width = x_size_table[j];
18055 + gfxvidinfo.height = current_height = y_size_table[j];
18060 + fprintf(stderr, "Video mode %dx%d@%d not available\n", current_width, current_height, aScreenDepth[i]);
18064 + if (bitdepth == 0)
18066 + fprintf(stderr, "No video mode found!\n");
18071 + graphics_subinit ();
18074 + if (!init_colors ())
18077 + buttonstate[0] = buttonstate[1] = buttonstate[2] = 0;
18078 + for (i = 0; i < 256; i++)
18084 +static void graphics_subshutdown (void)
18087 + fprintf(stderr, "Function: graphics_subshutdown\n");
18090 + SDL_FreeSurface(prSDLScreen);
18093 +void graphics_leave (void)
18096 + fprintf(stderr, "Function: graphics_leave\n");
18099 + graphics_subshutdown ();
18106 +/* Decode KeySyms. This function knows about all keys that are common
18107 + * between different keyboard languages. */
18108 +static int kc_decode (SDL_keysym *prKeySym)
18110 + switch (prKeySym->sym)
18112 + case SDLK_b: return AK_B;
18113 + case SDLK_c: return AK_C;
18114 + case SDLK_d: return AK_D;
18115 + case SDLK_e: return AK_E;
18116 + case SDLK_f: return AK_F;
18117 + case SDLK_g: return AK_G;
18118 + case SDLK_h: return AK_H;
18119 + case SDLK_i: return AK_I;
18120 + case SDLK_j: return AK_J;
18121 + case SDLK_k: return AK_K;
18122 + case SDLK_l: return AK_L;
18123 + case SDLK_n: return AK_N;
18124 + case SDLK_o: return AK_O;
18125 + case SDLK_p: return AK_P;
18126 + case SDLK_r: return AK_R;
18127 + case SDLK_s: return AK_S;
18128 + case SDLK_t: return AK_T;
18129 + case SDLK_u: return AK_U;
18130 + case SDLK_v: return AK_V;
18131 + case SDLK_x: return AK_X;
18133 + case SDLK_0: return AK_0;
18134 + case SDLK_1: return AK_1;
18135 + case SDLK_2: return AK_2;
18136 + case SDLK_3: return AK_3;
18137 + case SDLK_4: return AK_4;
18138 + case SDLK_5: return AK_5;
18139 + case SDLK_6: return AK_6;
18140 + case SDLK_7: return AK_7;
18141 + case SDLK_8: return AK_8;
18142 + case SDLK_9: return AK_9;
18144 + case SDLK_KP0: return AK_NP0;
18145 + case SDLK_KP1: return AK_NP1;
18146 + case SDLK_KP2: return AK_NP2;
18147 + case SDLK_KP3: return AK_NP3;
18148 + case SDLK_KP4: return AK_NP4;
18149 + case SDLK_KP5: return AK_NP5;
18150 + case SDLK_KP6: return AK_NP6;
18151 + case SDLK_KP7: return AK_NP7;
18152 + case SDLK_KP8: return AK_NP8;
18153 + case SDLK_KP9: return AK_NP9;
18154 + case SDLK_KP_DIVIDE: return AK_NPDIV;
18155 + case SDLK_KP_MULTIPLY: return AK_NPMUL;
18156 + case SDLK_KP_MINUS: return AK_NPSUB;
18157 + case SDLK_KP_PLUS: return AK_NPADD;
18158 + case SDLK_KP_PERIOD: return AK_NPDEL;
18159 + case SDLK_KP_ENTER: return AK_ENT;
18161 + case SDLK_F1: return AK_F1;
18162 + case SDLK_F2: return AK_F2;
18163 + case SDLK_F3: return AK_F3;
18164 + case SDLK_F4: return AK_F4;
18165 + case SDLK_F5: return AK_F5;
18166 + case SDLK_F6: return AK_F6;
18167 + case SDLK_F7: return AK_F7;
18168 + case SDLK_F8: return AK_F8;
18169 + case SDLK_F9: return AK_F9;
18170 + case SDLK_F10: return AK_F10;
18172 + case SDLK_BACKSPACE: return AK_BS;
18173 + case SDLK_DELETE: return AK_DEL;
18174 + case SDLK_LCTRL: return AK_CTRL;
18175 + case SDLK_RCTRL: return AK_RCTRL;
18176 + case SDLK_TAB: return AK_TAB;
18177 + case SDLK_LALT: return AK_LALT;
18178 + case SDLK_RALT: return AK_RALT;
18179 + case SDLK_RMETA: return AK_RAMI;
18180 + case SDLK_LMETA: return AK_LAMI;
18181 + case SDLK_RETURN: return AK_RET;
18182 + case SDLK_SPACE: return AK_SPC;
18183 + case SDLK_LSHIFT: return AK_LSH;
18184 + case SDLK_RSHIFT: return AK_RSH;
18185 + case SDLK_ESCAPE: return AK_ESC;
18187 + case SDLK_INSERT: return AK_HELP;
18188 + case SDLK_HOME: return AK_NPLPAREN;
18189 + case SDLK_END: return AK_NPRPAREN;
18190 + case SDLK_CAPSLOCK: return AK_CAPSLOCK;
18192 + case SDLK_UP: return AK_UP;
18193 + case SDLK_DOWN: return AK_DN;
18194 + case SDLK_LEFT: return AK_LF;
18195 + case SDLK_RIGHT: return AK_RT;
18197 + case SDLK_PAGEUP: return AK_RAMI; /* PgUp mapped to right amiga */
18198 + case SDLK_PAGEDOWN: return AK_LAMI; /* PgDn mapped to left amiga */
18200 + default: return -1;
18204 +static int decode_fr (SDL_keysym *prKeySym)
18206 + switch(prKeySym->sym)
18208 + /* FR specific */
18209 + case SDLK_a: return AK_Q;
18210 + case SDLK_m: return AK_SEMICOLON;
18211 + case SDLK_q: return AK_A;
18212 + case SDLK_y: return AK_Y;
18213 + case SDLK_w: return AK_Z;
18214 + case SDLK_z: return AK_W;
18215 + case SDLK_LEFTBRACKET: return AK_LBRACKET;
18216 + case SDLK_RIGHTBRACKET: return AK_RBRACKET;
18217 + case SDLK_COMMA: return AK_M;
18218 + case SDLK_LESS: case SDLK_GREATER: return AK_LTGT;
18219 + case SDLK_PERIOD: case SDLK_SEMICOLON: return AK_COMMA;
18220 + case SDLK_RIGHTPAREN: return AK_MINUS;
18221 + case SDLK_EQUALS: return AK_SLASH;
18222 + case SDLK_HASH: return AK_NUMBERSIGN;
18223 + case SDLK_SLASH: return AK_PERIOD;
18224 + case SDLK_MINUS: return AK_EQUAL;
18225 + case SDLK_BACKSLASH: return AK_BACKSLASH;
18226 + default: return -1;
18230 +static int decode_us (SDL_keysym *prKeySym)
18232 + switch(prKeySym->sym)
18234 + /* US specific */
18235 + case SDLK_a: return AK_A;
18236 + case SDLK_m: return AK_M;
18237 + case SDLK_q: return AK_Q;
18238 + case SDLK_y: return AK_Y;
18239 + case SDLK_w: return AK_W;
18240 + case SDLK_z: return AK_Z;
18241 + case SDLK_LEFTBRACKET: return AK_LBRACKET;
18242 + case SDLK_RIGHTBRACKET: return AK_RBRACKET;
18243 + case SDLK_COMMA: return AK_COMMA;
18244 + case SDLK_PERIOD: return AK_PERIOD;
18245 + case SDLK_SLASH: return AK_SLASH;
18246 + case SDLK_SEMICOLON: return AK_SEMICOLON;
18247 + case SDLK_MINUS: return AK_MINUS;
18248 + case SDLK_EQUALS: return AK_EQUAL;
18249 + /* this doesn't work: */
18250 + case SDLK_BACKQUOTE: return AK_QUOTE;
18251 + case SDLK_QUOTE: return AK_BACKQUOTE;
18252 + case SDLK_BACKSLASH: return AK_BACKSLASH;
18253 + default: return -1;
18257 +static int decode_de (SDL_keysym *prKeySym)
18259 + switch(prKeySym->sym)
18261 + /* DE specific */
18262 + case SDLK_a: return AK_A;
18263 + case SDLK_m: return AK_M;
18264 + case SDLK_q: return AK_Q;
18265 + case SDLK_w: return AK_W;
18266 + case SDLK_y: return AK_Z;
18267 + case SDLK_z: return AK_Y;
18268 + /* German umlaut oe */
18269 + case SDLK_WORLD_86: return AK_SEMICOLON;
18270 + /* German umlaut ae */
18271 + case SDLK_WORLD_68: return AK_QUOTE;
18272 + /* German umlaut ue */
18273 + case SDLK_WORLD_92: return AK_LBRACKET;
18274 + case SDLK_PLUS: case SDLK_ASTERISK: return AK_RBRACKET;
18275 + case SDLK_COMMA: return AK_COMMA;
18276 + case SDLK_PERIOD: return AK_PERIOD;
18277 + case SDLK_LESS: case SDLK_GREATER: return AK_LTGT;
18278 + case SDLK_HASH: return AK_NUMBERSIGN;
18279 + /* German sharp s */
18280 + case SDLK_WORLD_63: return AK_MINUS;
18281 + case SDLK_QUOTE: return AK_EQUAL;
18282 + case SDLK_CARET: return AK_BACKQUOTE;
18283 + case SDLK_MINUS: return AK_SLASH;
18284 + default: return -1;
18288 +static int decode_se (SDL_keysym *prKeySym)
18290 + switch(prKeySym->sym)
18292 + /* SE specific */
18293 + case SDLK_a: return AK_A;
18294 + case SDLK_m: return AK_M;
18295 + case SDLK_q: return AK_Q;
18296 + case SDLK_w: return AK_W;
18297 + case SDLK_y: return AK_Y;
18298 + case SDLK_z: return AK_Z;
18299 + case SDLK_WORLD_86: return AK_SEMICOLON;
18300 + case SDLK_WORLD_68: return AK_QUOTE;
18301 + case SDLK_WORLD_69: return AK_LBRACKET;
18302 + case SDLK_COMMA: return AK_COMMA;
18303 + case SDLK_PERIOD: return AK_PERIOD;
18304 + case SDLK_MINUS: return AK_SLASH;
18305 + case SDLK_LESS: case SDLK_GREATER: return AK_LTGT;
18306 + case SDLK_PLUS: case SDLK_QUESTION: return AK_EQUAL;
18307 + case SDLK_AT: case SDLK_WORLD_29: return AK_BACKQUOTE;
18308 + case SDLK_CARET: return AK_RBRACKET;
18309 + case SDLK_BACKSLASH: return AK_MINUS;
18310 + case SDLK_HASH: return AK_NUMBERSIGN;
18311 + default: return -1;
18315 +static int decode_it (SDL_keysym *prKeySym)
18317 + switch(prKeySym->sym)
18319 + /* IT specific */
18320 + case SDLK_a: return AK_A;
18321 + case SDLK_m: return AK_M;
18322 + case SDLK_q: return AK_Q;
18323 + case SDLK_w: return AK_W;
18324 + case SDLK_y: return AK_Y;
18325 + case SDLK_z: return AK_Z;
18326 + case SDLK_WORLD_82: return AK_SEMICOLON;
18327 + case SDLK_WORLD_64: return AK_QUOTE;
18328 + case SDLK_WORLD_72: return AK_LBRACKET;
18329 + case SDLK_PLUS: case SDLK_ASTERISK: return AK_RBRACKET;
18330 + case SDLK_COMMA: return AK_COMMA;
18331 + case SDLK_PERIOD: return AK_PERIOD;
18332 + case SDLK_LESS: case SDLK_GREATER: return AK_LTGT;
18333 + case SDLK_BACKSLASH: return AK_BACKQUOTE;
18334 + case SDLK_QUOTE: return AK_MINUS;
18335 + case SDLK_WORLD_76: return AK_EQUAL;
18336 + case SDLK_MINUS: return AK_SLASH;
18337 + case SDLK_HASH: return AK_NUMBERSIGN;
18338 + default: return -1;
18342 +static int decode_es (SDL_keysym *prKeySym)
18344 + switch(prKeySym->sym)
18346 + /* ES specific */
18347 + case SDLK_a: return AK_A;
18348 + case SDLK_m: return AK_M;
18349 + case SDLK_q: return AK_Q;
18350 + case SDLK_w: return AK_W;
18351 + case SDLK_y: return AK_Y;
18352 + case SDLK_z: return AK_Z;
18353 + case SDLK_WORLD_81: return AK_SEMICOLON;
18354 + case SDLK_PLUS: case SDLK_ASTERISK: return AK_RBRACKET;
18355 + case SDLK_COMMA: return AK_COMMA;
18356 + case SDLK_PERIOD: return AK_PERIOD;
18357 + case SDLK_LESS: case SDLK_GREATER: return AK_LTGT;
18358 + case SDLK_BACKSLASH: return AK_BACKQUOTE;
18359 + case SDLK_QUOTE: return AK_MINUS;
18360 + case SDLK_WORLD_76: return AK_EQUAL;
18361 + case SDLK_MINUS: return AK_SLASH;
18362 + case SDLK_HASH: return AK_NUMBERSIGN;
18363 + default: return -1;
18367 +static int keycode2amiga(SDL_keysym *prKeySym)
18369 + int iAmigaKeycode = kc_decode(prKeySym);
18370 + if (iAmigaKeycode == -1)
18372 + switch (currprefs.keyboard_lang)
18374 + case KBD_LANG_FR:
18375 + return decode_fr(prKeySym);
18376 + case KBD_LANG_US:
18377 + return decode_us(prKeySym);
18378 + case KBD_LANG_DE:
18379 + return decode_de(prKeySym);
18380 + case KBD_LANG_SE:
18381 + return decode_se (prKeySym);
18382 + case KBD_LANG_IT:
18383 + return decode_it (prKeySym);
18384 + case KBD_LANG_ES:
18385 + return decode_es (prKeySym);
18390 + return iAmigaKeycode;
18393 +static int refresh_necessary = 0;
18395 +void handle_events (void)
18397 + SDL_Event rEvent;
18398 + int iAmigaKeyCode;
18400 + int iIsHotKey = 0;
18402 + fprintf(stderr, "Function: handle_events\n");
18405 + /* Handle GUI events */
18406 + gui_handle_events ();
18408 + while (SDL_PollEvent(&rEvent))
18410 + switch (rEvent.type)
18414 + fprintf(stderr, "Event: quit\n");
18418 + case SDL_KEYDOWN:
18420 + fprintf(stderr, "Event: key down\n");
18422 + /* Check for hotkey sequence */
18424 + while (arHotKeys[i].pfHandler != NULL)
18426 + if (rEvent.key.keysym.sym == arHotKeys[i].aHotKeys[0])
18428 + arHotKeys[i].aPressedKeys[0] = 1;
18431 + if (arHotKeys[i].aPressedKeys[0] == 1 &&
18432 + rEvent.key.keysym.sym == arHotKeys[i].aHotKeys[1])
18434 + arHotKeys[i].aPressedKeys[1] = 1;
18435 + arHotKeys[i].pfHandler();
18440 + if (iIsHotKey == 0)
18442 + /* No hotkey sequence */
18443 + iAmigaKeyCode = keycode2amiga(&(rEvent.key.keysym));
18444 + if (iAmigaKeyCode >= 0)
18446 + if (!keystate[iAmigaKeyCode])
18448 + keystate[iAmigaKeyCode] = 1;
18449 + record_key(iAmigaKeyCode << 1);
18456 + fprintf(stderr, "Event: key up\n");
18458 + /* Check for hotkey sequence */
18460 + while (arHotKeys[i].pfHandler != NULL)
18462 + for (j = 0; j < 2; j++)
18464 + if (rEvent.key.keysym.sym == arHotKeys[i].aHotKeys[j] &&
18465 + arHotKeys[i].aPressedKeys[j] == 1)
18467 + arHotKeys[i].aPressedKeys[j] = 0;
18473 + if (iIsHotKey == 0)
18475 + iAmigaKeyCode = keycode2amiga(&(rEvent.key.keysym));
18476 + if (iAmigaKeyCode >= 0)
18478 + keystate[iAmigaKeyCode] = 0;
18479 + record_key((iAmigaKeyCode << 1) | 1);
18483 + case SDL_MOUSEBUTTONDOWN:
18485 + fprintf(stderr, "Event: mouse button down\n");
18487 + buttonstate[rEvent.button.button-1] = 1;
18489 + case SDL_MOUSEBUTTONUP:
18491 + fprintf(stderr, "Event: mouse button up\n");
18493 + buttonstate[rEvent.button.button-1] = 0;
18495 + case SDL_MOUSEMOTION:
18497 + fprintf(stderr, "Event: mouse motion\n");
18499 + newmousecounters = 1;
18500 + lastmx += rEvent.motion.xrel;
18501 + lastmy += rEvent.motion.yrel;
18505 +#if defined PICASSO96
18506 + if (screen_is_picasso && refresh_necessary)
18508 + SDL_UpdateRect(prSDLScreen, 0, 0, picasso_vidinfo.width, picasso_vidinfo.height);
18509 + refresh_necessary = 0;
18510 + memset (picasso_invalid_lines, 0, sizeof picasso_invalid_lines);
18512 + else if (screen_is_picasso && picasso_has_invalid_lines)
18516 + picasso_invalid_lines[picasso_vidinfo.height] = 0;
18517 + for (i = picasso_invalid_start; i < picasso_invalid_stop + 2; i++)
18519 + if (picasso_invalid_lines[i])
18521 + picasso_invalid_lines[i] = 0;
18530 + SDL_UpdateRect(prSDLScreen, 0, strt, picasso_vidinfo.width, i-strt);
18537 + picasso_has_invalid_lines = 0;
18538 + picasso_invalid_start = picasso_vidinfo.height + 1;
18539 + picasso_invalid_stop = -1;
18542 + /* Handle UAE reset */
18543 + if ((keystate[AK_CTRL] || keystate[AK_RCTRL]) && keystate[AK_LAMI] && keystate[AK_RAMI])
18547 +int check_prefs_changed_gfx (void)
18550 + if (changed_prefs.gfx_width != currprefs.gfx_width
18551 + || changed_prefs.gfx_height != currprefs.gfx_height)
18553 + fixup_prefs_dimensions (&changed_prefs);
18556 + if (changed_prefs.gfx_width == currprefs.gfx_width
18557 + && changed_prefs.gfx_height == currprefs.gfx_height
18558 + && changed_prefs.gfx_lores == currprefs.gfx_lores
18559 + && changed_prefs.gfx_linedbl == currprefs.gfx_linedbl
18560 + && changed_prefs.gfx_correct_aspect == currprefs.gfx_correct_aspect
18561 + && changed_prefs.gfx_xcenter == currprefs.gfx_xcenter
18562 + && changed_prefs.gfx_ycenter == currprefs.gfx_ycenter
18563 + && changed_prefs.gfx_afullscreen == currprefs.gfx_afullscreen
18564 + && changed_prefs.gfx_pfullscreen == currprefs.gfx_pfullscreen)
18569 + fprintf(stderr, "Function: check_prefs_changed_gfx\n");
18571 + graphics_subshutdown ();
18572 + currprefs.gfx_width = changed_prefs.gfx_width;
18573 + currprefs.gfx_height = changed_prefs.gfx_height;
18574 + currprefs.gfx_lores = changed_prefs.gfx_lores;
18575 + currprefs.gfx_linedbl = changed_prefs.gfx_linedbl;
18576 + currprefs.gfx_correct_aspect = changed_prefs.gfx_correct_aspect;
18577 + currprefs.gfx_xcenter = changed_prefs.gfx_xcenter;
18578 + currprefs.gfx_ycenter = changed_prefs.gfx_ycenter;
18579 + currprefs.gfx_afullscreen = changed_prefs.gfx_afullscreen;
18580 + currprefs.gfx_pfullscreen = changed_prefs.gfx_pfullscreen;
18582 + gui_update_gfx ();
18584 + graphics_subinit ();
18586 + /* if (! inwindow)
18587 + XWarpPointer (display, None, mywin, 0, 0, 0, 0,
18588 + current_width / 2, current_height / 2);
18590 + notice_screen_contents_lost ();
18592 + if (screen_is_picasso)
18593 + picasso_enablescreen (1);
18597 +int debuggable (void)
18602 +int needmousehack (void)
18609 +#if 0 /* Maybe that is responsible for the joystick emulation problems on SunOS? */
18610 + static int last_on = -1;
18611 + XKeyboardControl control;
18613 + if (last_on == on)
18616 + control.led = 1; /* implementation defined */
18617 + control.led_mode = on ? LedModeOn : LedModeOff;
18618 + XChangeKeyboardControl(display, KBLed | KBLedMode, &control);
18624 +void DX_Invalidate (int first, int last)
18627 + fprintf(stderr, "Function: DX_Invalidate %i - %i\n", first, last);
18630 + if (first > last)
18633 + picasso_has_invalid_lines = 1;
18634 + if (first < picasso_invalid_start)
18635 + picasso_invalid_start = first;
18636 + if (last > picasso_invalid_stop)
18637 + picasso_invalid_stop = last;
18639 + while (first <= last)
18641 + picasso_invalid_lines[first] = 1;
18646 +int DX_BitsPerCannon (void)
18651 +static int palette_update_start=256;
18652 +static int palette_update_end=0;
18654 +void DX_SetPalette (int start, int count)
18657 + fprintf(stderr, "Function: DX_SetPalette_real\n");
18660 + if (! screen_is_picasso || picasso96_state.RGBFormat != RGBFB_CHUNKY)
18663 + if (picasso_vidinfo.pixbytes != 1)
18665 + /* This is the case when we're emulating a 256 color display. */
18666 + while (count-- > 0)
18668 + int r = picasso96_state.CLUT[start].Red;
18669 + int g = picasso96_state.CLUT[start].Green;
18670 + int b = picasso96_state.CLUT[start].Blue;
18671 + picasso_vidinfo.clut[start++] = (doMask256 (r, red_bits, red_shift)
18672 + | doMask256 (g, green_bits, green_shift)
18673 + | doMask256 (b, blue_bits, blue_shift));
18678 + while (count-- > 0)
18681 + XColor col = parsed_xcolors[start];
18682 + col.red = picasso96_state.CLUT[start].Red * 0x0101;
18683 + col.green = picasso96_state.CLUT[start].Green * 0x0101;
18684 + col.blue = picasso96_state.CLUT[start].Blue * 0x0101;
18685 + XStoreColor (display, cmap, &col);
18691 +int DX_FillResolutions (uae_u16 *ppixel_format)
18693 + int i, count = 0;
18696 + int emulate_chunky = 0;
18699 + fprintf(stderr, "Function: DX_FillResolutions\n");
18702 + /* Find out, which is the highest resolution the SDL can offer */
18703 + for (i = MAX_SCREEN_MODES-1; i>=0; i--)
18705 + if (bitdepth == SDL_VideoModeOK(x_size_table[i], y_size_table[i], bitdepth, SDL_SWSURFACE))
18707 + w = x_size_table[i];
18708 + h = y_size_table[i];
18714 + fprintf(stderr, "Max. Picasso screen size: %d x %d\n", w, h);
18717 + picasso_vidinfo.rgbformat = (bit_unit == 8 ? RGBFB_CHUNKY
18718 + : bitdepth == 15 && bit_unit == 16 ? RGBFB_R5G5B5PC
18719 + : bitdepth == 16 && bit_unit == 16 ? RGBFB_R5G6B5PC
18720 + : bit_unit == 24 ? RGBFB_B8G8R8
18721 + : bit_unit == 32 ? RGBFB_B8G8R8A8
18724 + *ppixel_format = 1 << picasso_vidinfo.rgbformat;
18725 + if (bit_unit == 16 || bit_unit == 32)
18727 + *ppixel_format |= RGBFF_CHUNKY;
18728 + emulate_chunky = 1;
18731 + for (i = 0; i < MAX_SCREEN_MODES && count < MAX_PICASSO_MODES; i++)
18734 + for (j = 0; j <= emulate_chunky && count < MAX_PICASSO_MODES; j++)
18736 + if (x_size_table[i] <= w && y_size_table[i] <= h)
18738 + if (x_size_table[i] > picasso_maxw)
18739 + picasso_maxw = x_size_table[i];
18740 + if (y_size_table[i] > picasso_maxh)
18741 + picasso_maxh = y_size_table[i];
18742 + DisplayModes[count].res.width = x_size_table[i];
18743 + DisplayModes[count].res.height = y_size_table[i];
18744 + DisplayModes[count].depth = j == 1 ? 1 : bit_unit >> 3;
18745 + DisplayModes[count].refresh = 75;
18747 + fprintf(stderr, "Picasso resolution %d x %d @ %d allowed\n", DisplayModes[count].res.width, DisplayModes[count].res.height, DisplayModes[count].depth);
18755 + fprintf(stderr, "Max. Picasso screen size: %d x %d\n", picasso_maxw, picasso_maxh);
18760 +static void set_window_for_picasso (void)
18763 + fprintf(stderr, "Function: set_window_for_picasso\n");
18766 + if (current_width == picasso_vidinfo.width && current_height == picasso_vidinfo.height)
18769 + current_width = picasso_vidinfo.width;
18770 + current_height = picasso_vidinfo.height;
18771 + graphics_subshutdown ();
18772 + graphics_subinit ();
18773 +// XResizeWindow (display, mywin, current_width, current_height);
18776 +void gfx_set_picasso_modeinfo (int w, int h, int depth, int rgbfmt)
18779 + fprintf(stderr, "Function: gfx_set_picasso_modeinfo w: %i h: %i depth: %i rgbfmt: %i\n",w, h, depth, rgbfmt);
18782 + picasso_vidinfo.width = w;
18783 + picasso_vidinfo.height = h;
18784 + picasso_vidinfo.depth = depth;
18785 + picasso_vidinfo.pixbytes = bit_unit >> 3;
18786 + if (screen_is_picasso)
18787 + set_window_for_picasso();
18790 +void gfx_set_picasso_baseaddr (uaecptr a)
18794 +void gfx_set_picasso_state (int on)
18797 + fprintf(stderr, "Function: gfx_set_picasso_state\n");
18800 + if (on == screen_is_picasso)
18802 + graphics_subshutdown ();
18803 + screen_is_picasso = on;
18806 + // Set height, width for Picasso gfx
18807 + current_width = picasso_vidinfo.width;
18808 + current_height = picasso_vidinfo.height;
18812 + // Set height, width for Amiga gfx
18813 + current_width = gfxvidinfo.width;
18814 + current_height = gfxvidinfo.height;
18816 + graphics_subinit ();
18818 + DX_SetPalette (0, 256);
18821 +uae_u8 *gfx_lock_picasso (void)
18824 + fprintf(stderr, "Function: gfx_lock_picasso\n");
18826 + SDL_LockSurface(prSDLScreen);
18827 + return prSDLScreen->pixels;
18830 +void gfx_unlock_picasso (void)
18833 + fprintf(stderr, "Function: gfx_unlock_picasso\n");
18835 + SDL_UnlockSurface(prSDLScreen);
18839 +int lockscr (void)
18842 + fprintf(stderr, "Function: lockscr\n");
18844 + SDL_LockSurface(prSDLScreen);
18848 +void unlockscr (void)
18851 + fprintf(stderr, "Function: unlockscr\n");
18853 + SDL_UnlockSurface(prSDLScreen);
18856 +static void handle_mousegrab (void)
18858 + if (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF)
18860 + SDL_WM_GrabInput(SDL_GRAB_ON);
18861 + SDL_WarpMouse(0, 0);
18865 + SDL_WM_GrabInput(SDL_GRAB_OFF);
18869 +static void handle_inhibit (void)
18871 + toggle_inhibit_frame (IHF_SCROLLLOCK);
18875 +static void handle_interpol (void)
18877 + if (currprefs.sound_interpol == 0)
18879 + currprefs.sound_interpol = 1;
18880 + printf ("Interpol on: rh\n");
18882 + else if (currprefs.sound_interpol == 1)
18884 + currprefs.sound_interpol = 2;
18885 + printf ("Interpol on: crux\n");
18889 + currprefs.sound_interpol = 0;
18890 + printf ("Interpol off\n");
18894 +static void framerate_up (void)
18896 + if (currprefs.gfx_framerate < 20)
18897 + changed_prefs.gfx_framerate = currprefs.gfx_framerate + 1;
18900 +static void framerate_down (void)
18902 + if (currprefs.gfx_framerate > 1)
18903 + changed_prefs.gfx_framerate = currprefs.gfx_framerate - 1;
18906 +void target_save_options (FILE *f, struct uae_prefs *p)
18910 +int target_parse_option (struct uae_prefs *p, char *option, char *value)
18914 diff -urN src-0.8.22/src/serial.c src-0.8.22-mmu/src/serial.c
18915 --- src-0.8.22/src/serial.c 2001-12-17 19:38:38.000000000 +0100
18916 +++ src-0.8.22-mmu/src/serial.c 2003-07-25 12:12:12.000000000 +0200
18918 #define O_NONBLOCK O_NDELAY
18921 -#define SERIALDEBUG 1 /* 0, 1, 2 3 */
18922 +#define SERIALDEBUG 0 /* 0, 1, 2 3 */
18923 #define MODEMTEST 0 /* 0 or 1 */
18925 void serial_open (void);
18926 @@ -80,18 +80,25 @@
18930 +static int ser_log = 0;
18932 #ifdef POSIX_SERIAL
18933 struct termios tios;
18936 -uae_u16 serper=0,serdat;
18937 +uae_u16 serper=0, serdat = 0;
18939 void SERPER (uae_u16 w)
18941 int baud=0, pspeed;
18943 - if (!currprefs.use_serial)
18944 + if (!currprefs.use_serial) {
18945 + ser_log = (w == 0x170); /* enable logging if we are using 9600 BAUD */
18946 +#if SERIALDEBUG > 1
18947 + write_log("SERPER: %x\n", w);
18952 #if defined POSIX_SERIAL
18953 if (serper == w) /* don't set baudrate if it's already ok */
18954 @@ -178,12 +185,9 @@
18958 - if (!currprefs.use_serial)
18961 z = (unsigned char)(w&0xff);
18963 - if (currprefs.serial_demand && !dtr) {
18964 + if (currprefs.serial_demand && !dtr && !ser_log) {
18966 write_log("SERDAT: Baeh.. Your software needs SERIAL_ALWAYS to work properly.\n");
18968 @@ -206,8 +210,6 @@
18970 uae_u16 SERDATR (void)
18972 - if (!currprefs.use_serial)
18974 #if SERIALDEBUG > 2
18975 write_log ("SERDATR: read 0x%04x\n", serdat);
18977 @@ -284,10 +286,14 @@
18979 void serial_flush_buffer(void)
18981 - if (serdev == 1) {
18983 + if (serdev == 1 || ser_log) {
18986 - write (sd, outbuf, outlast);
18987 + write (sd, outbuf, outlast);
18990 + outbuf[outlast] = 0;
18991 + write_log("SER: %s\n", outbuf);
18995 diff -urN src-0.8.22/src/serial.c~ src-0.8.22-mmu/src/serial.c~
18996 --- src-0.8.22/src/serial.c~ 1970-01-01 01:00:00.000000000 +0100
18997 +++ src-0.8.22-mmu/src/serial.c~ 2003-07-25 12:11:11.000000000 +0200
19000 + * UAE - The Un*x Amiga Emulator
19002 + * Serial Line Emulation
19004 + * (c) 1996, 1997 Stefan Reinauer <stepan@linux.de>
19005 + * (c) 1997 Christian Schmitt <schmitt@freiburg.linux.de>
19009 +#include "sysconfig.h"
19010 +#include "sysdeps.h"
19012 +#include "config.h"
19013 +#include "options.h"
19015 +#include "memory.h"
19016 +#include "custom.h"
19017 +#include "newcpu.h"
19020 +#undef POSIX_SERIAL
19021 +/* Some more or less good way to determine whether we can safely compile in
19022 + * the serial stuff. I'm certain it breaks compilation on some systems. */
19023 +#if defined HAVE_SYS_TERMIOS_H && defined HAVE_POSIX_OPT_H && defined HAVE_SYS_IOCTL_H && defined HAVE_TCGETATTR
19024 +#define POSIX_SERIAL
19027 +#ifdef POSIX_SERIAL
19028 +#include <termios.h>
19029 +#include <unistd.h>
19030 +#include <sys/ioctl.h>
19033 +#if !defined B300 || !defined B1200 || !defined B2400 || !defined B4800 || !defined B9600
19034 +#undef POSIX_SERIAL
19036 +#if !defined B19200 || !defined B57600 || !defined B115200 || !defined B230400
19037 +#undef POSIX_SERIAL
19040 +#ifndef O_NONBLOCK
19041 +#define O_NONBLOCK O_NDELAY
19044 +#define SERIALDEBUG 0 /* 0, 1, 2 3 */
19045 +#define MODEMTEST 0 /* 0 or 1 */
19047 +void serial_open (void);
19048 +void serial_close (void);
19049 +void serial_init (void);
19050 +void serial_exit (void);
19052 +void serial_dtr_on (void);
19053 +void serial_dtr_off (void);
19055 +void serial_flush_buffer (void);
19056 +static int serial_read (char *buffer);
19058 +int serial_readstatus (void);
19059 +uae_u16 serial_writestatus (int, int);
19061 +uae_u16 SERDATR (void);
19063 +int SERDATS (void);
19064 +void SERPER (uae_u16 w);
19065 +void SERDAT (uae_u16 w);
19067 +static char inbuf[1024], outbuf[1024];
19068 +static int inptr, inlast, outlast;
19081 +static int ser_log = 0;
19083 +#ifdef POSIX_SERIAL
19084 + struct termios tios;
19087 +uae_u16 serper=0, serdat = 0;
19089 +void SERPER (uae_u16 w)
19091 + int baud=0, pspeed;
19093 + if (!currprefs.use_serial) {
19094 + ser_log = (w == 0x170); /* enable logging if we are using 9600 BAUD */
19095 +#if SERIALDEBUG > 1
19096 + write_log("SERPER: %x\n", w);
19101 +#if defined POSIX_SERIAL
19102 + if (serper == w) /* don't set baudrate if it's already ok */
19107 + write_log ("SERPER: 9bit transmission not implemented.\n");
19109 + switch (w & 0x7fff) {
19110 + /* These values should be calculated by the current
19111 + * color clock value (NTSC/PAL). But this solution is
19112 + * easy and it works.
19116 + case 0x2e14: baud=300; pspeed=B300; break;
19118 + case 0x0b85: baud=1200; pspeed=B1200; break;
19120 + case 0x05b9: baud=2400; pspeed=B2400; break;
19122 + case 0x02e1: baud=4800; pspeed=B4800; break;
19124 + case 0x0170: baud=9600; pspeed=B9600; break;
19126 + case 0x00b8: baud=19200; pspeed=B19200; break;
19128 + case 0x005d: baud=38400; pspeed=B38400; break;
19129 + case 0x003d: baud=57600; pspeed=B57600; break;
19130 + case 0x001e: baud=115200; pspeed=B115200; break;
19131 + case 0x000f: baud=230400; pspeed=B230400; break;
19133 + write_log ("SERPER: unsupported baudrate (0x%04x) %d\n",w&0x7fff,
19134 + (unsigned int)(3579546.471/(double)((w&0x7fff)+1))); return;
19137 + /* Only access hardware when we own it */
19138 + if (serdev == 1) {
19139 + if (tcgetattr (sd, &tios) < 0) {
19140 + write_log ("SERPER: TCGETATTR failed\n");
19144 + if (cfsetispeed (&tios, pspeed) < 0) { /* set serial input speed */
19145 + write_log ("SERPER: CFSETISPEED (%d bps) failed\n", baud);
19148 + if (cfsetospeed (&tios, pspeed) < 0) { /* set serial output speed */
19149 + write_log ("SERPER: CFSETOSPEED (%d bps) failed\n", baud);
19153 + if (tcsetattr (sd, TCSADRAIN, &tios) < 0) {
19154 + write_log ("SERPER: TCSETATTR failed\n");
19160 +#if SERIALDEBUG > 0
19162 + write_log ("SERPER: baudrate set to %d bit/sec\n", baud);
19166 +/* Not (fully) implemented yet:
19168 + * - Something's wrong with the Interrupts.
19169 + * (NComm works, TERM does not. TERM switches to a
19170 + * blind mode after a connect and wait's for the end
19171 + * of an asynchronous read before switching blind
19172 + * mode off again. It never gets there on UAE :-< )
19174 + * - RTS/CTS handshake, this is not really neccessary,
19175 + * because you can use RTS/CTS "outside" without
19176 + * passing it through to the emulated Amiga
19178 + * - ADCON-Register ($9e write, $10 read) Bit 11 (UARTBRK)
19179 + * (see "Amiga Intern", pg 246)
19182 +void SERDAT (uae_u16 w)
19186 + z = (unsigned char)(w&0xff);
19188 + if (currprefs.serial_demand && !dtr && !ser_log) {
19190 + write_log("SERDAT: Baeh.. Your software needs SERIAL_ALWAYS to work properly.\n");
19195 + outbuf[outlast++] = z;
19196 + if (outlast == sizeof outbuf)
19197 + serial_flush_buffer();
19200 +#if SERIALDEBUG > 2
19201 + write_log ("SERDAT: wrote 0x%04x\n", w);
19204 + serdat|=0x2000; /* Set TBE in the SERDATR ... */
19205 + intreq|=1; /* ... and in INTREQ register */
19209 +uae_u16 SERDATR (void)
19211 +#if SERIALDEBUG > 2
19212 + write_log ("SERDATR: read 0x%04x\n", serdat);
19218 +int SERDATS (void)
19222 + if (!serdev) /* || (serdat&0x4000)) */
19225 + if (waitqueue == 1) {
19226 + intreq |= 0x0800;
19230 + if ((serial_read ((char *)&z)) == 1) {
19232 + serdat = 0x4100; /* RBF and STP set! */
19233 + serdat |= ((unsigned int)z) & 0xff;
19234 + intreq |= 0x0800; /* Set RBF flag (Receive Buffer full) */
19236 +#if SERIALDEBUG > 1
19237 + write_log ("SERDATS: received 0x%02x --> serdat==0x%04x\n",
19238 + (unsigned int)z, (unsigned int)serdat);
19245 +void serial_dtr_on(void)
19247 +#if SERIALDEBUG > 0
19248 + write_log ("DTR on.\n");
19252 + if (currprefs.serial_demand)
19256 +void serial_dtr_off(void)
19258 +#if SERIALDEBUG > 0
19259 + write_log ("DTR off.\n");
19262 + if (currprefs.serial_demand)
19266 +static int serial_read (char *buffer)
19268 + if (inptr < inlast) {
19269 + *buffer = inbuf[inptr++];
19273 + if (serdev == 1) {
19274 + inlast = read (sd, inbuf, sizeof inbuf);
19276 + if (inptr < inlast) {
19277 + *buffer = inbuf[inptr++];
19285 +void serial_flush_buffer(void)
19287 + if (serdev == 1 || ser_log) {
19290 + write (sd, outbuf, outlast);
19293 + outbuf[outlast] = 0;
19294 + write_log("SER: %s\n", outbuf);
19305 +int serial_readstatus(void)
19309 +#ifdef POSIX_SERIAL
19310 + ioctl (sd, TIOCMGET, &status);
19312 + if (status & TIOCM_CAR) {
19314 + ciabpra |= 0x20; /* Push up Carrier Detect line */
19316 +#if SERIALDEBUG > 0
19317 + write_log ("Carrier detect.\n");
19322 + ciabpra &= ~0x20;
19324 +#if SERIALDEBUG > 0
19325 + write_log ("Carrier lost.\n");
19330 + if (status & TIOCM_DSR) {
19332 + ciabpra |= 0x08; /* DSR ON */
19337 + ciabpra &= ~0x08;
19345 +uae_u16 serial_writestatus (int old, int nw)
19347 + if ((old & 0x80) == 0x80 && (nw & 0x80) == 0x00)
19349 + if ((old & 0x80) == 0x00 && (nw & 0x80) == 0x80)
19350 + serial_dtr_off();
19352 + if ((old & 0x40) != (nw & 0x40))
19353 + write_log ("RTS %s.\n", ((nw & 0x40) == 0x40) ? "set" : "cleared");
19355 + if ((old & 0x10) != (nw & 0x10))
19356 + write_log ("CTS %s.\n", ((nw & 0x10) == 0x10) ? "set" : "cleared");
19358 + return nw; /* This value could also be changed here */
19361 +void serial_open(void)
19366 + if ((sd = open (currprefs.sername, O_RDWR|O_NONBLOCK|O_BINARY, 0)) < 0) {
19367 + write_log ("Error: Could not open Device %s\n", currprefs.sername);
19373 +#ifdef POSIX_SERIAL
19374 + if (tcgetattr (sd, &tios) < 0) { /* Initialize Serial tty */
19375 + write_log ("Serial: TCGETATTR failed\n");
19378 + cfmakeraw (&tios);
19381 + tios.c_cflag &= ~CRTSCTS; /* Disable RTS/CTS */
19383 + tios.c_cflag |= CRTSCTS; /* Enabled for testing modems */
19386 + if (tcsetattr (sd, TCSADRAIN, &tios) < 0) {
19387 + write_log ("Serial: TCSETATTR failed\n");
19393 +void serial_close (void)
19400 +void serial_init (void)
19402 + if (!currprefs.use_serial)
19405 + if (!currprefs.serial_demand)
19412 +void serial_exit (void)
19414 + serial_close (); /* serial_close can always be called because it */
19415 + dtr = 0; /* just closes *opened* filehandles which is ok */
19416 + return; /* when exiting. */