]> pere.pagekite.me Git - homepage.git/blob - linux/uae-0.8.22-mmu.diff
Switched blog to hungry.com for now. Updated all links.
[homepage.git] / linux / uae-0.8.22-mmu.diff
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
4 @@ -33,7 +33,7 @@
5
6 INCLUDES=-I. -I@top_srcdir@/src/include/
7
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 \
13 @@ -104,7 +104,7 @@
14 $(MAKE) -C tools build68kc
15 tools/cpuopti:
16 $(MAKE) -C tools cpuopti
17 -tools/gencpu:
18 +tools/gencpu: gencpu.c
19 $(MAKE) -C tools gencpu
20
21 custom.o: blit.h
22 @@ -113,14 +113,14 @@
23 cpudefs.c: tools/build68k @top_srcdir@/src/table68k
24 ./tools/build68k <@top_srcdir@/src/table68k >cpudefs.c
25
26 -cpuemu.c: tools/gencpu
27 +cpuemu.c: tools/gencpu @top_srcdir@/src/table68k
28 ./tools/gencpu
29
30 # gencpu also creates cpustbl.c and cputbl.h
31 -cpustbl.c: cpuemu.c
32 -cputbl.h: cpuemu.c
33 +cpustbl.c: cpuemu.c @top_srcdir@/src/table68k
34 +cputbl.h: cpuemu.c @top_srcdir@/src/table68k
35
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 >$@
40 rm 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
44 @@ -4052,6 +4052,7 @@
45
46 n_frames = 0;
47
48 + mmu_set_tc(0);
49 expamem_reset ();
50
51 DISK_reset ();
52 @@ -4514,8 +4515,10 @@
53 uae_u16 rval = (value << 8) | (value & 0xFF);
54 special_mem |= S_WRITE;
55 custom_wput (addr, rval);
56 - if (!warned)
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);
60 + warned++;
61 + }
62 }
63
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
68 @@ -0,0 +1,4878 @@
69 + /*
70 + * UAE - The Un*x Amiga Emulator
71 + *
72 + * Custom chip emulation
73 + *
74 + * Copyright 1995-2002 Bernd Schmidt
75 + * Copyright 1995 Alessandro Bissacco
76 + * Copyright 2000-2002 Toni Wilen
77 + */
78 +
79 +#include "sysconfig.h"
80 +#include "sysdeps.h"
81 +
82 +#include <ctype.h>
83 +#include <assert.h>
84 +
85 +#include "config.h"
86 +#include "options.h"
87 +#include "threaddep/thread.h"
88 +#include "uae.h"
89 +#include "gensound.h"
90 +#include "sounddep/sound.h"
91 +#include "events.h"
92 +#include "memory.h"
93 +#include "custom.h"
94 +#include "newcpu.h"
95 +#include "cia.h"
96 +#include "disk.h"
97 +#include "blitter.h"
98 +#include "xwin.h"
99 +#include "joystick.h"
100 +#include "audio.h"
101 +#include "keybuf.h"
102 +#include "serial.h"
103 +#include "osemu.h"
104 +#include "autoconf.h"
105 +#include "gui.h"
106 +#include "picasso96.h"
107 +#include "drawing.h"
108 +#include "savestate.h"
109 +
110 +#define SPRITE_COLLISIONS
111 +
112 +static uae_u16 last_custom_value;
113 +
114 +static unsigned int n_consecutive_skipped = 0;
115 +static unsigned int total_skipped = 0;
116 +
117 +/* Mouse and joystick emulation */
118 +
119 +int buttonstate[3];
120 +static int mouse_x, mouse_y;
121 +int joy0button, joy1button;
122 +unsigned int joy0dir, joy1dir;
123 +
124 +/* Events */
125 +
126 +unsigned long int currcycle, nextevent, is_lastline;
127 +static int rpt_did_reset;
128 +struct ev eventtab[ev_max];
129 +
130 +frame_time_t vsynctime, vsyncmintime;
131 +
132 +static int vpos;
133 +static uae_u16 lof;
134 +static int next_lineno;
135 +static enum nln_how nextline_how;
136 +static int lof_changed = 0;
137 +
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];
142 +
143 +/*
144 + * Hardware registers of all sorts.
145 + */
146 +
147 +static void custom_wput_1 (int, uaecptr, uae_u32) REGPARAM;
148 +
149 +static uae_u16 cregs[256];
150 +
151 +uae_u16 intena,intreq;
152 +uae_u16 dmacon;
153 +uae_u16 adkcon; /* used by audio code */
154 +
155 +static uae_u32 cop1lc,cop2lc,copcon;
156 +
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;
163 +static int fmode;
164 +static unsigned int beamcon0, new_beamcon0;
165 +
166 +#define MAX_SPRITES 8
167 +
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 };
171 +
172 +struct sprite {
173 + uaecptr pt;
174 + int xpos;
175 + int vstart;
176 + int vstop;
177 + int armed;
178 + enum sprstate state;
179 +};
180 +
181 +static struct sprite spr[8];
182 +
183 +static int sprite_vblank_endline = 25;
184 +
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;
190 +
191 +static uae_u32 bpl1dat, bpl2dat, bpl3dat, bpl4dat, bpl5dat, bpl6dat, bpl7dat, bpl8dat;
192 +static uae_s16 bpl1mod, bpl2mod;
193 +
194 +static uaecptr bplpt[8];
195 +uae_u8 *real_bplpt[8];
196 +/* Used as a debugging aid, to offset any bitplane temporarily. */
197 +int bpl_off[8];
198 +
199 +/*static int blitcount[256]; blitter debug */
200 +
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;
206 +
207 +/* The display and data fetch windows */
208 +
209 +enum diw_states
210 +{
211 + DIW_waiting_start, DIW_waiting_stop
212 +};
213 +
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;
220 +
221 +/* Sprite collisions */
222 +static unsigned int clxdat, clxcon, clxcon2, clxcon_bpl_enable, clxcon_bpl_match;
223 +static int clx_sprmask;
224 +
225 +enum copper_states {
226 + COP_stop,
227 + COP_read1_in2,
228 + COP_read1_wr_in4,
229 + COP_read1_wr_in2,
230 + COP_read1,
231 + COP_read2_wr_in2,
232 + COP_read2,
233 + COP_bltwait,
234 + COP_wait_in4,
235 + COP_wait_in2,
236 + COP_skip_in4,
237 + COP_skip_in2,
238 + COP_wait1,
239 + COP_wait
240 +};
241 +
242 +struct copper {
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;
249 + int hpos, vpos;
250 + unsigned int ignore_next;
251 + int vcmp, hcmp;
252 +
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
255 + dramatically. */
256 + unsigned int first_sync;
257 + unsigned int regtypes_modified;
258 +};
259 +
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
269 +
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
274 +
275 +
276 +static unsigned int regtypes[512];
277 +
278 +static struct copper cop_state;
279 +static int copper_enabled_thisline;
280 +static int cop_min_waittime;
281 +
282 +/*
283 + * Statistics
284 + */
285 +
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;
289 +int bogusframe;
290 +int n_frames;
291 +
292 +#define DEBUG_COPPER 0
293 +#if DEBUG_COPPER
294 +/* 10000 isn't enough! */
295 +#define NR_COPPER_RECORDS 40000
296 +#else
297 +#define NR_COPPER_RECORDS 1
298 +#endif
299 +
300 +/* Record copper activity for the debugger. */
301 +struct cop_record
302 +{
303 + int hpos, vpos;
304 + uaecptr addr;
305 +};
306 +static struct cop_record cop_record[2][NR_COPPER_RECORDS];
307 +static int nr_cop_records[2];
308 +static int curr_cop_set;
309 +
310 +/* Recording of custom chip register changes. */
311 +static int current_change_set;
312 +
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;
325 +#else
326 +struct sprite_entry sprite_entries[2][MAX_SPR_PIXELS / 16];
327 +struct color_change color_changes[2][MAX_REG_CHANGE];
328 +#endif
329 +
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];
333 +
334 +static int next_sprite_entry = 0;
335 +static int prev_next_sprite_entry;
336 +static int next_sprite_forced = 1;
337 +
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;
342 +
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;
346 +
347 +static uae_u32 thisline_changed;
348 +
349 +#ifdef SMART_UPDATE
350 +#define MARK_LINE_CHANGED do { thisline_changed = 1; } while (0)
351 +#else
352 +#define MARK_LINE_CHANGED do { ; } while (0)
353 +#endif
354 +
355 +static struct decision thisline_decision;
356 +static int passed_plfstop, fetch_cycle;
357 +
358 +enum fetchstate {
359 + fetch_not_started,
360 + fetch_started,
361 + fetch_was_plane0
362 +} fetch_state;
363 +
364 +/*
365 + * helper functions
366 + */
367 +
368 +uae_u32 get_copper_address (int copno)
369 +{
370 + switch (copno) {
371 + case 1: return cop1lc;
372 + case 2: return cop2lc;
373 + default: return 0;
374 + }
375 +}
376 +
377 +STATIC_INLINE void record_copper (uaecptr addr, int hpos, int vpos)
378 +{
379 +#if DEBUG_COPPER
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;
386 + }
387 +#endif
388 +}
389 +
390 +int find_copper_record (uaecptr addr, int *phpos, int *pvpos)
391 +{
392 + int s = curr_cop_set ^ 1;
393 + int t = nr_cop_records[s];
394 + int i;
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;
399 + return 1;
400 + }
401 + }
402 + return 0;
403 +}
404 +
405 +int rpt_available = 0;
406 +
407 +void reset_frame_rate_hack (void)
408 +{
409 + if (currprefs.m68k_speed != -1)
410 + return;
411 +
412 + if (! rpt_available) {
413 + currprefs.m68k_speed = 0;
414 + return;
415 + }
416 +
417 + rpt_did_reset = 1;
418 + is_lastline = 0;
419 + vsyncmintime = read_processor_time() + vsynctime;
420 + write_log ("Resetting frame rate hack\n");
421 +}
422 +
423 +void check_prefs_changed_custom (void)
424 +{
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 ();
432 + }
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;
437 +}
438 +
439 +STATIC_INLINE void setclr (uae_u16 *p, uae_u16 val)
440 +{
441 + if (val & 0x8000)
442 + *p |= val & 0x7FFF;
443 + else
444 + *p &= ~val;
445 +}
446 +
447 +__inline__ int current_hpos (void)
448 +{
449 + return (get_cycles () - eventtab[ev_hsync].oldcycles) / CYCLE_UNIT;
450 +}
451 +
452 +STATIC_INLINE uae_u8 *pfield_xlateptr (uaecptr plpt, int bytecount)
453 +{
454 + if (!chipmem_bank.check (plpt, bytecount)) {
455 + static int count = 0;
456 + if (!count)
457 + count++, write_log ("Warning: Bad playfield pointer\n");
458 + return NULL;
459 + }
460 + return chipmem_bank.xlateaddr (plpt);
461 +}
462 +
463 +STATIC_INLINE void docols (struct color_entry *colentry)
464 +{
465 + int i;
466 +
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)
471 + continue;
472 + colentry->acolors[i] = CONVERT_RGB (v);
473 + }
474 + } else {
475 + for (i = 0; i < 32; i++) {
476 + int v = color_reg_get (colentry, i);
477 + if (v < 0 || v > 4095)
478 + continue;
479 + colentry->acolors[i] = xcolors[v];
480 + }
481 + }
482 +}
483 +
484 +void notice_new_xcolors (void)
485 +{
486 + int i;
487 +
488 + docols(&current_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);
493 + }
494 +}
495 +
496 +static void do_sprites (int currhp);
497 +
498 +static void remember_ctable (void)
499 +{
500 + if (remembered_color_entry == -1) {
501 + /* The colors changed since we last recorded a color map. Record a
502 + * new one. */
503 + color_reg_cpy (curr_color_tables + next_color_entry, &current_colors);
504 + remembered_color_entry = next_color_entry++;
505 + }
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)
509 + {
510 + /* The remembered comparison didn't help us - need to compare again. */
511 + int oldctable = line_decisions[next_lineno].ctable;
512 + int changed = 0;
513 +
514 + if (oldctable == -1) {
515 + changed = 1;
516 + color_src_match = color_dest_match = -1;
517 + } else {
518 + color_compare_result = color_reg_cmp (&prev_color_tables[oldctable], &current_colors) != 0;
519 + if (color_compare_result)
520 + changed = 1;
521 + color_src_match = oldctable;
522 + color_dest_match = remembered_color_entry;
523 + }
524 + thisline_changed |= changed;
525 + } else {
526 + /* We know the result of the comparison */
527 + if (color_compare_result)
528 + thisline_changed = 1;
529 + }
530 +}
531 +
532 +static void remember_ctable_for_border (void)
533 +{
534 + remember_ctable ();
535 +}
536 +
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
539 + * checked. */
540 +static void decide_diw (int hpos)
541 +{
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)
545 + {
546 + thisline_decision.diwfirstword = diwfirstword < 0 ? 0 : diwfirstword;
547 + hdiwstate = DIW_waiting_stop;
548 + thisline_decision.diwlastword = -1;
549 + }
550 + if (hdiwstate == DIW_waiting_stop && thisline_decision.diwlastword == -1
551 + && pix_hpos >= diwlastword && last_diw_pix_hpos < diwlastword)
552 + {
553 + thisline_decision.diwlastword = diwlastword < 0 ? 0 : diwlastword;
554 + hdiwstate = DIW_waiting_start;
555 + }
556 + last_diw_pix_hpos = pix_hpos;
557 +}
558 +
559 +/* The HRM says 0xD8, but that can't work... */
560 +#define HARD_DDF_STOP (0xD4)
561 +
562 +static void finish_playfield_line (void)
563 +{
564 + int m1, m2;
565 +
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;
570 +
571 + if ((currprefs.chipset_mask & CSMASK_AGA) && (fmode & 0x4000)) {
572 + if (((diwstrt >> 8) ^ vpos) & 1)
573 + m1 = m2 = bpl2mod;
574 + else
575 + m1 = m2 = bpl1mod;
576 + } else {
577 + m1 = bpl1mod;
578 + m2 = bpl2mod;
579 + }
580 +
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;
591 + }
592 +
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;
598 +
599 +#ifdef SMART_UPDATE
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
606 + )
607 +#endif /* SMART_UPDATE */
608 + thisline_changed = 1;
609 +}
610 +
611 +static int fetchmode;
612 +
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
616 + 0x30 + n * 8. */
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
621 + resolutions). */
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:
625 + 8 planes: 73516240
626 + 4 planes: 3120
627 + 2 planes: 10. */
628 +static int fm_maxplane, fm_maxplane_shift;
629 +
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 };
634 +
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 };
638 +
639 +static void debug_cycle_diagram(void)
640 +{
641 + int fm, res, planes, cycle, v;
642 + char aa;
643 +
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);
653 + }
654 + write_log("\n");
655 + }
656 + write_log("\n");
657 + }
658 + }
659 + fm=0;
660 +}
661 +
662 +static void create_cycle_diagram_table(void)
663 +{
664 + int fm, res, cycle, planes, v;
665 + int fetch_start, max_planes;
666 + int *cycle_sequence;
667 +
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]) {
680 + v = 1;
681 + } else {
682 + v = 0;
683 + }
684 + cycle_diagram_table[fm][res][planes][cycle] = v;
685 + }
686 + }
687 + }
688 + }
689 + }
690 +#if 0
691 + debug_cycle_diagram ();
692 +#endif
693 +}
694 +
695 +
696 +/* Used by the copper. */
697 +static int estimated_last_fetch_cycle;
698 +static int cycle_diagram_shift;
699 +
700 +static void estimate_last_fetch_cycle (int hpos)
701 +{
702 + int fetchunit = fetchunits[fetchmode * 4 + GET_RES (bplcon0)];
703 +
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);
709 +
710 + estimated_last_fetch_cycle = hpos + (starting_last_block_at - fetch_cycle) + fetchunit;
711 + } else {
712 + int starting_last_block_at = (fetch_cycle + fetchunit - 1) & ~(fetchunit - 1);
713 + if (passed_plfstop == 2)
714 + starting_last_block_at -= fetchunit;
715 +
716 + estimated_last_fetch_cycle = hpos + (starting_last_block_at - fetch_cycle) + fetchunit;
717 + }
718 +}
719 +
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];
726 +
727 +/* Expansions from bplcon0/bplcon1. */
728 +static int toscr_res, toscr_delay1, toscr_delay2, toscr_nr_planes, fetchwidth;
729 +
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;
737 +
738 +static int delayoffset;
739 +
740 +STATIC_INLINE void compute_delay_offset (int hpos)
741 +{
742 + /* this fixes most horizontal scrolling jerkyness but can't be correct */
743 + delayoffset = ((hpos - fm_maxplane - 0x18) & fetchstart_mask) << 1;
744 + delayoffset &= ~7;
745 + if (delayoffset & 8)
746 + delayoffset = 8;
747 + else if (delayoffset & 16)
748 + delayoffset = 16;
749 + else if (delayoffset & 32)
750 + delayoffset = 32;
751 + else
752 + delayoffset = 0;
753 +}
754 +
755 +static void expand_fmodes (void)
756 +{
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;
766 +}
767 +
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 };
771 +
772 +/* Expand bplcon0/bplcon1 into the toscr_xxx variables. */
773 +static void compute_toscr_delay_1 (void)
774 +{
775 + int delay1 = (bplcon1 & 0x0f) | ((bplcon1 & 0x0c00) >> 6);
776 + int delay2 = ((bplcon1 >> 4) & 0x0f) | (((bplcon1 >> 4) & 0x0c00) >> 6);
777 + int delaymask;
778 + int fetchwidth = 16 << fetchmode;
779 +
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;
785 +}
786 +
787 +static void compute_toscr_delay (int hpos)
788 +{
789 + int v = bplcon0;
790 + int *planes;
791 +
792 + if (currprefs.chipset_mask & CSMASK_AGA)
793 + planes = maxplanes_aga;
794 + else if (! (currprefs.chipset_mask & CSMASK_ECS_DENISE))
795 + planes = maxplanes_ocs;
796 + else
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)])
801 + v &= ~0x7010;
802 + toscr_res = GET_RES (v);
803 +
804 + toscr_nr_planes = GET_PLANES (v);
805 +
806 + compute_toscr_delay_1 ();
807 +}
808 +
809 +STATIC_INLINE void maybe_first_bpl1dat (int hpos)
810 +{
811 + if (thisline_decision.plfleft == -1) {
812 + thisline_decision.plfleft = hpos;
813 + compute_delay_offset (hpos);
814 + compute_toscr_delay_1 ();
815 + }
816 +}
817 +
818 +STATIC_INLINE void fetch (int nr, int fm)
819 +{
820 + uaecptr p;
821 + if (nr >= toscr_nr_planes)
822 + return;
823 + p = bplpt[nr] + bpl_off[nr];
824 + switch (fm) {
825 + case 0:
826 + fetched[nr] = chipmem_wget (p);
827 + bplpt[nr] += 2;
828 + break;
829 + case 1:
830 + fetched_aga0[nr] = chipmem_lget (p);
831 + bplpt[nr] += 4;
832 + break;
833 + case 2:
834 + fetched_aga1[nr] = chipmem_lget (p);
835 + fetched_aga0[nr] = chipmem_lget (p + 4);
836 + bplpt[nr] += 8;
837 + break;
838 + }
839 + if (nr == 0)
840 + fetch_state = fetch_was_plane0;
841 +}
842 +
843 +static void clear_fetchbuffer (uae_u32 *ptr, int nwords)
844 +{
845 + int i;
846 +
847 + if (! thisline_changed)
848 + for (i = 0; i < nwords; i++)
849 + if (ptr[i]) {
850 + thisline_changed = 1;
851 + break;
852 + }
853 +
854 + memset (ptr, 0, nwords * 4);
855 +}
856 +
857 +static void update_toscr_planes (void)
858 +{
859 + if (toscr_nr_planes > thisline_decision.nr_planes) {
860 + int j;
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);
863 +#if 0
864 + if (thisline_decision.nr_planes > 0)
865 + printf ("Planes from %d to %d\n", thisline_decision.nr_planes, toscr_nr_planes);
866 +#endif
867 + thisline_decision.nr_planes = toscr_nr_planes;
868 + }
869 +}
870 +
871 +STATIC_INLINE void toscr_3_ecs (int nbits)
872 +{
873 + int delay1 = toscr_delay1;
874 + int delay2 = toscr_delay2;
875 + int i;
876 + uae_u32 mask = 0xFFFF >> (16 - nbits);
877 +
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;
882 + }
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;
887 + }
888 +}
889 +
890 +STATIC_INLINE void shift32plus (uae_u32 *p, int n)
891 +{
892 + uae_u32 t = p[1];
893 + t <<= n;
894 + t |= p[0] >> (32 - n);
895 + p[1] = t;
896 +}
897 +
898 +STATIC_INLINE void aga_shift (uae_u32 *p, int n, int fm)
899 +{
900 + if (fm == 2) {
901 + shift32plus (p + 2, n);
902 + shift32plus (p + 1, n);
903 + }
904 + shift32plus (p + 0, n);
905 + p[0] <<= n;
906 +}
907 +
908 +STATIC_INLINE void toscr_3_aga (int nbits, int fm)
909 +{
910 + int delay1 = toscr_delay1;
911 + int delay2 = toscr_delay2;
912 + int i;
913 + uae_u32 mask = 0xFFFF >> (16 - nbits);
914 +
915 + {
916 + int offs = (16 << fm) - nbits + delay1;
917 + int off1 = offs >> 5;
918 + if (off1 == 3)
919 + off1 = 2;
920 + offs -= off1 * 32;
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);
928 + }
929 + }
930 + {
931 + int offs = (16 << fm) - nbits + delay2;
932 + int off1 = offs >> 5;
933 + if (off1 == 3)
934 + off1 = 2;
935 + offs -= off1 * 32;
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);
943 + }
944 + }
945 +}
946 +
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); }
950 +
951 +STATIC_INLINE void toscr_1 (int nbits, int fm)
952 +{
953 + switch (fm) {
954 + case 0:
955 + toscr_2_0 (nbits);
956 + break;
957 + case 1:
958 + toscr_2_1 (nbits);
959 + break;
960 + case 2:
961 + toscr_2_2 (nbits);
962 + break;
963 + }
964 +
965 + out_nbits += nbits;
966 + if (out_nbits == 32) {
967 + int i;
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;
978 + }
979 + out_offs++;
980 + out_nbits = 0;
981 + }
982 +}
983 +
984 +static void toscr_fm0 (int);
985 +static void toscr_fm1 (int);
986 +static void toscr_fm2 (int);
987 +
988 +STATIC_INLINE void toscr (int nbits, int fm)
989 +{
990 + switch (fm) {
991 + case 0: toscr_fm0 (nbits); break;
992 + case 1: toscr_fm1 (nbits); break;
993 + case 2: toscr_fm2 (nbits); break;
994 + }
995 +}
996 +
997 +STATIC_INLINE void toscr_0 (int nbits, int fm)
998 +{
999 + int t;
1000 +
1001 + if (nbits > 16) {
1002 + toscr (16, fm);
1003 + nbits -= 16;
1004 + }
1005 +
1006 + t = 32 - out_nbits;
1007 + if (t < nbits) {
1008 + toscr_1 (t, fm);
1009 + nbits -= t;
1010 + }
1011 + toscr_1 (nbits, fm);
1012 +}
1013 +
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); }
1017 +
1018 +static int flush_plane_data (int fm)
1019 +{
1020 + int i = 0;
1021 + int fetchwidth = 16 << fm;
1022 +
1023 + if (out_nbits <= 16) {
1024 + i += 16;
1025 + toscr_1 (16, fm);
1026 + }
1027 + if (out_nbits != 0) {
1028 + i += 32 - out_nbits;
1029 + toscr_1 (32 - out_nbits, fm);
1030 + }
1031 + i += 32;
1032 +
1033 + toscr_1 (16, fm);
1034 + toscr_1 (16, fm);
1035 + return i >> (1 + toscr_res);
1036 +}
1037 +
1038 +STATIC_INLINE void flush_display (int fm)
1039 +{
1040 + if (toscr_nbits > 0 && thisline_decision.plfleft != -1)
1041 + toscr (toscr_nbits, fm);
1042 + toscr_nbits = 0;
1043 +}
1044 +
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)
1049 +{
1050 + int i;
1051 +
1052 + flush_display (fm);
1053 +
1054 + if (fm == 0)
1055 + for (i = 0; i < MAX_PLANES; i++)
1056 + todisplay[i][0] |= fetched[i];
1057 + else
1058 + for (i = 0; i < MAX_PLANES; i++) {
1059 + if (fm == 2)
1060 + todisplay[i][1] = fetched_aga1[i];
1061 + todisplay[i][0] = fetched_aga0[i];
1062 + }
1063 +
1064 + maybe_first_bpl1dat (pos);
1065 +}
1066 +
1067 +#define SPEEDUP
1068 +
1069 +#ifdef SPEEDUP
1070 +
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)
1073 +{
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);
1081 +
1082 + if (dma)
1083 + bplpt[plane] += nwords * 2;
1084 +
1085 + if (real_pt == 0)
1086 + /* @@@ Don't do this, fall back on chipmem_wget instead. */
1087 + return;
1088 +
1089 + while (nwords > 0) {
1090 + int bits_left = 32 - tmp_nbits;
1091 + uae_u32 t;
1092 +
1093 + shiftbuffer |= fetchval;
1094 +
1095 + t = (shiftbuffer >> delay) & 0xFFFF;
1096 +
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;
1102 +
1103 + outval = t;
1104 + tmp_nbits = 16 - bits_left;
1105 + shiftbuffer <<= 16;
1106 + } else {
1107 + outval = (outval << 16) | t;
1108 + shiftbuffer <<= 16;
1109 + tmp_nbits += 16;
1110 + if (tmp_nbits == 32) {
1111 + thisline_changed |= *dataptr ^ outval;
1112 + *dataptr++ = outval;
1113 + tmp_nbits = 0;
1114 + }
1115 + }
1116 + nwords--;
1117 + if (dma) {
1118 + fetchval = do_get_mem_word (real_pt);
1119 + real_pt++;
1120 + }
1121 + }
1122 + fetched[plane] = fetchval;
1123 + todisplay[plane][0] = shiftbuffer;
1124 + outword[plane] = outval;
1125 +}
1126 +
1127 +STATIC_INLINE void long_fetch_aga (int plane, int nwords, int weird_number_of_bits, int fm, int dma)
1128 +{
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;
1139 + if (off1 == 3)
1140 + off1 = 2;
1141 + offs -= off1 * 32;
1142 +
1143 + if (dma)
1144 + bplpt[plane] += nwords * 2;
1145 +
1146 + if (real_pt == 0)
1147 + /* @@@ Don't do this, fall back on chipmem_wget instead. */
1148 + return;
1149 +
1150 + while (nwords > 0) {
1151 + int i;
1152 +
1153 + shiftbuffer[0] = fetchval0;
1154 + if (fm == 2)
1155 + shiftbuffer[1] = fetchval1;
1156 +
1157 + for (i = 0; i < (1 << fm); i++) {
1158 + int bits_left = 32 - tmp_nbits;
1159 +
1160 + uae_u32 t0 = shiftbuffer[off1];
1161 + uae_u32 t1 = shiftbuffer[off1 + 1];
1162 + uae_u64 t = (((uae_u64)t1) << 32) | t0;
1163 +
1164 + t0 = (t >> offs) & 0xFFFF;
1165 +
1166 + if (weird_number_of_bits && bits_left < 16) {
1167 + outval <<= bits_left;
1168 + outval |= t0 >> (16 - bits_left);
1169 +
1170 + thisline_changed |= *dataptr ^ outval;
1171 + *dataptr++ = outval;
1172 +
1173 + outval = t0;
1174 + tmp_nbits = 16 - bits_left;
1175 + aga_shift (shiftbuffer, 16, fm);
1176 + } else {
1177 + outval = (outval << 16) | t0;
1178 + aga_shift (shiftbuffer, 16, fm);
1179 + tmp_nbits += 16;
1180 + if (tmp_nbits == 32) {
1181 + thisline_changed |= *dataptr ^ outval;
1182 + *dataptr++ = outval;
1183 + tmp_nbits = 0;
1184 + }
1185 + }
1186 + }
1187 +
1188 + nwords -= 1 << fm;
1189 +
1190 + if (dma) {
1191 + if (fm == 1)
1192 + fetchval0 = do_get_mem_long (real_pt);
1193 + else {
1194 + fetchval1 = do_get_mem_long (real_pt);
1195 + fetchval0 = do_get_mem_long (real_pt + 1);
1196 + }
1197 + real_pt += fm;
1198 + }
1199 + }
1200 + fetched_aga0[plane] = fetchval0;
1201 + fetched_aga1[plane] = fetchval1;
1202 + outword[plane] = outval;
1203 +}
1204 +
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); }
1211 +
1212 +static void do_long_fetch (int hpos, int nwords, int dma, int fm)
1213 +{
1214 + int added;
1215 + int i;
1216 +
1217 + flush_display (fm);
1218 + switch (fm) {
1219 + case 0:
1220 + if (out_nbits & 15) {
1221 + for (i = 0; i < toscr_nr_planes; i++)
1222 + long_fetch_ecs_1 (i, nwords, dma);
1223 + } else {
1224 + for (i = 0; i < toscr_nr_planes; i++)
1225 + long_fetch_ecs_0 (i, nwords, dma);
1226 + }
1227 + break;
1228 + case 1:
1229 + if (out_nbits & 15) {
1230 + for (i = 0; i < toscr_nr_planes; i++)
1231 + long_fetch_aga_1_1 (i, nwords, dma);
1232 + } else {
1233 + for (i = 0; i < toscr_nr_planes; i++)
1234 + long_fetch_aga_1_0 (i, nwords, dma);
1235 + }
1236 + break;
1237 + case 2:
1238 + if (out_nbits & 15) {
1239 + for (i = 0; i < toscr_nr_planes; i++)
1240 + long_fetch_aga_2_1 (i, nwords, dma);
1241 + } else {
1242 + for (i = 0; i < toscr_nr_planes; i++)
1243 + long_fetch_aga_2_0 (i, nwords, dma);
1244 + }
1245 + break;
1246 + }
1247 +
1248 + out_nbits += nwords * 16;
1249 + out_offs += out_nbits >> 5;
1250 + out_nbits &= 31;
1251 +
1252 + if (dma && toscr_nr_planes > 0)
1253 + fetch_state = fetch_was_plane0;
1254 +}
1255 +
1256 +#endif
1257 +
1258 +/* make sure fetch that goes beyond maxhpos is finished */
1259 +static void finish_final_fetch (int i, int fm)
1260 +{
1261 + passed_plfstop = 3;
1262 +
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 ();
1269 + }
1270 +}
1271 +
1272 +STATIC_INLINE int one_fetch_cycle_0 (int i, int ddfstop_to_test, int dma, int fm)
1273 +{
1274 + if (! passed_plfstop && i == ddfstop_to_test)
1275 + passed_plfstop = 1;
1276 +
1277 + if ((fetch_cycle & fetchunit_mask) == 0) {
1278 + if (passed_plfstop == 2) {
1279 + finish_final_fetch (i, fm);
1280 + return 1;
1281 + }
1282 + if (passed_plfstop)
1283 + passed_plfstop++;
1284 + }
1285 + if (dma) {
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) {
1291 + case 8:
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;
1301 + }
1302 + break;
1303 + case 4:
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;
1309 + }
1310 + break;
1311 + case 2:
1312 + switch (cycle_start) {
1313 + case 0: fetch (1, fm); break;
1314 + case 1: fetch (0, fm); break;
1315 + }
1316 + break;
1317 + }
1318 + }
1319 + fetch_cycle++;
1320 + toscr_nbits += 2 << toscr_res;
1321 +
1322 + if (toscr_nbits == 16)
1323 + flush_display (fm);
1324 + if (toscr_nbits > 16)
1325 + abort ();
1326 +
1327 + return 0;
1328 +}
1329 +
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); }
1333 +
1334 +STATIC_INLINE int one_fetch_cycle (int i, int ddfstop_to_test, int dma, int fm)
1335 +{
1336 + switch (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 ();
1341 + }
1342 +}
1343 +
1344 +STATIC_INLINE void update_fetch (int until, int fm)
1345 +{
1346 + int pos;
1347 + int dma = dmaen (DMA_BITPLANE);
1348 +
1349 + int ddfstop_to_test;
1350 +
1351 + if (framecnt != 0 || passed_plfstop == 3)
1352 + return;
1353 +
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
1356 + reach it. */
1357 + ddfstop_to_test = HARD_DDF_STOP;
1358 + if (ddfstop >= last_fetch_hpos && ddfstop < HARD_DDF_STOP)
1359 + ddfstop_to_test = ddfstop;
1360 +
1361 + compute_toscr_delay (last_fetch_hpos);
1362 + update_toscr_planes ();
1363 +
1364 + pos = last_fetch_hpos;
1365 + cycle_diagram_shift = (last_fetch_hpos - fetch_cycle) & fetchstart_mask;
1366 +
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. */
1370 + for (; ; pos++) {
1371 + if (pos == until) {
1372 + if (until >= maxhpos && passed_plfstop == 2) {
1373 + finish_final_fetch (pos, fm);
1374 + return;
1375 + }
1376 + flush_display (fm);
1377 + return;
1378 + }
1379 +
1380 + if (fetch_state == fetch_was_plane0)
1381 + break;
1382 +
1383 + fetch_state = fetch_started;
1384 + if (one_fetch_cycle (pos, ddfstop_to_test, dma, fm))
1385 + return;
1386 + }
1387 +
1388 +#ifdef SPEEDUP
1389 + /* Unrolled version of the for loop below. */
1390 + if (! passed_plfstop
1391 + && dma
1392 + && (fetch_cycle & fetchstart_mask) == (fm_maxplane & fetchstart_mask)
1393 +# if 0
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
1398 +# endif
1399 + && toscr_nr_planes == thisline_decision.nr_planes)
1400 + {
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;
1405 + int count;
1406 +
1407 + count = stop - pos;
1408 +
1409 + if (count >= fetchstart) {
1410 + count &= ~fetchstart_mask;
1411 +
1412 + if (thisline_decision.plfleft == -1) {
1413 + compute_delay_offset (pos);
1414 + compute_toscr_delay_1 ();
1415 + }
1416 + do_long_fetch (pos, count >> (3 - toscr_res), dma, fm);
1417 +
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);
1422 +
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;
1427 + pos += count;
1428 + fetch_cycle += count;
1429 + }
1430 + }
1431 +#endif
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;
1436 +
1437 + if (one_fetch_cycle (pos, ddfstop_to_test, dma, fm))
1438 + return;
1439 + }
1440 + if (until >= maxhpos && passed_plfstop == 2) {
1441 + finish_final_fetch (pos, fm);
1442 + return;
1443 + }
1444 + flush_display (fm);
1445 +}
1446 +
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); }
1450 +
1451 +STATIC_INLINE void decide_fetch (int hpos)
1452 +{
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 ();
1459 + }
1460 + }
1461 + last_fetch_hpos = hpos;
1462 +}
1463 +
1464 +/* This function is responsible for turning on datafetch if necessary. */
1465 +STATIC_INLINE void decide_line (int hpos)
1466 +{
1467 + if (hpos <= last_decide_line_hpos)
1468 + return;
1469 + if (fetch_state != fetch_not_started)
1470 + return;
1471 +
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;
1478 + }
1479 + if (diwstate == DIW_waiting_stop && vpos == plflastline) {
1480 + diwstate = DIW_waiting_start;
1481 + }
1482 +
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)
1487 + {
1488 + fetch_state = fetch_started;
1489 + fetch_cycle = 0;
1490 + last_fetch_hpos = plfstrt;
1491 + out_nbits = 0;
1492 + out_offs = 0;
1493 + toscr_nbits = 0;
1494 +
1495 + compute_toscr_delay (last_fetch_hpos);
1496 +
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;
1503 + out_nbits &= 31;
1504 + }
1505 + update_toscr_planes ();
1506 + }
1507 + estimate_last_fetch_cycle (plfstrt);
1508 + last_decide_line_hpos = hpos;
1509 + do_sprites (plfstrt);
1510 + return;
1511 + }
1512 + }
1513 +
1514 + if (last_decide_line_hpos < 0x34)
1515 + do_sprites (hpos);
1516 +
1517 + last_decide_line_hpos = hpos;
1518 +}
1519 +
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)
1523 +{
1524 + if (regno == -1 && value) {
1525 + thisline_decision.ham_seen = 1;
1526 + if (hpos < 0x18)
1527 + thisline_decision.ham_at_start = 1;
1528 + }
1529 +
1530 + /* Early positions don't appear on-screen. */
1531 + if (framecnt != 0 || vpos < minfirstline || hpos < 0x18
1532 + /*|| currprefs.emul_accuracy == 0*/)
1533 + return;
1534 +
1535 + decide_diw (hpos);
1536 + decide_line (hpos);
1537 +
1538 + if (thisline_decision.ctable == -1)
1539 + remember_ctable ();
1540 +
1541 +#ifdef OS_WITHOUT_MEMORY_MANAGEMENT
1542 + if (next_color_change >= max_color_change) {
1543 + ++delta_color_change;
1544 + return;
1545 + }
1546 +#endif
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;
1550 +}
1551 +
1552 +typedef int sprbuf_res_t, cclockres_t, hwres_t, bplres_t;
1553 +
1554 +static void do_playfield_collisions (void)
1555 +{
1556 + uae_u8 *ld = line_data[next_lineno];
1557 + int i;
1558 +
1559 + if (clxcon_bpl_enable == 0) {
1560 + clxdat |= 1;
1561 + return;
1562 + }
1563 +
1564 + for (i = thisline_decision.plfleft; i < thisline_decision.plfright; i += 2) {
1565 + int j;
1566 + uae_u32 total = 0xFFFFFFFF;
1567 + for (j = 0; j < 8; j++) {
1568 + uae_u32 t = 0;
1569 + if ((clxcon_bpl_enable & (1 << j)) == 0)
1570 + t = 0xFFFFFFFF;
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);
1574 + }
1575 + total &= t;
1576 + }
1577 + if (total)
1578 + clxdat |= 1;
1579 + }
1580 +}
1581 +
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)
1587 +{
1588 + int nr_sprites = curr_drawinfo[next_lineno].nr_sprites;
1589 + int first = curr_drawinfo[next_lineno].first_sprite_entry;
1590 + int i;
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);
1596 +
1597 + if (clxcon_bpl_enable == 0) {
1598 + clxdat |= 0x1FE;
1599 + return;
1600 + }
1601 +
1602 + for (i = 0; i < nr_sprites; i++) {
1603 + struct sprite_entry *e = curr_sprite_entries + first + i;
1604 + sprbuf_res_t j;
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;
1609 +
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;
1618 +
1619 + for (j = minpos; j < maxpos; j++) {
1620 + int sprpix = spixels[e->first_pixel + j - e->pos] & collision_mask;
1621 + int k;
1622 + int offs;
1623 +
1624 + if (sprpix == 0)
1625 + continue;
1626 +
1627 + offs = ((j << bplres) >> sprite_buffer_res) - ddf_left;
1628 + sprpix = sprite_ab_merge[sprpix & 255] | (sprite_ab_merge[sprpix >> 8] << 2);
1629 + sprpix <<= 1;
1630 +
1631 + /* Loop over number of playfields. */
1632 + for (k = 0; k < 2; k++) {
1633 + int l;
1634 + int match = 1;
1635 + int planes = ((currprefs.chipset_mask & CSMASK_AGA) ? 8 : 6);
1636 +
1637 + for (l = k; match && l < planes; l += 2) {
1638 + if (clxcon_bpl_enable & (1 << l)) {
1639 + int t = 0;
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;
1644 + }
1645 + if (t != ((clxcon_bpl_match >> l) & 1))
1646 + match = 0;
1647 + }
1648 + }
1649 + if (match)
1650 + clxdat |= sprpix;
1651 + sprpix <<= 4;
1652 + }
1653 + }
1654 + }
1655 +}
1656 +
1657 +static void expand_sprres (void)
1658 +{
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;
1663 + else
1664 + sprres = RES_LORES;
1665 + break;
1666 + case 1:
1667 + sprres = RES_LORES;
1668 + break;
1669 + case 2:
1670 + sprres = RES_HIRES;
1671 + break;
1672 + case 3:
1673 + sprres = RES_SUPERHIRES;
1674 + break;
1675 + }
1676 +}
1677 +
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)
1680 +{
1681 + int j = 0;
1682 + while (datab) {
1683 + unsigned int tmp = *buf;
1684 + unsigned int col = (datab & 3) << (2 * num);
1685 + tmp |= col;
1686 + if ((j & mask) == 0)
1687 + *buf++ = tmp;
1688 + if (dbl)
1689 + *buf++ = tmp;
1690 + j++;
1691 + datab >>= 2;
1692 + if (do_collisions) {
1693 + tmp &= collision_mask;
1694 + if (tmp) {
1695 + unsigned int shrunk_tmp = sprite_ab_merge[tmp & 255] | (sprite_ab_merge[tmp >> 8] << 2);
1696 + clxdat |= sprclx[shrunk_tmp];
1697 + }
1698 + }
1699 + }
1700 +}
1701 +
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
1704 + etc.
1705 + This function assumes that for all sprites in a given line, SPRXP either
1706 + stays equal or increases between successive calls.
1707 +
1708 + The data is recorded either in lores pixels (if ECS), or in hires pixels
1709 + (if AGA). No support for SHRES sprites. */
1710 +
1711 +static void record_sprite (int line, int num, int sprxp, uae_u16 *data, uae_u16 *datb, unsigned int ctl)
1712 +{
1713 + struct sprite_entry *e = curr_sprite_entries + next_sprite_entry;
1714 + int i;
1715 + int word_offs;
1716 + uae_u16 *buf;
1717 + uae_u32 collision_mask;
1718 + int width = sprite_width;
1719 + int dbl = 0;
1720 + unsigned int mask = 0;
1721 +
1722 + if (sprres != RES_LORES)
1723 + thisline_decision.any_hires_sprites = 1;
1724 +
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;
1729 + }
1730 +
1731 + /* Try to coalesce entries if they aren't too far apart. */
1732 + if (! next_sprite_forced && e[-1].max + 16 >= sprxp) {
1733 + e--;
1734 + } else {
1735 + next_sprite_entry++;
1736 + e->pos = sprxp;
1737 + e->has_attached = 0;
1738 + }
1739 +
1740 + if (sprxp < e->pos)
1741 + abort ();
1742 +
1743 + e->max = sprxp + width;
1744 + e[1].first_pixel = e->first_pixel + ((e->max - e->pos + 3) & ~3);
1745 + next_sprite_forced = 0;
1746 +
1747 + collision_mask = clxmask[clxcon >> 12];
1748 + word_offs = e->first_pixel + sprxp - e->pos;
1749 +
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]);
1755 +
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);
1759 + else
1760 + record_sprite_1 (buf, datab, num, dbl, mask, 0, collision_mask);
1761 + data++;
1762 + datb++;
1763 + }
1764 +
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. */
1767 +
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) {
1773 + stb1[0] |= state;
1774 + stb1[1] |= state;
1775 + stb1[2] |= state;
1776 + stb1[3] |= state;
1777 + stb1[4] |= state;
1778 + stb1[5] |= state;
1779 + stb1[6] |= state;
1780 + stb1[7] |= state;
1781 + stb1 += 8;
1782 + }
1783 + e->has_attached = 1;
1784 + }
1785 +}
1786 +
1787 +static void decide_sprites (int hpos)
1788 +{
1789 + int nrs[MAX_SPRITES], posns[MAX_SPRITES];
1790 + int count, i;
1791 + int point = hpos * 2;
1792 + int width = sprite_width;
1793 + int window_width = (width << lores_shift) >> sprres;
1794 +
1795 + if (framecnt != 0 || hpos < 0x14 || nr_armed == 0 || point == last_sprite_point)
1796 + return;
1797 +
1798 + decide_diw (hpos);
1799 + decide_line (hpos);
1800 +
1801 +#if 0
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)
1804 + return;
1805 +#endif
1806 + count = 0;
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);
1811 + int j, bestp;
1812 +
1813 + if (! spr[i].armed || sprxp < 0 || hw_xp <= last_sprite_point || hw_xp > point)
1814 + continue;
1815 + if ((thisline_decision.diwfirstword >= 0 && window_xp + window_width < thisline_decision.diwfirstword)
1816 + || (thisline_decision.diwlastword >= 0 && window_xp > thisline_decision.diwlastword))
1817 + continue;
1818 +
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)
1822 + break;
1823 + if (posns[bestp] == sprxp && nrs[bestp] < i)
1824 + break;
1825 + }
1826 + for (j = count; j > bestp; j--) {
1827 + posns[j] = posns[j-1];
1828 + nrs[j] = nrs[j-1];
1829 + }
1830 + posns[j] = sprxp;
1831 + nrs[j] = i;
1832 + count++;
1833 + }
1834 + for (i = 0; i < count; i++) {
1835 + int nr = nrs[i];
1836 + record_sprite (next_lineno, nr, spr[nr].xpos, sprdata[nr], sprdatb[nr], sprctl[nr]);
1837 + }
1838 + last_sprite_point = point;
1839 +}
1840 +
1841 +STATIC_INLINE int sprites_differ (struct draw_info *dip, struct draw_info *dip_old)
1842 +{
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;
1846 + int npixels;
1847 + int i;
1848 +
1849 + if (dip->nr_sprites != dip_old->nr_sprites)
1850 + return 1;
1851 +
1852 + if (dip->nr_sprites == 0)
1853 + return 0;
1854 +
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)
1859 + return 1;
1860 +
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)
1864 + return 1;
1865 + if (memcmp (spixstate.bytes + this_first->first_pixel, spixstate.bytes + prev_first->first_pixel, npixels) != 0)
1866 + return 1;
1867 + return 0;
1868 +}
1869 +
1870 +STATIC_INLINE int color_changes_differ (struct draw_info *dip, struct draw_info *dip_old)
1871 +{
1872 + if (dip->nr_color_changes != dip_old->nr_color_changes)
1873 + return 1;
1874 +
1875 + if (dip->nr_color_changes == 0)
1876 + return 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)
1880 + return 1;
1881 + return 0;
1882 +}
1883 +
1884 +/* End of a horizontal scan line. Finish off all decisions that were not
1885 + * made yet. */
1886 +static void finish_decisions (void)
1887 +{
1888 + struct draw_info *dip;
1889 + struct draw_info *dip_old;
1890 + struct decision *dp;
1891 + int changed;
1892 + int hpos = current_hpos ();
1893 +
1894 + if (framecnt != 0)
1895 + return;
1896 +
1897 + decide_diw (hpos);
1898 + decide_line (hpos);
1899 + decide_fetch (hpos);
1900 +
1901 + if (thisline_decision.plfleft != -1 && thisline_decision.plflinelen == -1) {
1902 + if (fetch_state != fetch_not_started)
1903 + abort ();
1904 + thisline_decision.plfright = thisline_decision.plfleft;
1905 + thisline_decision.plflinelen = 0;
1906 + thisline_decision.bplres = RES_LORES;
1907 + }
1908 +
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;
1914 +
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;
1919 +
1920 + dip = curr_drawinfo + next_lineno;
1921 + dip_old = prev_drawinfo + next_lineno;
1922 + dp = line_decisions + next_lineno;
1923 + changed = thisline_changed;
1924 +
1925 + if (thisline_decision.plfleft != -1) {
1926 + record_diw_line (thisline_decision.diwfirstword, thisline_decision.diwlastword);
1927 +
1928 + decide_sprites (hpos);
1929 + }
1930 +
1931 + dip->last_sprite_entry = next_sprite_entry;
1932 + dip->last_color_change = next_color_change;
1933 +
1934 + if (thisline_decision.ctable == -1) {
1935 + if (thisline_decision.plfleft == -1)
1936 + remember_ctable_for_border ();
1937 + else
1938 + remember_ctable ();
1939 + }
1940 +
1941 + dip->nr_color_changes = next_color_change - dip->first_color_change;
1942 + dip->nr_sprites = next_sprite_entry - dip->first_sprite_entry;
1943 +
1944 + if (thisline_decision.plfleft != line_decisions[next_lineno].plfleft)
1945 + changed = 1;
1946 + if (! changed && color_changes_differ (dip, dip_old))
1947 + changed = 1;
1948 + if (!changed && thisline_decision.plfleft != -1 && sprites_differ (dip, dip_old))
1949 + changed = 1;
1950 +
1951 + if (changed) {
1952 + thisline_changed = 1;
1953 + *dp = thisline_decision;
1954 + } else
1955 + /* The only one that may differ: */
1956 + dp->ctable = thisline_decision.ctable;
1957 +}
1958 +
1959 +/* Set the state of all decisions to "undecided" for a new scanline. */
1960 +static void reset_decisions (void)
1961 +{
1962 + if (framecnt != 0)
1963 + return;
1964 +
1965 + thisline_decision.any_hires_sprites = 0;
1966 + thisline_decision.nr_planes = 0;
1967 +
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);
1972 +
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;
1980 + }
1981 + thisline_decision.ctable = -1;
1982 +
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;
1987 +
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;
1992 +
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);
1998 +
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;
2004 +}
2005 +
2006 +void compute_vsynctime (void)
2007 +{
2008 + vsynctime = syncbase / vblank_hz;
2009 + if (currprefs.produce_sound > 1) {
2010 + vsynctime = vsynctime * 9 / 10;
2011 + }
2012 +}
2013 +
2014 +/* set PAL or NTSC timing variables */
2015 +
2016 +static void init_hz (void)
2017 +{
2018 + int isntsc;
2019 +
2020 + beamcon0 = new_beamcon0;
2021 +
2022 + isntsc = beamcon0 & 0x20 ? 0 : 1;
2023 + if (!isntsc) {
2024 + maxvpos = MAXVPOS_PAL;
2025 + maxhpos = MAXHPOS_PAL;
2026 + minfirstline = MINFIRSTLINE_PAL;
2027 + vblank_endline = VBLANK_ENDLINE_PAL;
2028 + vblank_hz = VBLANK_HZ_PAL;
2029 + } else {
2030 + maxvpos = MAXVPOS_NTSC;
2031 + maxhpos = MAXHPOS_NTSC;
2032 + minfirstline = MINFIRSTLINE_NTSC;
2033 + vblank_endline = VBLANK_ENDLINE_NTSC;
2034 + vblank_hz = VBLANK_HZ_NTSC;
2035 + }
2036 + compute_vsynctime ();
2037 +
2038 + write_log ("Using %s timing\n", isntsc ? "NTSC" : "PAL");
2039 +}
2040 +
2041 +static void calcdiw (void)
2042 +{
2043 + int hstrt = diwstrt & 0xFF;
2044 + int hstop = diwstop & 0xFF;
2045 + int vstrt = diwstrt >> 8;
2046 + int vstop = diwstop >> 8;
2047 +
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;
2053 + } else {
2054 + hstop += 0x100;
2055 + if ((vstop & 0x80) == 0)
2056 + vstop |= 0x100;
2057 + }
2058 +
2059 + diwfirstword = coord_diw_to_window_x (hstrt);
2060 + diwlastword = coord_diw_to_window_x (hstop);
2061 + if (diwfirstword < 0)
2062 + diwfirstword = 0;
2063 +
2064 + plffirstline = vstrt;
2065 + plflastline = vstop;
2066 +
2067 +#if 0
2068 + /* This happens far too often. */
2069 + if (plffirstline < minfirstline) {
2070 + write_log ("Warning: Playfield begins before line %d!\n", minfirstline);
2071 + plffirstline = minfirstline;
2072 + }
2073 +#endif
2074 +
2075 +#if 0 /* Turrican does this */
2076 + if (plflastline > 313) {
2077 + write_log ("Warning: Playfield out of range!\n");
2078 + plflastline = 313;
2079 + }
2080 +#endif
2081 + plfstrt = ddfstrt;
2082 + plfstop = ddfstop;
2083 + if (plfstrt < 0x18)
2084 + plfstrt = 0x18;
2085 +}
2086 +
2087 +/* Mousehack stuff */
2088 +
2089 +#define defstepx (1<<16)
2090 +#define defstepy (1<<16)
2091 +#define defxoffs 0
2092 +#define defyoffs 0
2093 +
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;
2100 +
2101 +int lastmx, lastmy;
2102 +int newmousecounters;
2103 +int ievent_alive = 0;
2104 +
2105 +static enum { unknown_mouse, normal_mouse, dont_care_mouse, follow_mouse } mousestate;
2106 +
2107 +static void mousehack_setdontcare (void)
2108 +{
2109 + if (mousestate == dont_care_mouse)
2110 + return;
2111 +
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;
2116 +}
2117 +
2118 +static void mousehack_setfollow (void)
2119 +{
2120 + if (mousestate == follow_mouse)
2121 + return;
2122 +
2123 + write_log ("Follow sprite mode set\n");
2124 + mousestate = follow_mouse;
2125 + lastdiffx = lastdiffy = 0;
2126 + sprvbfl = 0;
2127 + spr0ctl = spr0pos = 0;
2128 + mstepx = defstepx; mstepy = defstepy;
2129 +}
2130 +
2131 +static uae_u32 mousehack_helper (void)
2132 +{
2133 + int mousexpos, mouseypos;
2134 +
2135 +#ifdef PICASSO96
2136 + if (picasso_on) {
2137 + picasso_clip_mouse (&lastmx, &lastmy);
2138 + mousexpos = lastmx;
2139 + mouseypos = lastmy;
2140 + } else
2141 +#endif
2142 + {
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;
2147 + if (lastmy < 0)
2148 + lastmy = 0;
2149 + if (lastmx < 0)
2150 + lastmx = 0;
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);
2155 + }
2156 +
2157 + switch (m68k_dreg (regs, 0)) {
2158 + case 0:
2159 + return ievent_alive ? -1 : needmousehack ();
2160 + case 1:
2161 + ievent_alive = 10;
2162 + return mousexpos;
2163 + case 2:
2164 + return mouseypos;
2165 + }
2166 + return 0;
2167 +}
2168 +
2169 +void togglemouse (void)
2170 +{
2171 + switch (mousestate) {
2172 + case dont_care_mouse: mousehack_setfollow (); break;
2173 + case follow_mouse: mousehack_setdontcare (); break;
2174 + default: break; /* Nnnnnghh! */
2175 + }
2176 +}
2177 +
2178 +STATIC_INLINE int adjust (int val)
2179 +{
2180 + if (val > 127)
2181 + return 127;
2182 + else if (val < -127)
2183 + return -127;
2184 + return val;
2185 +}
2186 +
2187 +static void do_mouse_hack (void)
2188 +{
2189 + int spr0x = ((spr0pos & 0xff) << 2) | ((spr0ctl & 1) << 1);
2190 + int spr0y = ((spr0pos >> 8) | ((spr0ctl & 4) << 6)) << 1;
2191 + int diffx, diffy;
2192 +
2193 + if (ievent_alive > 0) {
2194 + mouse_x = mouse_y = 0;
2195 + return;
2196 + }
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;
2204 + mouse_x += diffx;
2205 + if (diffy > 127) diffy = 127;
2206 + if (diffy < -127) diffy = -127;
2207 + mouse_y += diffy;
2208 + }
2209 + lastsampledmx += diffx; lastsampledmy += diffy;
2210 + break;
2211 +
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;
2217 + break;
2218 +
2219 + case follow_mouse:
2220 + if (sprvbfl && sprvbfl-- > 1) {
2221 + int mousexpos, mouseypos;
2222 +
2223 + if ((lastdiffx > docal || lastdiffx < -docal)
2224 + && lastspr0x != spr0x
2225 + && spr0x > plfstrt*4 + 34 + xcaloff
2226 + && spr0x < plfstop*4 - xcaloff)
2227 + {
2228 + int val = (lastdiffx << 16) / (spr0x - lastspr0x);
2229 + if (val >= 0x8000)
2230 + mstepx = (mstepx * (calweight - 1) + val) / calweight;
2231 + }
2232 + if ((lastdiffy > docal || lastdiffy < -docal)
2233 + && lastspr0y != spr0y
2234 + && spr0y > plffirstline + ycaloff
2235 + && spr0y < plflastline - ycaloff)
2236 + {
2237 + int val = (lastdiffy << 16) / (spr0y - lastspr0y);
2238 + if (val >= 0x8000)
2239 + mstepy = (mstepy * (calweight - 1) + val) / calweight;
2240 + }
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;
2250 + }
2251 + break;
2252 +
2253 + default:
2254 + abort ();
2255 + }
2256 +}
2257 +
2258 +static void mousehack_handle (unsigned int ctl, unsigned int pos)
2259 +{
2260 + if (!sprvbfl && ((pos & 0xff) << 2) > 2 * DISPLAY_LEFT_SHIFT) {
2261 + spr0ctl = ctl;
2262 + spr0pos = pos;
2263 + sprvbfl = 2;
2264 + }
2265 +}
2266 +
2267 +static int timehack_alive = 0;
2268 +
2269 +static uae_u32 timehack_helper (void)
2270 +{
2271 +#ifdef HAVE_GETTIMEOFDAY
2272 + struct timeval tv;
2273 + if (m68k_dreg (regs, 0) == 0)
2274 + return timehack_alive;
2275 +
2276 + timehack_alive = 10;
2277 +
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);
2281 + return 0;
2282 +#else
2283 + return 2;
2284 +#endif
2285 +}
2286 +
2287 + /*
2288 + * register functions
2289 + */
2290 +STATIC_INLINE uae_u16 DENISEID (void)
2291 +{
2292 + if (currprefs.chipset_mask & CSMASK_AGA)
2293 + return 0xF8;
2294 + if (currprefs.chipset_mask & CSMASK_ECS_DENISE)
2295 + return 0xFC;
2296 + return 0xFFFF;
2297 +}
2298 +STATIC_INLINE uae_u16 DMACONR (void)
2299 +{
2300 + return (dmacon | (bltstate==BLT_done ? 0 : 0x4000)
2301 + | (blt_info.blitzero ? 0x2000 : 0));
2302 +}
2303 +STATIC_INLINE uae_u16 INTENAR (void)
2304 +{
2305 + return intena;
2306 +}
2307 +uae_u16 INTREQR (void)
2308 +{
2309 + return intreq /* | (currprefs.use_serial ? 0x0001 : 0) */;
2310 +}
2311 +STATIC_INLINE uae_u16 ADKCONR (void)
2312 +{
2313 + return adkcon;
2314 +}
2315 +STATIC_INLINE uae_u16 VPOSR (void)
2316 +{
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;
2321 +}
2322 +static void VPOSW (uae_u16 v)
2323 +{
2324 + if (lof != (v & 0x8000))
2325 + lof_changed = 1;
2326 + lof = v & 0x8000;
2327 + /*
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...
2330 + */
2331 +}
2332 +
2333 +STATIC_INLINE uae_u16 VHPOSR (void)
2334 +{
2335 + return (vpos << 8) | current_hpos ();
2336 +}
2337 +
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); }
2342 +
2343 +static void start_copper (void)
2344 +{
2345 + int was_active = eventtab[ev_copper].active;
2346 + eventtab[ev_copper].active = 0;
2347 + if (was_active)
2348 + events_schedule ();
2349 +
2350 + cop_state.ignore_next = 0;
2351 + cop_state.state = COP_read1;
2352 + cop_state.vpos = vpos;
2353 + cop_state.hpos = current_hpos () & ~1;
2354 +
2355 + if (dmaen (DMA_COPPER)) {
2356 + copper_enabled_thisline = 1;
2357 + set_special (SPCFLAG_COPPER);
2358 + }
2359 +}
2360 +
2361 +static void COPJMP1 (uae_u16 a)
2362 +{
2363 + cop_state.ip = cop1lc;
2364 + start_copper ();
2365 +}
2366 +
2367 +static void COPJMP2 (uae_u16 a)
2368 +{
2369 + cop_state.ip = cop2lc;
2370 + start_copper ();
2371 +}
2372 +
2373 +STATIC_INLINE void COPCON (uae_u16 a)
2374 +{
2375 + copcon = a;
2376 +}
2377 +
2378 +static void DMACON (int hpos, uae_u16 v)
2379 +{
2380 + int i;
2381 +
2382 + uae_u16 oldcon = dmacon;
2383 +
2384 + decide_line (hpos);
2385 + decide_fetch (hpos);
2386 +
2387 + setclr (&dmacon, v);
2388 + dmacon &= 0x1FFF;
2389 +
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;
2394 + }
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);
2403 + }
2404 + if (! (dmacon & DMA_COPPER)) {
2405 + copper_enabled_thisline = 0;
2406 + unset_special (SPCFLAG_COPPER);
2407 + cop_state.state = COP_stop;
2408 + }
2409 +
2410 + if ((dmacon & DMA_BLITPRI) > (oldcon & DMA_BLITPRI) && bltstate != BLT_done) {
2411 + static int count = 0;
2412 + if (!count) {
2413 + count = 1;
2414 + write_log ("warning: program is doing blitpri hacks.\n");
2415 + }
2416 + set_special (SPCFLAG_BLTNASTY);
2417 + }
2418 + if ((dmacon & (DMA_BLITPRI | DMA_BLITTER | DMA_MASTER)) != (DMA_BLITPRI | DMA_BLITTER | DMA_MASTER))
2419 + unset_special (SPCFLAG_BLTNASTY);
2420 +
2421 + if (currprefs.produce_sound > 0) {
2422 + update_audio ();
2423 +
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)
2428 + continue;
2429 + cdp->dmaen = chan_ena;
2430 + if (cdp->dmaen)
2431 + audio_channel_enable_dma (cdp);
2432 + else
2433 + audio_channel_disable_dma (cdp);
2434 + }
2435 + schedule_audio ();
2436 + }
2437 + events_schedule();
2438 +}
2439 +
2440 +/*static int trace_intena = 0;*/
2441 +
2442 +STATIC_INLINE void INTENA (uae_u16 v)
2443 +{
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
2452 +
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
2456 + installed. */
2457 + if (v & 0x8000)
2458 + set_special (SPCFLAG_INT);
2459 +}
2460 +
2461 +void INTREQ_0 (uae_u16 v)
2462 +{
2463 + setclr (&intreq,v);
2464 + set_special (SPCFLAG_INT);
2465 +}
2466 +
2467 +void INTREQ (uae_u16 v)
2468 +{
2469 + INTREQ_0 (v);
2470 + if ((v & 0x8800) == 0x0800)
2471 + serdat &= 0xbfff;
2472 + rethink_cias ();
2473 +}
2474 +
2475 +static void update_adkmasks (void)
2476 +{
2477 + unsigned long t;
2478 +
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);
2484 +}
2485 +
2486 +static void ADKCON (uae_u16 v)
2487 +{
2488 + if (currprefs.produce_sound > 0)
2489 + update_audio ();
2490 +
2491 + setclr (&adkcon,v);
2492 + update_adkmasks ();
2493 +}
2494 +
2495 +static void BEAMCON0 (uae_u16 v)
2496 +{
2497 + if (currprefs.chipset_mask & CSMASK_ECS_AGNUS)
2498 + new_beamcon0 = v & 0x20;
2499 +}
2500 +
2501 +static void BPLPTH (int hpos, uae_u16 v, int num)
2502 +{
2503 + decide_line (hpos);
2504 + decide_fetch (hpos);
2505 + bplpt[num] = (bplpt[num] & 0xffff) | ((uae_u32)v << 16);
2506 +}
2507 +static void BPLPTL (int hpos, uae_u16 v, int num)
2508 +{
2509 + decide_line (hpos);
2510 + decide_fetch (hpos);
2511 + bplpt[num] = (bplpt[num] & ~0xffff) | (v & 0xfffe);
2512 +}
2513 +
2514 +static void BPLCON0 (int hpos, uae_u16 v)
2515 +{
2516 + if (! (currprefs.chipset_mask & CSMASK_ECS_DENISE))
2517 + v &= ~0x00F1;
2518 + else if (! (currprefs.chipset_mask & CSMASK_AGA))
2519 + v &= ~0x00B1;
2520 +
2521 + if (bplcon0 == v)
2522 + return;
2523 + decide_line (hpos);
2524 + decide_fetch (hpos);
2525 +
2526 + /* HAM change? */
2527 + if ((bplcon0 ^ v) & 0x800) {
2528 + record_color_change (hpos, -1, !! (v & 0x800));
2529 + }
2530 +
2531 + bplcon0 = v;
2532 + curr_diagram = cycle_diagram_table[fetchmode][GET_RES(bplcon0)][GET_PLANES (v)];
2533 +
2534 + if (currprefs.chipset_mask & CSMASK_AGA) {
2535 + decide_sprites (hpos);
2536 + expand_sprres ();
2537 + }
2538 +
2539 + expand_fmodes ();
2540 +}
2541 +
2542 +STATIC_INLINE void BPLCON1 (int hpos, uae_u16 v)
2543 +{
2544 + if (bplcon1 == v)
2545 + return;
2546 + decide_line (hpos);
2547 + decide_fetch (hpos);
2548 + bplcon1 = v;
2549 +}
2550 +
2551 +STATIC_INLINE void BPLCON2 (int hpos, uae_u16 v)
2552 +{
2553 + if (bplcon2 == v)
2554 + return;
2555 + decide_line (hpos);
2556 + bplcon2 = v;
2557 +}
2558 +
2559 +STATIC_INLINE void BPLCON3 (int hpos, uae_u16 v)
2560 +{
2561 + if (! (currprefs.chipset_mask & CSMASK_AGA))
2562 + return;
2563 + if (bplcon3 == v)
2564 + return;
2565 + decide_line (hpos);
2566 + decide_sprites (hpos);
2567 + bplcon3 = v;
2568 + expand_sprres ();
2569 +}
2570 +
2571 +STATIC_INLINE void BPLCON4 (int hpos, uae_u16 v)
2572 +{
2573 + if (! (currprefs.chipset_mask & CSMASK_AGA))
2574 + return;
2575 + if (bplcon4 == v)
2576 + return;
2577 + decide_line (hpos);
2578 + bplcon4 = v;
2579 +}
2580 +
2581 +static void BPL1MOD (int hpos, uae_u16 v)
2582 +{
2583 + v &= ~1;
2584 + if ((uae_s16)bpl1mod == (uae_s16)v)
2585 + return;
2586 + decide_line (hpos);
2587 + decide_fetch (hpos);
2588 + bpl1mod = v;
2589 +}
2590 +
2591 +static void BPL2MOD (int hpos, uae_u16 v)
2592 +{
2593 + v &= ~1;
2594 + if ((uae_s16)bpl2mod == (uae_s16)v)
2595 + return;
2596 + decide_line (hpos);
2597 + decide_fetch (hpos);
2598 + bpl2mod = v;
2599 +}
2600 +
2601 +STATIC_INLINE void BPL1DAT (int hpos, uae_u16 v)
2602 +{
2603 + decide_line (hpos);
2604 + bpl1dat = v;
2605 +
2606 + maybe_first_bpl1dat (hpos);
2607 +}
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; }
2616 +
2617 +static void DIWSTRT (int hpos, uae_u16 v)
2618 +{
2619 + if (diwstrt == v && ! diwhigh_written)
2620 + return;
2621 + decide_line (hpos);
2622 + diwhigh_written = 0;
2623 + diwstrt = v;
2624 + calcdiw ();
2625 +}
2626 +
2627 +static void DIWSTOP (int hpos, uae_u16 v)
2628 +{
2629 + if (diwstop == v && ! diwhigh_written)
2630 + return;
2631 + decide_line (hpos);
2632 + diwhigh_written = 0;
2633 + diwstop = v;
2634 + calcdiw ();
2635 +}
2636 +
2637 +static void DIWHIGH (int hpos, uae_u16 v)
2638 +{
2639 + if (! (currprefs.chipset_mask & CSMASK_ECS_DENISE))
2640 + return;
2641 + if (diwhigh_written && diwhigh == v)
2642 + return;
2643 + decide_line (hpos);
2644 + diwhigh_written = 1;
2645 + diwhigh = v;
2646 + calcdiw ();
2647 +}
2648 +
2649 +static void DDFSTRT (int hpos, uae_u16 v)
2650 +{
2651 + v &= 0xFC;
2652 + if (ddfstrt == v)
2653 + return;
2654 + decide_line (hpos);
2655 + ddfstrt = v;
2656 + calcdiw ();
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");
2662 + }
2663 +}
2664 +
2665 +static void DDFSTOP (int hpos, uae_u16 v)
2666 +{
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. */
2671 + v &= 0xFE;
2672 + if (ddfstop == v)
2673 + return;
2674 + decide_line (hpos);
2675 + decide_fetch (hpos);
2676 + ddfstop = v;
2677 + calcdiw ();
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");
2686 + }
2687 +}
2688 +
2689 +static void FMODE (uae_u16 v)
2690 +{
2691 + if (! (currprefs.chipset_mask & CSMASK_AGA))
2692 + v = 0;
2693 +
2694 + fmode = v;
2695 + sprite_width = GET_SPRITEWIDTH (fmode);
2696 + switch (fmode & 3) {
2697 + case 0:
2698 + fetchmode = 0;
2699 + break;
2700 + case 1:
2701 + case 2:
2702 + fetchmode = 1;
2703 + break;
2704 + case 3:
2705 + fetchmode = 2;
2706 + break;
2707 + }
2708 + curr_diagram = cycle_diagram_table[fetchmode][GET_RES (v)][GET_PLANES (bplcon0)];
2709 + expand_fmodes ();
2710 +}
2711 +
2712 +static void BLTADAT (uae_u16 v)
2713 +{
2714 + maybe_blit (0);
2715 +
2716 + blt_info.bltadat = v;
2717 +}
2718 +/*
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.
2722 + */
2723 +static void BLTBDAT (uae_u16 v)
2724 +{
2725 + maybe_blit (0);
2726 +
2727 + if (bltcon1 & 2)
2728 + blt_info.bltbhold = v << (bltcon1 >> 12);
2729 + else
2730 + blt_info.bltbhold = v >> (bltcon1 >> 12);
2731 + blt_info.bltbdat = v;
2732 +}
2733 +static void BLTCDAT (uae_u16 v) { maybe_blit (0); blt_info.bltcdat = v; }
2734 +
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); }
2739 +
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)
2744 +{
2745 + if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS))
2746 + return;
2747 + maybe_blit (0); bltcon0 = (bltcon0 & 0xFF00) | (v & 0xFF);
2748 +}
2749 +static void BLTCON1 (uae_u16 v) { maybe_blit (0); bltcon1 = v; }
2750 +
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; }
2753 +
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); }
2762 +
2763 +static void BLTSIZE (uae_u16 v)
2764 +{
2765 + maybe_blit (0);
2766 +
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;
2771 +
2772 + bltstate = BLT_init;
2773 + do_blitter ();
2774 +}
2775 +
2776 +static void BLTSIZV (uae_u16 v)
2777 +{
2778 + if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS))
2779 + return;
2780 + maybe_blit (0);
2781 + oldvblts = v & 0x7FFF;
2782 +}
2783 +
2784 +static void BLTSIZH (uae_u16 v)
2785 +{
2786 + if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS))
2787 + return;
2788 + maybe_blit (0);
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;
2794 + do_blitter ();
2795 +}
2796 +
2797 +STATIC_INLINE void SPRxCTL_1 (uae_u16 v, int num, int hpos)
2798 +{
2799 + int sprxp;
2800 + struct sprite *s = &spr[num];
2801 + sprctl[num] = v;
2802 + nr_armed -= s->armed;
2803 + s->armed = 0;
2804 + sprxp = (sprpos[num] & 0xFF) * 2 + (v & 1);
2805 +
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
2810 + resolution. */
2811 + sprxp <<= 1;
2812 + sprxp |= (v >> 4) & 1;
2813 + }
2814 + s->xpos = sprxp;
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);
2821 +#endif
2822 +}
2823 +STATIC_INLINE void SPRxPOS_1 (uae_u16 v, int num, int hpos)
2824 +{
2825 + int sprxp;
2826 + struct sprite *s = &spr[num];
2827 + sprpos[num] = v;
2828 + sprxp = (v & 0xFF) * 2 + (sprctl[num] & 1);
2829 +
2830 + if (currprefs.chipset_mask & CSMASK_AGA) {
2831 + sprxp <<= 1;
2832 + sprxp |= (sprctl[num] >> 4) & 1;
2833 + }
2834 + s->xpos = sprxp;
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);
2838 +#endif
2839 +}
2840 +STATIC_INLINE void SPRxDATA_1 (uae_u16 v, int num)
2841 +{
2842 + sprdata[num][0] = v;
2843 + nr_armed += 1 - spr[num].armed;
2844 + spr[num].armed = 1;
2845 +}
2846 +STATIC_INLINE void SPRxDATB_1 (uae_u16 v, int num)
2847 +{
2848 + sprdatb[num][0] = v;
2849 +}
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)
2855 +{
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);
2861 +#endif
2862 +}
2863 +static void SPRxPTL (int hpos, uae_u16 v, int num)
2864 +{
2865 + decide_sprites (hpos);
2866 + spr[num].pt &= ~0xffff;
2867 + spr[num].pt |= v;
2868 +#ifdef SPRITE_DEBUG
2869 + write_log ("%d:%d:SPR%dPTL %08.8X\n", vpos, hpos, num, spr[num].pt);
2870 +#endif
2871 +}
2872 +
2873 +static void CLXCON (uae_u16 v)
2874 +{
2875 + clxcon = 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);
2879 +}
2880 +static void CLXCON2 (uae_u16 v)
2881 +{
2882 + if (!(currprefs.chipset_mask & CSMASK_AGA))
2883 + return;
2884 + clxcon2 = v;
2885 + clxcon_bpl_enable |= v & (0x40|0x80);
2886 + clxcon_bpl_match |= (v & (0x01|0x02)) << 6;
2887 + }
2888 +static uae_u16 CLXDAT (void)
2889 +{
2890 + uae_u16 v = clxdat;
2891 + clxdat = 0;
2892 + return v;
2893 +}
2894 +
2895 +static uae_u16 COLOR_READ (int num)
2896 +{
2897 + int cr, cg, cb, colreg;
2898 + uae_u16 cval;
2899 +
2900 + if (!(currprefs.chipset_mask & CSMASK_AGA) || !(bplcon2 & 0x0100))
2901 + return 0xffff;
2902 +
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);
2909 + else
2910 + cval = ((cr >> 4) << 8) | ((cg >> 4) << 4) | ((cb >> 4) << 0);
2911 + return cval;
2912 +}
2913 +
2914 +static void COLOR_WRITE (int hpos, uae_u16 v, int num)
2915 +{
2916 + v &= 0xFFF;
2917 + if (currprefs.chipset_mask & CSMASK_AGA) {
2918 + int r,g,b;
2919 + int cr,cg,cb;
2920 + int colreg;
2921 + uae_u32 cval;
2922 +
2923 + /* writing is disabled when RDRAM=1 */
2924 + if (bplcon2 & 0x0100)
2925 + return;
2926 +
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;
2934 +
2935 + if (bplcon3 & 0x200) {
2936 + cr &= 0xF0; cr |= r;
2937 + cg &= 0xF0; cg |= g;
2938 + cb &= 0xF0; cb |= b;
2939 + } else {
2940 + cr = r + (r << 4);
2941 + cg = g + (g << 4);
2942 + cb = b + (b << 4);
2943 + }
2944 + cval = (cr << 16) | (cg << 8) | cb;
2945 + if (cval == current_colors.color_regs_aga[colreg])
2946 + return;
2947 +
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);
2953 + } else {
2954 + if (current_colors.color_regs_ecs[num] == v)
2955 + return;
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];
2961 + }
2962 +}
2963 +
2964 +static uae_u16 potgo_value;
2965 +
2966 +static void POTGO (uae_u16 v)
2967 +{
2968 + potgo_value = v;
2969 +}
2970 +
2971 +static uae_u16 POTGOR (void)
2972 +{
2973 + uae_u16 v = (potgo_value | (potgo_value >> 1)) & 0x5500;
2974 +
2975 + v |= (~potgo_value & 0xAA00) >> 1;
2976 +
2977 + if (JSEM_ISMOUSE (0, &currprefs)) {
2978 + if (buttonstate[2])
2979 + v &= 0xFBFF;
2980 +
2981 + if (buttonstate[1])
2982 + v &= 0xFEFF;
2983 + } else if (JSEM_ISJOY0 (0, &currprefs) || JSEM_ISJOY1 (0, &currprefs)) {
2984 + if (joy0button & 2) v &= 0xfbff;
2985 + if (joy0button & 4) v &= 0xfeff;
2986 + }
2987 +
2988 + if (JSEM_ISJOY0 (1, &currprefs) || JSEM_ISJOY1 (1, &currprefs)) {
2989 + if (joy1button & 2) v &= 0xbfff;
2990 + if (joy1button & 4) v &= 0xefff;
2991 + }
2992 +
2993 + return v;
2994 +}
2995 +
2996 +static uae_u16 POT0DAT (void)
2997 +{
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])
3003 + cnt += 0x100;
3004 + }
3005 +
3006 + return cnt;
3007 +}
3008 +static uae_u16 JOY0DAT (void)
3009 +{
3010 + if (JSEM_ISMOUSE (0, &currprefs)) {
3011 + do_mouse_hack ();
3012 + return ((uae_u8)mouse_x) + ((uae_u16)mouse_y << 8);
3013 + }
3014 + return joy0dir;
3015 +}
3016 +static uae_u16 JOY1DAT (void)
3017 +{
3018 + if (JSEM_ISMOUSE (1, &currprefs)) {
3019 + do_mouse_hack ();
3020 + return ((uae_u8)mouse_x) + ((uae_u16)mouse_y << 8);
3021 + }
3022 + return joy1dir;
3023 +}
3024 +static void JOYTEST (uae_u16 v)
3025 +{
3026 + if (JSEM_ISMOUSE (0, &currprefs)) {
3027 + mouse_x = v & 0xFC;
3028 + mouse_y = (v >> 8) & 0xFC;
3029 + }
3030 +}
3031 +
3032 +/* The copper code. The biggest nightmare in the whole emulator.
3033 +
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
3045 + it down).
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. */
3067 +
3068 +/* Determine which cycles are available for the copper in a display
3069 + * with a agiven number of planes. */
3070 +
3071 +STATIC_INLINE int copper_cant_read (int hpos)
3072 +{
3073 + int t;
3074 +
3075 + if (hpos + 1 >= maxhpos)
3076 + return 1;
3077 +
3078 + if (fetch_state == fetch_not_started || hpos < thisline_decision.plfleft)
3079 + return 0;
3080 +
3081 + if ((passed_plfstop == 3 && hpos >= thisline_decision.plfright)
3082 + || hpos >= estimated_last_fetch_cycle)
3083 + return 0;
3084 +
3085 + t = curr_diagram[(hpos + cycle_diagram_shift) & fetchstart_mask];
3086 +#if 0
3087 + if (t == -1)
3088 + abort ();
3089 +#endif
3090 + return t;
3091 +}
3092 +
3093 +STATIC_INLINE int dangerous_reg (int reg)
3094 +{
3095 + /* Safe:
3096 + * Bitplane pointers, control registers, modulos and data.
3097 + * Sprite pointers, control registers, and data.
3098 + * Color registers. */
3099 + if (reg >= 0xE0 && reg < 0x1C0)
3100 + return 0;
3101 + return 1;
3102 +}
3103 +
3104 +#define FAST_COPPER 1
3105 +
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
3111 + speedup.
3112 +
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
3117 + to be fast. */
3118 +static void predict_copper (void)
3119 +{
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;
3124 +
3125 + switch (state) {
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))
3130 + return;
3131 + state = state == COP_read2_wr_in2 ? COP_read2 : COP_read1;
3132 + break;
3133 +
3134 + case COP_read1_in2:
3135 + c_hpos += 2;
3136 + state = COP_read1;
3137 + break;
3138 +
3139 + case COP_stop:
3140 + case COP_bltwait:
3141 + case COP_wait1:
3142 + case COP_skip_in4:
3143 + case COP_skip_in2:
3144 + return;
3145 +
3146 + case COP_wait_in4:
3147 + c_hpos += 2;
3148 + /* fallthrough */
3149 + case COP_wait_in2:
3150 + c_hpos += 2;
3151 + /* fallthrough */
3152 + case COP_wait:
3153 + state = COP_wait;
3154 + break;
3155 +
3156 + default:
3157 + break;
3158 + }
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;
3164 +
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;
3169 + if (w1 & 1) {
3170 + w2 = chipmem_wget (ip);
3171 + if (w2 & 1)
3172 + goto done;
3173 + state = COP_wait;
3174 + c_hpos += 4;
3175 + } else if (dangerous_reg (w1)) {
3176 + c_hpos += 4;
3177 + goto done;
3178 + } else {
3179 + cop_state.regtypes_modified |= regtypes[w1 & 0x1FE];
3180 + state = COP_read1;
3181 + c_hpos += 2;
3182 + }
3183 + ip += 2;
3184 + }
3185 +
3186 + while (c_hpos + 1 < maxhpos) {
3187 + if (state == COP_read1) {
3188 + w1 = chipmem_wget (ip);
3189 + if (w1 & 1) {
3190 + w2 = chipmem_wget (ip + 2);
3191 + if (w2 & 1)
3192 + break;
3193 + state = COP_wait;
3194 + c_hpos += 6;
3195 + } else if (dangerous_reg (w1)) {
3196 + c_hpos += 6;
3197 + goto done;
3198 + } else {
3199 + cop_state.regtypes_modified |= regtypes[w1 & 0x1FE];
3200 + c_hpos += 4;
3201 + }
3202 + ip += 4;
3203 + } else if (state == COP_wait) {
3204 + if ((w2 & 0xFE) != 0xFE)
3205 + break;
3206 + else {
3207 + unsigned int vcmp = (w1 & (w2 | 0x8000)) >> 8;
3208 + unsigned int hcmp = (w1 & 0xFE);
3209 +
3210 + unsigned int vp = vpos & (((w2 >> 8) & 0x7F) | 0x80);
3211 + if (vp < vcmp) {
3212 + /* Whee. We can wait until the end of the line! */
3213 + c_hpos = maxhpos;
3214 + } else if (vp > vcmp || hcmp <= c_hpos) {
3215 + state = COP_read1;
3216 + /* minimum wakeup time */
3217 + c_hpos += 2;
3218 + } else {
3219 + state = COP_read1;
3220 + c_hpos = hcmp;
3221 + }
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;
3226 + }
3227 + }
3228 + } else
3229 + abort ();
3230 + }
3231 +
3232 + done:
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 ();
3240 + }
3241 +}
3242 +
3243 +static void perform_copper_write (int old_hpos)
3244 +{
3245 + int vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80);
3246 + unsigned int address = cop_state.saved_i1 & 0x1FE;
3247 +
3248 + record_copper (cop_state.saved_ip - 4, old_hpos, vpos);
3249 +
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);
3254 + return;
3255 + }
3256 +
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;
3263 + } else
3264 + custom_wput_1 (old_hpos, address, cop_state.saved_i2);
3265 +}
3266 +
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
3278 +};
3279 +
3280 +static void update_copper (int until_hpos)
3281 +{
3282 + int vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80);
3283 + int c_hpos = cop_state.hpos;
3284 +
3285 + if (eventtab[ev_copper].active)
3286 + abort ();
3287 +
3288 + if (cop_state.state == COP_wait && vp < cop_state.vcmp)
3289 + abort ();
3290 +
3291 + until_hpos &= ~1;
3292 +
3293 + if (until_hpos > (maxhpos & ~1))
3294 + until_hpos = maxhpos & ~1;
3295 +
3296 + until_hpos += 2;
3297 + for (;;) {
3298 + int old_hpos = c_hpos;
3299 + int hp;
3300 +
3301 + if (c_hpos >= until_hpos)
3302 + break;
3303 +
3304 + /* So we know about the fetch state. */
3305 + decide_line (c_hpos);
3306 +
3307 + switch (cop_state.state) {
3308 + case COP_read1_in2:
3309 + cop_state.state = COP_read1;
3310 + break;
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)
3316 + goto out;
3317 +
3318 + break;
3319 + case COP_read1_wr_in4:
3320 + cop_state.state = COP_read1_wr_in2;
3321 + break;
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)
3327 + goto out;
3328 +
3329 + break;
3330 + case COP_wait_in2:
3331 + cop_state.state = COP_wait1;
3332 + break;
3333 + case COP_wait_in4:
3334 + cop_state.state = COP_wait_in2;
3335 + break;
3336 + case COP_skip_in2:
3337 + {
3338 + static int skipped_before;
3339 + unsigned int vcmp, hcmp, vp1, hp1;
3340 + cop_state.state = COP_read1_in2;
3341 +
3342 + vcmp = (cop_state.saved_i1 & (cop_state.saved_i2 | 0x8000)) >> 8;
3343 + hcmp = (cop_state.saved_i1 & cop_state.saved_i2 & 0xFE);
3344 +
3345 + if (! skipped_before) {
3346 + skipped_before = 1;
3347 + write_log ("Program uses Copper SKIP instruction.\n");
3348 + }
3349 +
3350 + vp1 = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80);
3351 + hp1 = old_hpos & (cop_state.saved_i2 & 0xFE);
3352 +
3353 + if ((vp1 > vcmp || (vp1 == vcmp && hp1 >= hcmp))
3354 + && ((cop_state.saved_i2 & 0x8000) != 0 || ! (DMACONR() & 0x4000)))
3355 + cop_state.ignore_next = 1;
3356 + break;
3357 + }
3358 + case COP_skip_in4:
3359 + cop_state.state = COP_skip_in2;
3360 + break;
3361 + default:
3362 + break;
3363 + }
3364 +
3365 + c_hpos += 2;
3366 + if (copper_cant_read (old_hpos))
3367 + continue;
3368 +
3369 + switch (cop_state.state) {
3370 + case COP_read1_wr_in4:
3371 + abort ();
3372 +
3373 + case COP_read1_wr_in2:
3374 + case COP_read1:
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;
3378 + break;
3379 +
3380 + case COP_read2_wr_in2:
3381 + abort ();
3382 +
3383 + case COP_read2:
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;
3389 + break;
3390 + }
3391 +
3392 + cop_state.saved_i1 = cop_state.i1;
3393 + cop_state.saved_i2 = cop_state.i2;
3394 + cop_state.saved_ip = cop_state.ip;
3395 +
3396 + if (cop_state.i1 & 1) {
3397 + if (cop_state.i2 & 1)
3398 + cop_state.state = COP_skip_in4;
3399 + else
3400 + cop_state.state = COP_wait_in4;
3401 + } else {
3402 + unsigned int reg = cop_state.i1 & 0x1FE;
3403 + cop_state.state = isagnus[reg >> 1] ? COP_read1_wr_in2 : COP_read1_wr_in4;
3404 + }
3405 + break;
3406 +
3407 + case COP_wait1:
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))
3423 + break;
3424 + cop_state.state = COP_wait;
3425 +
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);
3428 +
3429 + vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80);
3430 +
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);
3435 + goto out;
3436 + }
3437 + if (vp < cop_state.vcmp) {
3438 + copper_enabled_thisline = 0;
3439 + unset_special (SPCFLAG_COPPER);
3440 + goto out;
3441 + }
3442 +
3443 + /* fall through */
3444 + do_wait:
3445 + case COP_wait:
3446 + if (vp < cop_state.vcmp)
3447 + abort ();
3448 +
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)
3456 + abort ();
3457 + else if (wait_finish <= until_hpos) {
3458 + c_hpos = wait_finish;
3459 + } else
3460 + c_hpos = until_hpos;
3461 + }
3462 + break;
3463 + }
3464 +
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);
3472 + goto out;
3473 + }
3474 +
3475 + record_copper (cop_state.ip - 4, old_hpos, vpos);
3476 +
3477 + cop_state.state = COP_read1;
3478 + break;
3479 +
3480 + default:
3481 + break;
3482 + }
3483 + }
3484 +
3485 + out:
3486 + cop_state.hpos = c_hpos;
3487 +
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 ();
3493 +}
3494 +
3495 +static void compute_spcflag_copper (void)
3496 +{
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)
3500 + return;
3501 +
3502 + if (cop_state.state == COP_wait) {
3503 + int vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80);
3504 +
3505 + if (vp < cop_state.vcmp)
3506 + return;
3507 + }
3508 + copper_enabled_thisline = 1;
3509 +
3510 + if (currprefs.fast_copper)
3511 + predict_copper ();
3512 +
3513 + if (! eventtab[ev_copper].active)
3514 + set_special (SPCFLAG_COPPER);
3515 +}
3516 +
3517 +static void copper_handler (void)
3518 +{
3519 + /* This will take effect immediately, within the same cycle. */
3520 + set_special (SPCFLAG_COPPER);
3521 +
3522 + if (! copper_enabled_thisline)
3523 + abort ();
3524 +
3525 + eventtab[ev_copper].active = 0;
3526 +}
3527 +
3528 +void blitter_done_notify (void)
3529 +{
3530 + if (cop_state.state != COP_bltwait)
3531 + return;
3532 +
3533 + cop_state.hpos = current_hpos () & ~1;
3534 + cop_state.vpos = vpos;
3535 + cop_state.state = COP_wait;
3536 + compute_spcflag_copper ();
3537 +}
3538 +
3539 +void do_copper (void)
3540 +{
3541 + int hpos = current_hpos ();
3542 + update_copper (hpos);
3543 +}
3544 +
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)
3550 +{
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)
3557 + return;
3558 +
3559 + if ((cop_state.regtypes_modified & regtypes[addr & 0x1FE]) == 0)
3560 + return;
3561 + }
3562 +
3563 + eventtab[ev_copper].active = 0;
3564 + if (do_schedule)
3565 + events_schedule ();
3566 + set_special (SPCFLAG_COPPER);
3567 + }
3568 + if (copper_enabled_thisline)
3569 + update_copper (hpos);
3570 +}
3571 +
3572 +STATIC_INLINE uae_u16 sprite_fetch (struct sprite *s, int dma)
3573 +{
3574 + uae_u16 data = last_custom_value;
3575 + if (dma)
3576 + data = last_custom_value = chipmem_wget (s->pt);
3577 + s->pt += 2;
3578 + return data;
3579 +}
3580 +
3581 +STATIC_INLINE void do_sprites_1 (int num, int cycle, int hpos)
3582 +{
3583 + struct sprite *s = &spr[num];
3584 + int dma;
3585 +
3586 + if (cycle == 0) {
3587 + if (vpos == s->vstart)
3588 + s->state = SPR_waiting_stop;
3589 + if (vpos == s->vstop)
3590 + s->state = SPR_restart;
3591 + }
3592 + if (!dmaen (DMA_SPRITE))
3593 + return;
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:");
3600 +#endif
3601 + if (cycle == 0) {
3602 + SPRxPOS_1 (dma ? data : sprpos[num], num, hpos);
3603 + } else {
3604 + s->state = SPR_waiting_start;
3605 + SPRxCTL_1 (dma ? data : sprctl[num], num, hpos);
3606 + }
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]);
3612 +
3613 + if (cycle == 0)
3614 + SPRxDATA_1 (dma ? data : sprdata[num][0], num);
3615 + else
3616 + SPRxDATB_1 (dma ? data : sprdatb[num][0], num);
3617 + switch (sprite_width)
3618 + {
3619 + case 64:
3620 + {
3621 + uae_u32 data32 = sprite_fetch (s, dma);
3622 + uae_u32 data641 = sprite_fetch (s, dma);
3623 + uae_u32 data642 = sprite_fetch (s, dma);
3624 + if (dma) {
3625 + if (cycle == 0) {
3626 + sprdata[num][3] = data642;
3627 + sprdata[num][2] = data641;
3628 + sprdata[num][1] = data32;
3629 + } else {
3630 + sprdatb[num][3] = data642;
3631 + sprdatb[num][2] = data641;
3632 + sprdatb[num][1] = data32;
3633 + }
3634 + }
3635 + }
3636 + break;
3637 + case 32:
3638 + {
3639 + uae_u32 data32 = sprite_fetch (s, dma);
3640 + if (dma) {
3641 + if (cycle == 0)
3642 + sprdata[num][1] = data32;
3643 + else
3644 + sprdatb[num][1] = data32;
3645 + }
3646 + }
3647 + break;
3648 + }
3649 + }
3650 +}
3651 +
3652 +#define SPR0_HPOS 0x15
3653 +static void do_sprites (int hpos)
3654 +{
3655 + int maxspr, minspr;
3656 + int i;
3657 +
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
3672 + * demo). */
3673 + /* Maximum for Sanity Turmoil: 27.
3674 + Minimum for Sanity Arte: 22. */
3675 + if (vpos < sprite_vblank_endline)
3676 + return;
3677 +
3678 + maxspr = hpos;
3679 + minspr = last_sprite_hpos;
3680 +
3681 + if (minspr >= SPR0_HPOS + MAX_SPRITES * 4 || maxspr < SPR0_HPOS)
3682 + return;
3683 +
3684 + if (maxspr > SPR0_HPOS + MAX_SPRITES * 4)
3685 + maxspr = SPR0_HPOS + MAX_SPRITES * 4;
3686 + if (minspr < SPR0_HPOS)
3687 + minspr = SPR0_HPOS;
3688 +
3689 + for (i = minspr; i < maxspr; i++) {
3690 + int cycle = -1;
3691 + switch ((i - SPR0_HPOS) & 3)
3692 + {
3693 + case 0:
3694 + cycle = 0;
3695 + break;
3696 + case 2:
3697 + cycle = 1;
3698 + break;
3699 + }
3700 + if (cycle >= 0)
3701 + do_sprites_1 ((i - SPR0_HPOS) / 4, cycle, i);
3702 + }
3703 + last_sprite_hpos = hpos;
3704 +}
3705 +
3706 +static void init_sprites (void)
3707 +{
3708 + int i;
3709 +
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);
3714 +}
3715 +
3716 +static void adjust_array_sizes (void)
3717 +{
3718 +#ifdef OS_WITHOUT_MEMORY_MANAGEMENT
3719 + if (delta_sprite_entry) {
3720 + void *p1,*p2;
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;
3727 + if (p1 && p2) {
3728 + write_log ("new max_sprite_entry=%d\n",mcc);
3729 + max_sprite_entry = mcc;
3730 + }
3731 + }
3732 + if (delta_color_change) {
3733 + void *p1,*p2;
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;
3740 + if (p1 && p2) {
3741 + write_log ("new max_color_change=%d\n",mcc);
3742 + max_color_change = mcc;
3743 + }
3744 + }
3745 +#endif
3746 +}
3747 +
3748 +static void init_hardware_frame (void)
3749 +{
3750 + next_lineno = 0;
3751 + nextline_how = nln_normal;
3752 + diwstate = DIW_waiting_start;
3753 + hdiwstate = DIW_waiting_start;
3754 +}
3755 +
3756 +void init_hardware_for_drawing_frame (void)
3757 +{
3758 + adjust_array_sizes ();
3759 +
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);
3766 + }
3767 + prev_next_sprite_entry = next_sprite_entry;
3768 +
3769 + next_color_change = 0;
3770 + next_sprite_entry = 0;
3771 + next_color_entry = 0;
3772 + remembered_color_entry = -1;
3773 +
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];
3780 +
3781 + prev_drawinfo = line_drawinfo[current_change_set];
3782 + curr_drawinfo = line_drawinfo[current_change_set ^ 1];
3783 + current_change_set ^= 1;
3784 +
3785 + color_src_match = color_dest_match = -1;
3786 +
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;
3790 +}
3791 +
3792 +static void do_savestate(void);
3793 +
3794 +static void vsync_handler (void)
3795 +{
3796 + int i;
3797 + for (i = 0; i < MAX_SPRITES; i++)
3798 + spr[i].state = SPR_waiting_start;
3799 +
3800 + n_frames++;
3801 +
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
3807 + * needed time. */
3808 + if ((long int)(curr_time - vsyncmintime) > 0 || rpt_did_reset)
3809 + vsyncmintime = curr_time + vsynctime;
3810 + rpt_did_reset = 0;
3811 + } else {
3812 +#ifdef RPT_WORKS_OK
3813 + if (RPT_WORKS_OK) {
3814 + frame_time_t curr_time;
3815 + do
3816 + curr_time = read_processor_time ();
3817 + while ((long int)(read_processor_time () - vsyncmintime) < 0);
3818 + vsyncmintime = curr_time + vsynctime;
3819 + }
3820 +#endif
3821 + }
3822 +
3823 + handle_events ();
3824 +
3825 + getjoystate (0, &joy0dir, &joy0button);
3826 + getjoystate (1, &joy1dir, &joy1button);
3827 +
3828 + INTREQ (0x8020);
3829 + if (bplcon0 & 4)
3830 + lof ^= 0x8000;
3831 +
3832 +#ifdef PICASSO96
3833 + if (picasso_on)
3834 + picasso_handle_vsync ();
3835 +#endif
3836 + vsync_handle_redraw (lof, lof_changed);
3837 +
3838 + if (quit_program > 0)
3839 + return;
3840 +
3841 + {
3842 + static int cnt = 0;
3843 + if (cnt == 0) {
3844 + /* resolution_check_change (); */
3845 + DISK_check_change ();
3846 + cnt = 5;
3847 + }
3848 + cnt--;
3849 + }
3850 +
3851 + /* Start a new set of copper records. */
3852 + curr_cop_set ^= 1;
3853 + nr_cop_records[curr_cop_set] = 0;
3854 +
3855 + /* For now, let's only allow this to change at vsync time. It gets too
3856 + * hairy otherwise. */
3857 + if (beamcon0 != new_beamcon0)
3858 + init_hz ();
3859 +
3860 + lof_changed = 0;
3861 +
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;
3867 +
3868 + init_hardware_frame ();
3869 +
3870 +#ifdef HAVE_GETTIMEOFDAY
3871 + {
3872 + struct timeval tv;
3873 + unsigned long int newtime;
3874 +
3875 + gettimeofday (&tv,NULL);
3876 + newtime = (tv.tv_sec-seconds_base) * 1000 + tv.tv_usec / 1000;
3877 +
3878 + if (!bogusframe) {
3879 + lastframetime = newtime - msecs;
3880 +
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)
3884 + {
3885 + n_consecutive_skipped = 0;
3886 + clear_inhibit_frame (IHF_SOUNDADJUST);
3887 + } else {
3888 + n_consecutive_skipped++;
3889 + set_inhibit_frame (IHF_SOUNDADJUST);
3890 + total_skipped++;
3891 + }
3892 +#endif
3893 +
3894 + frametime += lastframetime;
3895 + timeframes++;
3896 +
3897 + if ((timeframes & 127) == 0)
3898 + gui_fps (1000 * timeframes / frametime);
3899 + }
3900 + msecs = newtime;
3901 + bogusframe = 0;
3902 + }
3903 +#endif
3904 + if (ievent_alive > 0)
3905 + ievent_alive--;
3906 + if (timehack_alive > 0)
3907 + timehack_alive--;
3908 + CIA_vsync_handler ();
3909 +}
3910 +
3911 +static void hsync_handler (void)
3912 +{
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);
3916 +
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 ();
3923 + }
3924 + hsync_record_line_state (next_lineno, nextline_how, thisline_changed);
3925 +
3926 + eventtab[ev_hsync].evtime += get_cycles () - eventtab[ev_hsync].oldcycles;
3927 + eventtab[ev_hsync].oldcycles = get_cycles ();
3928 + CIA_hsync_handler ();
3929 +
3930 + if (currprefs.produce_sound > 0) {
3931 + int nr;
3932 +
3933 + update_audio ();
3934 +
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;
3938 +
3939 + if (cdp->data_written == 2) {
3940 + cdp->data_written = 0;
3941 + cdp->nextdat = chipmem_wget (cdp->pt);
3942 + cdp->pt += 2;
3943 + if (cdp->state == 2 || cdp->state == 3) {
3944 + if (cdp->wlen == 1) {
3945 + cdp->pt = cdp->lc;
3946 + cdp->wlen = cdp->len;
3947 + cdp->intreq2 = 1;
3948 + } else
3949 + cdp->wlen = (cdp->wlen - 1) & 0xFFFF;
3950 + }
3951 + }
3952 + }
3953 + }
3954 +
3955 + hardware_line_completed (next_lineno);
3956 +
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
3960 + this has). */
3961 +
3962 + if (++vpos >= (maxvpos + (lof != 0))) {
3963 + vpos = 0;
3964 + vsync_handler ();
3965 + }
3966 +
3967 + DISK_update ();
3968 +
3969 + is_lastline = vpos + 1 == maxvpos + (lof != 0) && currprefs.m68k_speed == -1 && ! rpt_did_reset;
3970 +
3971 + if ((bplcon0 & 4) && currprefs.gfx_linedbl)
3972 + notice_interlace_seen ();
3973 +
3974 + if (framecnt == 0) {
3975 + int lineno = vpos;
3976 + nextline_how = nln_normal;
3977 + if (currprefs.gfx_linedbl) {
3978 + lineno *= 2;
3979 + nextline_how = currprefs.gfx_linedbl == 1 ? nln_doubled : nln_nblack;
3980 + if (bplcon0 & 4) {
3981 + if (!lof) {
3982 + lineno++;
3983 + nextline_how = nln_lower;
3984 + } else {
3985 + nextline_how = nln_upper;
3986 + }
3987 + }
3988 + }
3989 + next_lineno = lineno;
3990 + reset_decisions ();
3991 + }
3992 + if (uae_int_requested) {
3993 + set_uae_int_flag ();
3994 + INTREQ (0xA000);
3995 + }
3996 + /* See if there's a chance of a copper wait ending this line. */
3997 + cop_state.hpos = 0;
3998 + compute_spcflag_copper ();
3999 +}
4000 +
4001 +static void init_regtypes (void)
4002 +{
4003 + int i;
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;
4022 + else switch (i) {
4023 + case 0x02:
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;
4029 + break;
4030 + case 0x04: case 0x06: case 0x2A: case 0x2C:
4031 + regtypes[i] = REGTYPE_POS;
4032 + break;
4033 + case 0x0A: case 0x0C:
4034 + case 0x12: case 0x14: case 0x16:
4035 + case 0x36:
4036 + regtypes[i] = REGTYPE_JOYPORT;
4037 + break;
4038 + case 0x104:
4039 + case 0x102:
4040 + regtypes[i] = REGTYPE_PLANE;
4041 + break;
4042 + case 0x88: case 0x8A:
4043 + case 0x8E: case 0x90: case 0x92: case 0x94:
4044 + case 0x96:
4045 + case 0x100:
4046 + regtypes[i] |= REGTYPE_FORCE;
4047 + break;
4048 + }
4049 + }
4050 +}
4051 +
4052 +void init_eventtab (void)
4053 +{
4054 + int i;
4055 +
4056 + currcycle = 0;
4057 + for (i = 0; i < ev_max; i++) {
4058 + eventtab[i].active = 0;
4059 + eventtab[i].oldcycles = 0;
4060 + }
4061 +
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;
4066 +
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 ();
4076 +}
4077 +
4078 +void customreset (void)
4079 +{
4080 + int i;
4081 + int zero = 0;
4082 +#ifdef HAVE_GETTIMEOFDAY
4083 + struct timeval tv;
4084 +#endif
4085 +
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];
4092 + }
4093 + } else {
4094 + for (i = 0; i < 256; i++) {
4095 + current_colors.color_regs_aga[i] = 0;
4096 + current_colors.acolors[i] = CONVERT_RGB (zero);
4097 + }
4098 + }
4099 +
4100 + clx_sprmask = 0xFF;
4101 + clxdat = 0;
4102 +
4103 + /* Clear the armed flags of all sprites. */
4104 + memset (spr, 0, sizeof spr);
4105 + nr_armed = 0;
4106 +
4107 + dmacon = intena = 0;
4108 +
4109 + copcon = 0;
4110 + DSKLEN (0, 0);
4111 +
4112 + bplcon0 = 0;
4113 + bplcon4 = 0x11; /* Get AGA chipset into ECS compatibility mode */
4114 + bplcon3 = 0xC00;
4115 +
4116 + FMODE (0);
4117 + CLXCON (0);
4118 + lof = 0;
4119 + }
4120 +
4121 + n_frames = 0;
4122 +
4123 + mmu_set_tc(0);
4124 + expamem_reset ();
4125 +
4126 + DISK_reset ();
4127 + CIA_reset ();
4128 + unset_special (~(SPCFLAG_BRK | SPCFLAG_MODE_CHANGE));
4129 +
4130 + vpos = 0;
4131 +
4132 + if (needmousehack ()) {
4133 +#if 0
4134 + mousehack_setfollow();
4135 +#else
4136 + mousehack_setdontcare();
4137 +#endif
4138 + } else {
4139 + mousestate = normal_mouse;
4140 + }
4141 + ievent_alive = 0;
4142 + timehack_alive = 0;
4143 +
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);
4152 +
4153 + bltstate = BLT_done;
4154 + cop_state.state = COP_stop;
4155 + diwstate = DIW_waiting_start;
4156 + hdiwstate = DIW_waiting_start;
4157 + currcycle = 0;
4158 +
4159 + new_beamcon0 = currprefs.ntscmode ? 0x00 : 0x20;
4160 + init_hz ();
4161 +
4162 + audio_reset ();
4163 +
4164 + init_sprites ();
4165 +
4166 + init_hardware_frame ();
4167 + reset_drawing ();
4168 +
4169 + reset_decisions ();
4170 +
4171 +#ifdef HAVE_GETTIMEOFDAY
4172 + gettimeofday (&tv, NULL);
4173 + seconds_base = tv.tv_sec;
4174 + bogusframe = 1;
4175 +#endif
4176 +
4177 + init_regtypes ();
4178 +
4179 + sprite_buffer_res = currprefs.chipset_mask & CSMASK_AGA ? RES_HIRES : RES_LORES;
4180 + if (savestate_state == STATE_RESTORE) {
4181 + uae_u16 v;
4182 + uae_u32 vv;
4183 +
4184 + update_adkmasks ();
4185 + INTENA (0);
4186 + INTREQ (0);
4187 +#if 0
4188 + DMACON (0, 0);
4189 +#endif
4190 + COPJMP1 (0);
4191 + if (diwhigh)
4192 + diwhigh_written = 1;
4193 + v = bplcon0;
4194 + BPLCON0 (0, 0);
4195 + BPLCON0 (0, v);
4196 + FMODE (fmode);
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];
4205 + }
4206 + } else {
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);
4214 + }
4215 + }
4216 + CLXCON (clxcon);
4217 + CLXCON2 (clxcon2);
4218 + calcdiw ();
4219 + write_log ("State restored\n");
4220 + dumpcustom ();
4221 + for (i = 0; i < 8; i++)
4222 + nr_armed += spr[i].armed != 0;
4223 + }
4224 + expand_sprres ();
4225 +}
4226 +
4227 +void dumpcustom (void)
4228 +{
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);
4234 + if (timeframes) {
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);
4239 + }
4240 + /*for (i=0; i<256; i++) if (blitcount[i]) write_log ("minterm %x = %d\n",i,blitcount[i]); blitter debug */
4241 +}
4242 +
4243 +int intlev (void)
4244 +{
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;
4253 + }
4254 + return -1;
4255 +}
4256 +
4257 +static void gen_custom_tables (void)
4258 +{
4259 + int i;
4260 + for (i = 0; i < 256; i++) {
4261 + unsigned int j;
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));
4273 + }
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;
4285 + }
4286 +}
4287 +
4288 +void custom_init (void)
4289 +{
4290 + uaecptr pos;
4291 +
4292 +#ifdef OS_WITHOUT_MEMORY_MANAGEMENT
4293 + int num;
4294 +
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));
4298 + }
4299 +#endif
4300 +
4301 + pos = here ();
4302 +
4303 + org (RTAREA_BASE+0xFF70);
4304 + calltrap (deftrap (mousehack_helper));
4305 + dw (RTS);
4306 +
4307 + org (RTAREA_BASE+0xFFA0);
4308 + calltrap (deftrap (timehack_helper));
4309 + dw (RTS);
4310 +
4311 + org (pos);
4312 +
4313 + gen_custom_tables ();
4314 + build_blitfilltable ();
4315 +
4316 + drawing_init ();
4317 +
4318 + mousestate = unknown_mouse;
4319 +
4320 + if (needmousehack ())
4321 + mousehack_setfollow ();
4322 +
4323 + create_cycle_diagram_table ();
4324 +}
4325 +
4326 +/* Custom chip memory bank */
4327 +
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;
4334 +
4335 +addrbank custom_bank = {
4336 + custom_lget, custom_wget, custom_bget,
4337 + custom_lput, custom_wput, custom_bput,
4338 + default_xlate, default_check, NULL
4339 +};
4340 +
4341 +STATIC_INLINE uae_u32 REGPARAM2 custom_wget_1 (uaecptr addr)
4342 +{
4343 + uae_u16 v;
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;
4349 +
4350 + case 0x008: v = DSKDATR (current_hpos ()); break;
4351 +
4352 + case 0x00A: v = JOY0DAT (); break;
4353 + case 0x00C: v = JOY1DAT (); break;
4354 + case 0x00E: v = CLXDAT (); break;
4355 + case 0x010: v = ADKCONR (); break;
4356 +
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;
4364 +
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);
4372 + break;
4373 +
4374 + default:
4375 + v = last_custom_value;
4376 + custom_wput (addr, v);
4377 + last_custom_value = 0xffff;
4378 + return v;
4379 + }
4380 + last_custom_value = v;
4381 + return v;
4382 +}
4383 +
4384 +uae_u32 REGPARAM2 custom_wget (uaecptr addr)
4385 +{
4386 + sync_copper_with_cpu (current_hpos (), 1, addr);
4387 + return custom_wget_1 (addr);
4388 +}
4389 +
4390 +uae_u32 REGPARAM2 custom_bget (uaecptr addr)
4391 +{
4392 + special_mem |= S_READ;
4393 + return custom_wget (addr & 0xfffe) >> (addr & 1 ? 0 : 8);
4394 +}
4395 +
4396 +uae_u32 REGPARAM2 custom_lget (uaecptr addr)
4397 +{
4398 + special_mem |= S_READ;
4399 + return ((uae_u32)custom_wget (addr & 0xfffe) << 16) | custom_wget ((addr + 2) & 0xfffe);
4400 +}
4401 +
4402 +void REGPARAM2 custom_wput_1 (int hpos, uaecptr addr, uae_u32 value)
4403 +{
4404 + addr &= 0x1FE;
4405 + last_custom_value = value;
4406 + switch (addr) {
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;
4411 +
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;
4419 +
4420 + case 0x044: BLTAFWM (value); break;
4421 + case 0x046: BLTALWM (value); break;
4422 +
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;
4431 +
4432 + case 0x058: BLTSIZE (value); break;
4433 +
4434 + case 0x064: BLTAMOD (value); break;
4435 + case 0x062: BLTBMOD (value); break;
4436 + case 0x060: BLTCMOD (value); break;
4437 + case 0x066: BLTDMOD (value); break;
4438 +
4439 + case 0x070: BLTCDAT (value); break;
4440 + case 0x072: BLTBDAT (value); break;
4441 + case 0x074: BLTADAT (value); break;
4442 +
4443 + case 0x07E: DSKSYNC (value); break;
4444 +
4445 + case 0x080: COP1LCH (value); break;
4446 + case 0x082: COP1LCL (value); break;
4447 + case 0x084: COP2LCH (value); break;
4448 + case 0x086: COP2LCL (value); break;
4449 +
4450 + case 0x088: COPJMP1 (value); break;
4451 + case 0x08A: COPJMP2 (value); break;
4452 +
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;
4457 +
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;
4463 +
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;
4470 +
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;
4477 +
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;
4484 +
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;
4491 +
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;
4508 +
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;
4513 +
4514 + case 0x108: BPL1MOD (hpos, value); break;
4515 + case 0x10A: BPL2MOD (hpos, value); break;
4516 + case 0x10E: CLXCON2 (value); break;
4517 +
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;
4526 +
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);
4534 + break;
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);
4538 + break;
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);
4542 + break;
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);
4546 + break;
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);
4550 + break;
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);
4554 + break;
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);
4558 + break;
4559 +
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;
4567 + }
4568 +}
4569 +
4570 +void REGPARAM2 custom_wput (uaecptr addr, uae_u32 value)
4571 +{
4572 + int hpos = current_hpos ();
4573 + special_mem |= S_WRITE;
4574 +
4575 + sync_copper_with_cpu (hpos, 1, addr);
4576 + custom_wput_1 (hpos, addr, value);
4577 +}
4578 +
4579 +void REGPARAM2 custom_bput (uaecptr addr, uae_u32 value)
4580 +{
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);
4588 + warned++;
4589 + }
4590 +}
4591 +
4592 +void REGPARAM2 custom_lput(uaecptr addr, uae_u32 value)
4593 +{
4594 + special_mem |= S_WRITE;
4595 + custom_wput (addr & 0xfffe, value >> 16);
4596 + custom_wput ((addr + 2) & 0xfffe, (uae_u16)value);
4597 +}
4598 +
4599 +void custom_prepare_savestate (void)
4600 +{
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;
4607 + }
4608 +}
4609 +
4610 +#define RB restore_u8 ()
4611 +#define RW restore_u16 ()
4612 +#define RL restore_u32 ()
4613 +
4614 +uae_u8 *restore_custom (uae_u8 *src)
4615 +{
4616 + uae_u16 dsklen, dskbytr, dskdatr;
4617 + int dskpt;
4618 + int i;
4619 +
4620 + audio_reset ();
4621 +
4622 + currprefs.chipset_mask = RL;
4623 + RW; /* 000 ? */
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 */
4670 + RW; /* 068 ? */
4671 + RW; /* 06A ? */
4672 + RW; /* 06C ? */
4673 + RW; /* 06E ? */
4674 + BLTCDAT(RW); /* 070 BLTCDAT */
4675 + BLTBDAT(RW); /* 072 BLTBDAT */
4676 + BLTADAT(RW); /* 074 BLTADAT */
4677 + RW; /* 076 ? */
4678 + RW; /* 078 ? */
4679 + RW; /* 07A ? */
4680 + RW; /* 07C LISAID */
4681 + DSKSYNC(RW); /* 07E DSKSYNC */
4682 + cop1lc = RL; /* 080/082 COP1LC */
4683 + cop2lc = RL; /* 084/086 COP2LC */
4684 + RW; /* 088 ? */
4685 + RW; /* 08A ? */
4686 + RW; /* 08C ? */
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++)
4697 + bplpt[i] = RL;
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++)
4707 + RW; /* BPLXDAT */
4708 + for(i = 0; i < 32; i++)
4709 + current_colors.color_regs_ecs[i] = RW; /* 180 COLORxx */
4710 + RW; /* 1C0 ? */
4711 + RW; /* 1C2 ? */
4712 + RW; /* 1C4 ? */
4713 + RW; /* 1C6 ? */
4714 + RW; /* 1C8 ? */
4715 + RW; /* 1CA ? */
4716 + RW; /* 1CC ? */
4717 + RW; /* 1CE ? */
4718 + RW; /* 1D0 ? */
4719 + RW; /* 1D2 ? */
4720 + RW; /* 1D4 ? */
4721 + RW; /* 1D6 ? */
4722 + RW; /* 1D8 ? */
4723 + RW; /* 1DA ? */
4724 + new_beamcon0 = RW; /* 1DC BEAMCON0 */
4725 + RW; /* 1DE ? */
4726 + RW; /* 1E0 ? */
4727 + RW; /* 1E2 ? */
4728 + RW; /* 1E4 ? */
4729 + RW; /* 1E6 ? */
4730 + RW; /* 1E8 ? */
4731 + RW; /* 1EA ? */
4732 + RW; /* 1EC ? */
4733 + RW; /* 1EE ? */
4734 + RW; /* 1F0 ? */
4735 + RW; /* 1F2 ? */
4736 + RW; /* 1F4 ? */
4737 + RW; /* 1F6 ? */
4738 + RW; /* 1F8 ? */
4739 + RW; /* 1FA ? */
4740 + fmode = RW; /* 1FC FMODE */
4741 + RW; /* 1FE ? */
4742 +
4743 + DISK_restore_custom (dskpt, dsklen, dskdatr, dskbytr);
4744 +
4745 + return src;
4746 +}
4747 +
4748 +
4749 +#define SB save_u8
4750 +#define SW save_u16
4751 +#define SL save_u32
4752 +
4753 +extern uae_u16 serper;
4754 +
4755 +uae_u8 *save_custom (int *len)
4756 +{
4757 + uae_u8 *dstbak, *dst;
4758 + int i;
4759 + uae_u32 dskpt;
4760 + uae_u16 dsklen, dsksync, dskdatr, dskbytr;
4761 +
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 */
4852 + SW (0); /* 1C0 */
4853 + SW (0); /* 1C2 */
4854 + SW (0); /* 1C4 */
4855 + SW (0); /* 1C6 */
4856 + SW (0); /* 1C8 */
4857 + SW (0); /* 1CA */
4858 + SW (0); /* 1CC */
4859 + SW (0); /* 1CE */
4860 + SW (0); /* 1D0 */
4861 + SW (0); /* 1D2 */
4862 + SW (0); /* 1D4 */
4863 + SW (0); /* 1D6 */
4864 + SW (0); /* 1D8 */
4865 + SW (0); /* 1DA */
4866 + SW (beamcon0); /* 1DC BEAMCON0 */
4867 + SW (0); /* 1DE */
4868 + SW (0); /* 1E0 */
4869 + SW (0); /* 1E2 */
4870 + SW (0); /* 1E4 */
4871 + SW (0); /* 1E6 */
4872 + SW (0); /* 1E8 */
4873 + SW (0); /* 1EA */
4874 + SW (0); /* 1EC */
4875 + SW (0); /* 1EE */
4876 + SW (0); /* 1F0 */
4877 + SW (0); /* 1F2 */
4878 + SW (0); /* 1F4 */
4879 + SW (0); /* 1F6 */
4880 + SW (0); /* 1F8 */
4881 + SW (0); /* 1FA */
4882 + SW (fmode); /* 1FC FMODE */
4883 + SW (0xffff); /* 1FE */
4884 +
4885 + *len = dst - dstbak;
4886 + return dstbak;
4887 +}
4888 +
4889 +uae_u8 *restore_custom_agacolors (uae_u8 *src)
4890 +{
4891 + int i;
4892 +
4893 + for (i = 0; i < 256; i++)
4894 + current_colors.color_regs_aga[i] = RL;
4895 + return src;
4896 +}
4897 +
4898 +uae_u8 *save_custom_agacolors (int *len)
4899 +{
4900 + uae_u8 *dstbak, *dst;
4901 + int i;
4902 +
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;
4907 + return dstbak;
4908 +}
4909 +
4910 +uae_u8 *restore_custom_sprite (uae_u8 *src, int num)
4911 +{
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;
4924 + return src;
4925 +}
4926 +
4927 +uae_u8 *save_custom_sprite(int *len, int num)
4928 +{
4929 + uae_u8 *dstbak, *dst;
4930 +
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;
4945 + return dstbak;
4946 +}
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
4950 @@ -680,6 +680,9 @@
4951 printf ("Plane %d offset %d\n", i, bpl_off[i]);
4952 }
4953 break;
4954 + case 'u':
4955 + mmu_dump_tables();
4956 + break;
4957 case 'h':
4958 case '?':
4959 {
4960 @@ -704,6 +707,7 @@
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");
4967 }
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
4971 @@ -0,0 +1,717 @@
4972 + /*
4973 + * UAE - The Un*x Amiga Emulator
4974 + *
4975 + * Debugger
4976 + *
4977 + * (c) 1995 Bernd Schmidt
4978 + *
4979 + */
4980 +
4981 +#include "sysconfig.h"
4982 +#include "sysdeps.h"
4983 +
4984 +#include <ctype.h>
4985 +#include <signal.h>
4986 +
4987 +#include "config.h"
4988 +#include "options.h"
4989 +#include "threaddep/thread.h"
4990 +#include "uae.h"
4991 +#include "memory.h"
4992 +#include "custom.h"
4993 +#include "newcpu.h"
4994 +#include "debug.h"
4995 +#include "cia.h"
4996 +#include "xwin.h"
4997 +#include "gui.h"
4998 +#include "identify.h"
4999 +
5000 +static int debugger_active = 0;
5001 +static uaecptr skipaddr;
5002 +static int do_skip;
5003 +int debugging = 0;
5004 +
5005 +static FILE *logfile;
5006 +
5007 +void activate_debugger (void)
5008 +{
5009 + if (logfile)
5010 + fclose (logfile);
5011 + logfile = 0;
5012 + do_skip = 0;
5013 + if (debugger_active)
5014 + return;
5015 + debugger_active = 1;
5016 + set_special (SPCFLAG_BRK);
5017 + debugging = 1;
5018 + /* use_debugger = 1; */
5019 +}
5020 +
5021 +int firsthist = 0;
5022 +int lasthist = 0;
5023 +#ifdef NEED_TO_DEBUG_BADLY
5024 +struct regstruct history[MAX_HIST];
5025 +union flagu historyf[MAX_HIST];
5026 +#else
5027 +uaecptr history[MAX_HIST];
5028 +#endif
5029 +
5030 +static void ignore_ws (char **c)
5031 +{
5032 + while (**c && isspace(**c)) (*c)++;
5033 +}
5034 +
5035 +static uae_u32 readhex (char **c)
5036 +{
5037 + uae_u32 val = 0;
5038 + char nc;
5039 +
5040 + ignore_ws (c);
5041 +
5042 + while (isxdigit(nc = **c)) {
5043 + (*c)++;
5044 + val *= 16;
5045 + nc = toupper(nc);
5046 + if (isdigit(nc)) {
5047 + val += nc - '0';
5048 + } else {
5049 + val += nc - 'A' + 10;
5050 + }
5051 + }
5052 + return val;
5053 +}
5054 +
5055 +static uae_u32 readint (char **c)
5056 +{
5057 + uae_u32 val = 0;
5058 + char nc;
5059 + int negative = 0;
5060 +
5061 + ignore_ws (c);
5062 +
5063 + if (**c == '-')
5064 + negative = 1, (*c)++;
5065 + while (isdigit(nc = **c)) {
5066 + (*c)++;
5067 + val *= 10;
5068 + val += nc - '0';
5069 + }
5070 + return val * (negative ? -1 : 1);
5071 +}
5072 +
5073 +static char next_char( char **c)
5074 +{
5075 + ignore_ws (c);
5076 + return *(*c)++;
5077 +}
5078 +
5079 +static int more_params (char **c)
5080 +{
5081 + ignore_ws (c);
5082 + return (**c) != 0;
5083 +}
5084 +
5085 +static void dumpmem (uaecptr addr, uaecptr *nxmem, int lines)
5086 +{
5087 + broken_in = 0;
5088 + for (;lines-- && !broken_in;) {
5089 + int i;
5090 + printf ("%08lx ", addr);
5091 + for (i = 0; i < 16; i++) {
5092 + printf ("%04x ", get_word(addr)); addr += 2;
5093 + }
5094 + printf ("\n");
5095 + }
5096 + *nxmem = addr;
5097 +}
5098 +
5099 +static void foundmod (uae_u32 ptr, char *type)
5100 +{
5101 + char name[21];
5102 + uae_u8 *ptr2 = chipmemory + ptr;
5103 + int i,length;
5104 +
5105 + printf ("Found possible %s module at 0x%lx.\n", type, ptr);
5106 + memcpy (name, ptr2, 20);
5107 + name[20] = '\0';
5108 +
5109 + /* Browse playlist */
5110 + length = 0;
5111 + for (i = 0x3b8; i < 0x438; i++)
5112 + if (ptr2[i] > length)
5113 + length = ptr2[i];
5114 +
5115 + length = (length+1)*1024 + 0x43c;
5116 +
5117 + /* Add sample lengths */
5118 + ptr2 += 0x2A;
5119 + for (i = 0; i < 31; i++, ptr2 += 30)
5120 + length += 2*((ptr2[0]<<8)+ptr2[1]);
5121 +
5122 + printf ("Name \"%s\", Length 0x%lx bytes.\n", name, length);
5123 +}
5124 +
5125 +static void modulesearch (void)
5126 +{
5127 + uae_u8 *p = get_real_address (0);
5128 + uae_u32 ptr;
5129 +
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)");
5135 +
5136 + if (ptr >= 0x438 && p[0] == 'F' && p[1] == 'L' && p[2] == 'T' && p[3] == '4')
5137 + foundmod (ptr - 0x438, "Startrekker");
5138 +
5139 + if (strncmp ((char *)p, "SMOD", 4) == 0) {
5140 + printf ("Found possible FutureComposer 1.3 module at 0x%lx, length unknown.\n", ptr);
5141 + }
5142 + if (strncmp ((char *)p, "FC14", 4) == 0) {
5143 + printf ("Found possible FutureComposer 1.4 module at 0x%lx, length unknown.\n", ptr);
5144 + }
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);
5150 + }
5151 + if (p[4] == 0x41 && p[5] == 0xFA) {
5152 + int i;
5153 +
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)
5156 + break;
5157 + if (i < 0x240) {
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);
5162 + }
5163 + }
5164 + }
5165 + }
5166 +}
5167 +
5168 +static void dump_traps (void)
5169 +{
5170 + int i;
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));
5174 + }
5175 +}
5176 +
5177 +static void dump_ints (void)
5178 +{
5179 + int i;
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));
5183 + }
5184 +}
5185 +
5186 +static void disassemble_wait (FILE *file, unsigned long insn)
5187 +{
5188 + uae_u8 vp,hp,ve,he,bfd,v_mask,h_mask;
5189 +
5190 + vp = (insn & 0xff000000) >> 24;
5191 + hp = (insn & 0x00fe0000) >> 16;
5192 + ve = (insn & 0x00007f00) >> 8;
5193 + he = (insn & 0x000000fe);
5194 + bfd = insn & 0x00008000 >> 15;
5195 +
5196 + /* bit15 can never be masked out*/
5197 + v_mask = vp & (ve | 0x80);
5198 + h_mask = hp & he;
5199 + if (v_mask > 0) {
5200 + fprintf (file, "vpos ");
5201 + if (ve != 0x7f) {
5202 + fprintf (file, "& 0x%02x ", ve);
5203 + }
5204 + fprintf (file, ">= 0x%02x", v_mask);
5205 + }
5206 + if (he > 0) {
5207 + if (v_mask > 0) {
5208 + fprintf (file," and");
5209 + }
5210 + fprintf (file, " hpos ");
5211 + if (he != 0xfe) {
5212 + fprintf (file, "& 0x%02x ", he);
5213 + }
5214 + fprintf (file, ">= 0x%02x", h_mask);
5215 + } else {
5216 + fprintf (file, ", ignore horizontal");
5217 + }
5218 +
5219 + fprintf (file, ".\n \t; VP %02x, VE %02x; HP %02x, HE %02x; BFD %d\n",
5220 + vp, ve, hp, he, bfd);
5221 +}
5222 +
5223 +/* simple decode copper by Mark Cox */
5224 +static void decode_copper_insn (FILE* file, unsigned long insn, unsigned long addr)
5225 +{
5226 + uae_u32 insn_type = insn & 0x00010001;
5227 + int hpos, vpos;
5228 + char record[] = " ";
5229 + if (find_copper_record (addr, &hpos, &vpos)) {
5230 + sprintf (record, " [%03x %03x]", vpos, hpos);
5231 + }
5232 +
5233 + fprintf (file, "%08lx: %04lx %04lx%s\t; ", addr, insn >> 16, insn & 0xFFFF, record);
5234 +
5235 + switch (insn_type) {
5236 + case 0x00010000: /* WAIT insn */
5237 + fprintf (file, "Wait for ");
5238 + disassemble_wait (file, insn);
5239 +
5240 + if (insn == 0xfffffffe)
5241 + fprintf (file, " \t; End of Copperlist\n");
5242 +
5243 + break;
5244 +
5245 + case 0x00010001: /* SKIP insn */
5246 + fprintf (file, "Skip if ");
5247 + disassemble_wait (file, insn);
5248 + break;
5249 +
5250 + case 0x00000000:
5251 + case 0x00000001: /* MOVE insn */
5252 + fprintf (file, "%s := 0x%04lx\n",
5253 + custd[(insn & 0x01fe0000) >> 17].name,
5254 + insn & 0x0000ffff);
5255 +
5256 + if ((insn & 0xfe000000) != 0) {
5257 + fprintf (file, " \t;OCS Compatibility warning: bits 15-9 should be 0 for compatibility with OCS\n");
5258 + }
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 */
5262 + break;
5263 +
5264 + default:
5265 + abort ();
5266 + }
5267 +
5268 +}
5269 +
5270 +
5271 +static uaecptr decode_copperlist (FILE* file, uaecptr address, int nolines)
5272 +{
5273 + uae_u32 insn;
5274 + while (nolines-- > 0) {
5275 + insn = get_long (address);
5276 + decode_copper_insn (file, insn, address);
5277 + address += 4;
5278 + }
5279 + return 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 */
5283 +}
5284 +
5285 +
5286 +/* cheat-search by Holger Jakob */
5287 +static void cheatsearch (char **c)
5288 +{
5289 + uae_u8 *p = get_real_address (0);
5290 + static uae_u32 *vlist = NULL;
5291 + uae_u32 ptr;
5292 + uae_u32 val = 0;
5293 + uae_u32 type = 0; /* not yet */
5294 + uae_u32 count = 0;
5295 + uae_u32 fcount = 0;
5296 + uae_u32 full = 0;
5297 + char nc;
5298 +
5299 + ignore_ws (c);
5300 +
5301 + while (isxdigit (nc = **c)) {
5302 + (*c)++;
5303 + val *= 10;
5304 + nc = toupper (nc);
5305 + if (isdigit (nc)) {
5306 + val += nc - '0';
5307 + }
5308 + }
5309 + if (vlist == NULL) {
5310 + vlist = malloc (256*4);
5311 + if (vlist != 0) {
5312 + for (count = 0; count<255; count++)
5313 + vlist[count] = 0;
5314 + count = 0;
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))
5320 + {
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]);
5324 + } else
5325 + full = 1;
5326 + }
5327 + }
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");
5330 + }
5331 + } else {
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))
5337 + {
5338 + fcount++;
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]);
5341 + }
5342 + }
5343 + printf ("%d hits of %d found\n",fcount,val);
5344 + free (vlist);
5345 + vlist = NULL;
5346 + }
5347 +}
5348 +
5349 +static void writeintomem (char **c)
5350 +{
5351 + uae_u8 *p = get_real_address (0);
5352 + uae_u32 addr = 0;
5353 + uae_u32 val = 0;
5354 + char nc;
5355 +
5356 + ignore_ws(c);
5357 + while (isxdigit(nc = **c)) {
5358 + (*c)++;
5359 + addr *= 16;
5360 + nc = toupper(nc);
5361 + if (isdigit(nc)) {
5362 + addr += nc - '0';
5363 + } else {
5364 + addr += nc - 'A' + 10;
5365 + }
5366 + }
5367 + ignore_ws(c);
5368 + while (isxdigit(nc = **c)) {
5369 + (*c)++;
5370 + val *= 10;
5371 + nc = toupper(nc);
5372 + if (isdigit(nc)) {
5373 + val += nc - '0';
5374 + }
5375 + }
5376 +
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);
5383 + } else
5384 + printf ("Invalid address %08x\n",addr);
5385 +}
5386 +
5387 +static void show_exec_tasks (void)
5388 +{
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);
5400 + while (node) {
5401 + printf ("%08lx: %08lx %s\n", node, 0, get_real_address (get_long (node + 10)));
5402 + node = get_long (node);
5403 + }
5404 + printf ("Waiting:\n");
5405 + node = get_long (taskwait);
5406 + end = get_long (taskwait + 4);
5407 + while (node) {
5408 + printf ("%08lx: %08lx %s\n", node, 0, get_real_address (get_long (node + 10)));
5409 + node = get_long (node);
5410 + }
5411 +}
5412 +
5413 +static int trace_same_insn_count;
5414 +static uae_u8 trace_insn_copy[10];
5415 +static struct regstruct trace_prev_regs;
5416 +void debug (void)
5417 +{
5418 + char input[80];
5419 + uaecptr nextpc,nxdis,nxmem,nxcopper;
5420 +
5421 + bogusframe = 1;
5422 +
5423 + if (do_skip && skipaddr == 0xC0DEDBAD) {
5424 +#if 0
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)
5428 + {
5429 + trace_same_insn_count++;
5430 + return;
5431 + }
5432 + }
5433 + if (trace_same_insn_count > 1)
5434 + fprintf (logfile, "[ repeated %d times ]\n", trace_same_insn_count);
5435 +#endif
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, &regs, sizeof regs);
5440 + }
5441 +
5442 + if (do_skip && (m68k_getpc() != skipaddr/* || regs.a[0] != 0x1e558*/)) {
5443 + set_special (SPCFLAG_BRK);
5444 + return;
5445 + }
5446 + do_skip = 0;
5447 +
5448 +#ifdef NEED_TO_DEBUG_BADLY
5449 + history[lasthist] = regs;
5450 + historyf[lasthist] = regflags;
5451 +#else
5452 + history[lasthist] = m68k_getpc();
5453 +#endif
5454 + if (++lasthist == MAX_HIST) lasthist = 0;
5455 + if (lasthist == firsthist) {
5456 + if (++firsthist == MAX_HIST) firsthist = 0;
5457 + }
5458 +
5459 + m68k_dumpstate (stdout, &nextpc);
5460 + nxdis = nextpc; nxmem = nxcopper = 0;
5461 +
5462 + for (;;) {
5463 + char cmd, *inptr;
5464 +
5465 + printf (">");
5466 + fflush (stdout);
5467 + if (fgets (input, 80, stdin) == 0)
5468 + return;
5469 + inptr = input;
5470 + cmd = next_char (&inptr);
5471 + switch (cmd) {
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;
5479 + case 'S':
5480 + {
5481 + uae_u8 *memp;
5482 + uae_u32 src, len;
5483 + char *name;
5484 + FILE *fp;
5485 +
5486 + if (!more_params (&inptr))
5487 + goto S_argh;
5488 +
5489 + name = inptr;
5490 + while (*inptr != '\0' && !isspace (*inptr))
5491 + inptr++;
5492 + if (!isspace (*inptr))
5493 + goto S_argh;
5494 +
5495 + *inptr = '\0';
5496 + inptr++;
5497 + if (!more_params (&inptr))
5498 + goto S_argh;
5499 + src = readhex (&inptr);
5500 + if (!more_params (&inptr))
5501 + goto S_argh;
5502 + len = readhex (&inptr);
5503 + if (! valid_address (src, len)) {
5504 + printf ("Invalid memory block\n");
5505 + break;
5506 + }
5507 + memp = get_real_address (src);
5508 + fp = fopen (name, "w");
5509 + if (fp == NULL) {
5510 + printf ("Couldn't open file\n");
5511 + break;
5512 + }
5513 + if (fwrite (memp, 1, len, fp) != len) {
5514 + printf ("Error writing file\n");
5515 + }
5516 + fclose (fp);
5517 + break;
5518 +
5519 + S_argh:
5520 + printf ("S command needs more arguments!\n");
5521 + break;
5522 + }
5523 + case 'd':
5524 + {
5525 + uae_u32 daddr;
5526 + int count;
5527 +
5528 + if (more_params(&inptr))
5529 + daddr = readhex(&inptr);
5530 + else
5531 + daddr = nxdis;
5532 + if (more_params(&inptr))
5533 + count = readhex(&inptr);
5534 + else
5535 + count = 10;
5536 + m68k_disasm (stdout, daddr, &nxdis, count);
5537 + }
5538 + break;
5539 + case 'T': show_exec_tasks (); break;
5540 + case 't': set_special (SPCFLAG_BRK); return;
5541 + case 'z':
5542 + skipaddr = nextpc;
5543 + do_skip = 1;
5544 + set_special (SPCFLAG_BRK);
5545 + return;
5546 +
5547 + case 'f':
5548 + skipaddr = readhex (&inptr);
5549 + do_skip = 1;
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, &regs, sizeof regs);
5556 + }
5557 + return;
5558 +
5559 + case 'q': uae_quit();
5560 + debugger_active = 0;
5561 + debugging = 0;
5562 + return;
5563 +
5564 + case 'g':
5565 + if (more_params (&inptr))
5566 + m68k_setpc (readhex (&inptr));
5567 + fill_prefetch_0 ();
5568 + debugger_active = 0;
5569 + debugging = 0;
5570 + return;
5571 +
5572 + case 'H':
5573 + {
5574 + int count;
5575 + int temp;
5576 +#ifdef NEED_TO_DEBUG_BADLY
5577 + struct regstruct save_regs = regs;
5578 + union flagu save_flags = regflags;
5579 +#endif
5580 +
5581 + if (more_params(&inptr))
5582 + count = readhex(&inptr);
5583 + else
5584 + count = 10;
5585 + if (count < 0)
5586 + break;
5587 + temp = lasthist;
5588 + while (count-- > 0 && temp != firsthist) {
5589 + if (temp == 0) temp = MAX_HIST-1; else temp--;
5590 + }
5591 + while (temp != lasthist) {
5592 +#ifdef NEED_TO_DEBUG_BADLY
5593 + regs = history[temp];
5594 + regflags = historyf[temp];
5595 + m68k_dumpstate (NULL);
5596 +#else
5597 + m68k_disasm (stdout, history[temp], NULL, 1);
5598 +#endif
5599 + if (++temp == MAX_HIST) temp = 0;
5600 + }
5601 +#ifdef NEED_TO_DEBUG_BADLY
5602 + regs = save_regs;
5603 + regflags = save_flags;
5604 +#endif
5605 + }
5606 + break;
5607 + case 'm':
5608 + {
5609 + uae_u32 maddr; int lines;
5610 + if (more_params(&inptr))
5611 + maddr = readhex(&inptr);
5612 + else
5613 + maddr = nxmem;
5614 + if (more_params(&inptr))
5615 + lines = readhex(&inptr);
5616 + else
5617 + lines = 16;
5618 + dumpmem(maddr, &nxmem, lines);
5619 + }
5620 + break;
5621 + case 'o':
5622 + {
5623 + uae_u32 maddr;
5624 + int lines;
5625 +
5626 + if (more_params(&inptr)) {
5627 + maddr = readhex(&inptr);
5628 + if (maddr == 1 || maddr == 2)
5629 + maddr = get_copper_address (maddr);
5630 + }
5631 + else
5632 + maddr = nxcopper;
5633 +
5634 + if (more_params (&inptr))
5635 + lines = readhex (&inptr);
5636 + else
5637 + lines = 10;
5638 +
5639 + nxcopper = decode_copperlist (stdout, maddr, lines);
5640 + break;
5641 + }
5642 + case 'O':
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;
5648 + } else {
5649 + int i;
5650 + for (i = 0; i < 8; i++)
5651 + printf ("Plane %d offset %d\n", i, bpl_off[i]);
5652 + }
5653 + break;
5654 + case 'u':
5655 + mmu_dump_tables();
5656 + break;
5657 + case 'h':
5658 + case '?':
5659 + {
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");
5684 + }
5685 + break;
5686 + }
5687 + }
5688 +}
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 @@
5693 regs.s = 0;
5694 /* Set some interrupt vectors */
5695 for (a = 8; a < 0xC0; a += 4) {
5696 - put_long (a, 0xF8001A);
5697 + phys_put_long (a, 0xF8001A);
5698 }
5699 regs.isp = regs.msp = regs.usp = 0x800;
5700 m68k_areg(regs, 7) = 0x80000;
5701 regs.intmask = 0;
5702
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);
5713 }
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);
5724
5725 /* Build an IORequest */
5726 request = 0x800;
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;
5736 ersatz_doio ();
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");
5744
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;
5755 ersatz_doio ();
5756
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;
5768 ersatz_doio ();
5769
5770 @@ -174,25 +174,25 @@
5771 fill_prefetch_0 ();
5772
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);
5785 -
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);
5804 +
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);
5812 }
5813
5814 void ersatz_perform (uae_u16 what)
5815 @@ -204,7 +204,7 @@
5816
5817 case EOP_SERVEINT:
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);
5821 break;
5822
5823 case EOP_DOIO:
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
5827 @@ -19,6 +19,8 @@
5828 #include "autoconf.h"
5829 #include "picasso96.h"
5830 #include "savestate.h"
5831 +#include "custom.h"
5832 +#include "newcpu.h"
5833
5834 #define MAX_EXPANSION_BOARDS 8
5835
5836 @@ -843,9 +845,9 @@
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))
5845 {
5846 /* warn user */
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
5851 @@ -16,6 +16,7 @@
5852 * The source for the insn timings is Markt & Technik's Amiga Magazin 8/1992.
5853 *
5854 * Copyright 1995, 1996, 1997, 1998, 1999, 2000 Bernd Schmidt
5855 + * vim:ts=8:sw=4:
5856 */
5857
5858 #include "sysconfig.h"
5859 @@ -25,12 +26,14 @@
5860 #include "readcpu.h"
5861
5862 #define BOOL_TYPE "int"
5863 +#define VERIFY_MMU_GENAMODE 0
5864
5865 static FILE *headerfile;
5866 static FILE *stblfile;
5867
5868 static int using_prefetch;
5869 static int using_exception_3;
5870 +static int using_mmu;
5871 static int cpu_level;
5872
5873 /* For the current opcode, the next lower level that will have different code.
5874 @@ -43,6 +46,20 @@
5875 static int *opcode_last_postfix;
5876 static unsigned long *counts;
5877
5878 +
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
5885 +
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_" };
5891 +
5892 static void read_counts (void)
5893 {
5894 FILE *file;
5895 @@ -133,11 +150,16 @@
5896 return 0;
5897 }
5898
5899 +int nexti_no_inc = 0;
5900 +
5901 +
5902 static const char *gen_nextilong (void)
5903 {
5904 static char buffer[80];
5905 int r = m68k_pc_offset;
5906 - m68k_pc_offset += 4;
5907 +
5908 + if (!nexti_no_inc)
5909 + m68k_pc_offset += 4;
5910
5911 insn_n_cycles += 8;
5912
5913 @@ -152,7 +174,9 @@
5914 {
5915 static char buffer[80];
5916 int r = m68k_pc_offset;
5917 - m68k_pc_offset += 2;
5918 +
5919 + if (!nexti_no_inc)
5920 + m68k_pc_offset += 2;
5921
5922 insn_n_cycles += 4;
5923
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)
5930 +
5931 {
5932 +
5933 + if (!using_mmu)
5934 + xlateflag = XLATE_PHYS;
5935 +
5936 start_brace ();
5937 switch (mode) {
5938 case Dreg:
5939 if (movem)
5940 abort ();
5941 - if (getv == 1)
5942 + if (getv == GENA_GETV_FETCH)
5943 switch (size) {
5944 case sz_byte:
5945 #if defined(AMIGA) && !defined(WARPUP)
5946 @@ -247,7 +276,7 @@
5947 case Areg:
5948 if (movem)
5949 abort ();
5950 - if (getv == 1)
5951 + if (getv == GENA_GETV_FETCH)
5952 switch (size) {
5953 case sz_word:
5954 printf ("\tuae_s16 %s = m68k_areg(regs, %s);\n", name, reg);
5955 @@ -329,7 +358,7 @@
5956 printf ("\tuaecptr %sa = %s;\n", name, gen_nextilong ());
5957 break;
5958 case imm:
5959 - if (getv != 1)
5960 + if (getv != GENA_GETV_FETCH)
5961 abort ();
5962 switch (size) {
5963 case sz_byte:
5964 @@ -346,22 +375,22 @@
5965 }
5966 return;
5967 case imm0:
5968 - if (getv != 1)
5969 + if (getv != GENA_GETV_FETCH)
5970 abort ();
5971 printf ("\tuae_s8 %s = %s;\n", name, gen_nextibyte ());
5972 return;
5973 case imm1:
5974 - if (getv != 1)
5975 + if (getv != GENA_GETV_FETCH)
5976 abort ();
5977 printf ("\tuae_s16 %s = %s;\n", name, gen_nextiword ());
5978 return;
5979 case imm2:
5980 - if (getv != 1)
5981 + if (getv != GENA_GETV_FETCH)
5982 abort ();
5983 printf ("\tuae_s32 %s = %s;\n", name, gen_nextilong ());
5984 return;
5985 case immi:
5986 - if (getv != 1)
5987 + if (getv != GENA_GETV_FETCH)
5988 abort ();
5989 printf ("\tuae_u32 %s = %s;\n", name, reg);
5990 return;
5991 @@ -372,7 +401,7 @@
5992 /* We get here for all non-reg non-immediate addressing modes to
5993 * actually fetch the value. */
5994
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");
6000 @@ -384,7 +413,7 @@
6001 start_brace ();
6002 }
6003
6004 - if (getv == 1) {
6005 + if (getv == GENA_GETV_FETCH) {
6006 switch (size) {
6007 case sz_byte: insn_n_cycles += 4; break;
6008 case sz_word: insn_n_cycles += 4; break;
6009 @@ -393,9 +422,9 @@
6010 }
6011 start_brace ();
6012 switch (size) {
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;
6019 default: abort ();
6020 }
6021 }
6022 @@ -427,7 +456,7 @@
6023 }
6024 }
6025
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)
6028 {
6029 switch (mode) {
6030 case Dreg:
6031 @@ -472,19 +501,19 @@
6032 switch (size) {
6033 case sz_byte:
6034 insn_n_cycles += 4;
6035 - printf ("\tput_byte(%sa,%s);\n", to, from);
6036 + printf ("\t%sput_byte(%sa,%s);\n", mem_prefix[xlateflag], to, from);
6037 break;
6038 case sz_word:
6039 insn_n_cycles += 4;
6040 if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
6041 abort ();
6042 - printf ("\tput_word(%sa,%s);\n", to, from);
6043 + printf ("\t%sput_word(%sa,%s);\n", mem_prefix[xlateflag], to, from);
6044 break;
6045 case sz_long:
6046 insn_n_cycles += 8;
6047 if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
6048 abort ();
6049 - printf ("\tput_long(%sa,%s);\n", to, from);
6050 + printf ("\t%sput_long(%sa,%s);\n", mem_prefix[xlateflag], to, from);
6051 break;
6052 default:
6053 abort ();
6054 @@ -506,16 +535,20 @@
6055 {
6056 char getcode[100];
6057 int size = table68k[opcode].size == sz_long ? 4 : 2;
6058 + int xlateflag = using_mmu ? XLATE_LOG : XLATE_PHYS;
6059
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)");
6064 } else {
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)");
6069 }
6070
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);
6075 start_brace ();
6076 printf ("\twhile (dmask) { m68k_dreg(regs, movem_index1[dmask]) = %s; srca += %d; dmask = movem_next[dmask]; }\n",
6077 getcode, size);
6078 @@ -530,14 +563,19 @@
6079 {
6080 char putcode[100];
6081 int size = table68k[opcode].size == sz_long ? 4 : 2;
6082 + int noxlate = using_mmu ? XLATE_LOG : XLATE_PHYS;
6083 +
6084 + strcpy(putcode, mem_prefix[noxlate]);
6085 +
6086 if (table68k[opcode].size == sz_long) {
6087 - strcpy (putcode, "put_long(srca,");
6088 + strcat (putcode, "put_long(srca,");
6089 } else {
6090 - strcpy (putcode, "put_word(srca,");
6091 + strcat (putcode, "put_word(srca,");
6092 }
6093
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);
6098 if (using_prefetch)
6099 sync_m68k_pc ();
6100
6101 @@ -825,6 +863,7 @@
6102 static void gen_opcode (unsigned long int opcode)
6103 {
6104 struct instr *curi = table68k + opcode;
6105 + int xlateflag = using_mmu ? XLATE_LOG : XLATE_PHYS;
6106 insn_n_cycles = 4;
6107
6108 start_brace ();
6109 @@ -859,16 +898,16 @@
6110 case i_OR:
6111 case i_AND:
6112 case i_EOR:
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);
6121 break;
6122 case i_ORSR:
6123 case i_EORSR:
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");
6129 }
6130 @@ -877,7 +916,7 @@
6131 break;
6132 case i_ANDSR:
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");
6138 }
6139 @@ -885,31 +924,31 @@
6140 printf ("\tMakeFromSR();\n");
6141 break;
6142 case i_SUB:
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);
6147 start_brace ();
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);
6151 break;
6152 case i_SUBA:
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);
6157 start_brace ();
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);
6161 break;
6162 case i_SUBX:
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);
6167 start_brace ();
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);
6173 break;
6174 case i_SBCD:
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);
6179 start_brace ();
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 @@
6183 duplicate_carry ();
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);
6188 break;
6189 case i_ADD:
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);
6194 start_brace ();
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);
6198 break;
6199 case i_ADDA:
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);
6204 start_brace ();
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);
6208 break;
6209 case i_ADDX:
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);
6214 start_brace ();
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);
6220 break;
6221 case i_ABCD:
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);
6226 start_brace ();
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 @@
6230 duplicate_carry ();
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);
6235 break;
6236 case i_NEG:
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);
6239 start_brace ();
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);
6243 break;
6244 case i_NEGX:
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);
6247 start_brace ();
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);
6253 break;
6254 case i_NBCD:
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);
6257 start_brace ();
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");
6262 duplicate_carry();
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);
6266 break;
6267 case i_CLR:
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);
6273 break;
6274 case i_NOT:
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);
6277 start_brace ();
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);
6282 break;
6283 case i_TST:
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", "", "");
6287 break;
6288 case i_BTST:
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");
6295 else
6296 @@ -1021,55 +1060,55 @@
6297 printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n");
6298 break;
6299 case i_BCHG:
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");
6306 else
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);
6312 break;
6313 case i_BCLR:
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");
6320 else
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);
6326 break;
6327 case i_BSET:
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");
6334 else
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);
6340 break;
6341 case i_CMPM:
6342 case i_CMP:
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);
6347 start_brace ();
6348 genflags (flag_cmp, curi->size, "newv", "src", "dst");
6349 break;
6350 case i_CMPA:
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);
6355 start_brace ();
6356 genflags (flag_cmp, sz_long, "newv", "src", "dst");
6357 break;
6358 /* The next two are coded a little unconventional, but they are doing
6359 * weird things... */
6360 case i_MVPRM:
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);
6363
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 @@
6367 break;
6368 case i_MVPMR:
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");
6374 } else {
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");
6377 }
6378 - genastore ("val", curi->dmode, "dstreg", curi->size, "dst");
6379 + genastore ("val", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
6380 break;
6381 case i_MOVE:
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);
6389 break;
6390 case i_MOVEA:
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");
6397 } else {
6398 printf ("\tuae_u32 val = src;\n");
6399 }
6400 - genastore ("val", curi->dmode, "dstreg", sz_long, "dst");
6401 + genastore ("val", curi->dmode, "dstreg", sz_long, "dst", xlateflag);
6402 break;
6403 case i_MVSR2:
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);
6410 else
6411 - genastore ("regs.sr", curi->smode, "srcreg", sz_word, "src");
6412 + genastore ("regs.sr", curi->smode, "srcreg", sz_word, "src", xlateflag);
6413 break;
6414 case i_MV2SR:
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");
6419 else {
6420 @@ -1124,20 +1163,20 @@
6421 printf ("\tMakeFromSR();\n");
6422 break;
6423 case i_SWAP:
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);
6426 start_brace ();
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);
6431 break;
6432 case i_EXG:
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);
6441 break;
6442 case i_EXT:
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);
6445 start_brace ();
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);
6454 break;
6455 case i_MVMEL:
6456 genmovemel (opcode);
6457 @@ -1157,18 +1196,18 @@
6458 genmovemle (opcode);
6459 break;
6460 case i_TRAP:
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);
6463 sync_m68k_pc ();
6464 printf ("\tException(src+32,0);\n");
6465 m68k_pc_offset = 0;
6466 break;
6467 case i_MVR2USP:
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");
6471 break;
6472 case i_MVUSP2R:
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);
6477 break;
6478 case i_RESET:
6479 printf ("\tcustomreset();\n");
6480 @@ -1176,15 +1215,15 @@
6481 case i_NOP:
6482 break;
6483 case i_STOP:
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");
6489 break;
6490 case i_RTE:
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");
6497 fill_prefetch_0 ();
6498 printf ("\tMakeFromSR();\n");
6499 @@ -1193,13 +1232,14 @@
6500 if (next_cpu_level < 0)
6501 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 @@
6518 break;
6519 case i_RTD:
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");
6527 fill_prefetch_0 ();
6528 @@ -1226,18 +1266,18 @@
6529 m68k_pc_offset = 0;
6530 break;
6531 case i_LINK:
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");
6543 break;
6544 case i_UNLK:
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);
6552 break;
6553 case i_RTS:
6554 printf ("\tm68k_do_rts();\n");
6555 @@ -1252,8 +1292,8 @@
6556 case i_RTR:
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");
6565 fill_prefetch_0 ();
6566 @@ -1261,19 +1301,19 @@
6567 m68k_pc_offset = 0;
6568 break;
6569 case i_JSR:
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);
6573 fill_prefetch_0 ();
6574 m68k_pc_offset = 0;
6575 break;
6576 case i_JMP:
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");
6580 fill_prefetch_0 ();
6581 m68k_pc_offset = 0;
6582 break;
6583 case i_BSR:
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 @@
6590 next_cpu_level = 1;
6591 }
6592 }
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;
6600 break;
6601 case i_LEA:
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);
6608 break;
6609 case i_PEA:
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);
6616 break;
6617 case i_DBcc:
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);
6622
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);
6626
6627 printf ("\t\tif (src) {\n");
6628 if (using_exception_3) {
6629 @@ -1362,15 +1402,15 @@
6630 need_endlabel = 1;
6631 break;
6632 case i_Scc:
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);
6635 start_brace ();
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);
6639 break;
6640 case i_DIVU:
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);
6646 sync_m68k_pc ();
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);
6655 printf ("\t}\n");
6656 printf ("\t}\n");
6657 insn_n_cycles += 136;
6658 @@ -1390,8 +1430,8 @@
6659 break;
6660 case i_DIVS:
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);
6666 sync_m68k_pc ();
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);
6675 printf ("\t}\n");
6676 printf ("\t}\n");
6677 insn_n_cycles += 154;
6678 need_endlabel = 1;
6679 break;
6680 case i_MULU:
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);
6685 start_brace ();
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;
6691 break;
6692 case i_MULS:
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);
6697 start_brace ();
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;
6703 break;
6704 case i_CHK:
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);
6712 need_endlabel = 1;
6713 @@ -1435,8 +1475,8 @@
6714
6715 case i_CHK2:
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) {
6723 case sz_byte:
6724 @@ -1460,8 +1500,8 @@
6725 break;
6726
6727 case i_ASR:
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);
6732 start_brace ();
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));
6737 printf ("\t}\n");
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);
6741 break;
6742 case i_ASL:
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);
6747 start_brace ();
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));
6752 printf ("\t}\n");
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);
6756 break;
6757 case i_LSR:
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);
6762 start_brace ();
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");
6767 printf ("\t}\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);
6771 break;
6772 case i_LSL:
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);
6777 start_brace ();
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));
6782 printf ("\t}\n");
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);
6786 break;
6787 case i_ROL:
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);
6792 start_brace ();
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");
6797 printf ("}\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);
6801 break;
6802 case i_ROR:
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);
6807 start_brace ();
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);
6812 printf ("\t}\n");
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);
6816 break;
6817 case i_ROXL:
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);
6822 start_brace ();
6823 switch (curi->size) {
6824 case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
6825 @@ -1669,11 +1709,11 @@
6826 printf ("\t} }\n");
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);
6831 break;
6832 case i_ROXR:
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);
6837 start_brace ();
6838 switch (curi->size) {
6839 case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
6840 @@ -1702,10 +1742,10 @@
6841 printf ("\t} }\n");
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);
6846 break;
6847 case i_ASRW:
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);
6850 start_brace ();
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");
6856 duplicate_carry ();
6857 - genastore ("val", curi->smode, "srcreg", curi->size, "data");
6858 + genastore ("val", curi->smode, "srcreg", curi->size, "data", xlateflag);
6859 break;
6860 case i_ASLW:
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);
6863 start_brace ();
6864 switch (curi->size) {
6865 case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
6866 @@ -1739,10 +1779,10 @@
6867 duplicate_carry ();
6868
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);
6872 break;
6873 case i_LSRW:
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);
6876 start_brace ();
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");
6882 duplicate_carry ();
6883 - genastore ("val", curi->smode, "srcreg", curi->size, "data");
6884 + genastore ("val", curi->smode, "srcreg", curi->size, "data", xlateflag);
6885 break;
6886 case i_LSLW:
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);
6889 start_brace ();
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);
6895 duplicate_carry ();
6896 - genastore ("val", curi->smode, "srcreg", curi->size, "data");
6897 + genastore ("val", curi->smode, "srcreg", curi->size, "data", xlateflag);
6898 break;
6899 case i_ROLW:
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);
6902 start_brace ();
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);
6911 break;
6912 case i_RORW:
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);
6915 start_brace ();
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);
6924 break;
6925 case i_ROXLW:
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);
6928 start_brace ();
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);
6934 duplicate_carry ();
6935 - genastore ("val", curi->smode, "srcreg", curi->size, "data");
6936 + genastore ("val", curi->smode, "srcreg", curi->size, "data", xlateflag);
6937 break;
6938 case i_ROXRW:
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);
6941 start_brace ();
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");
6947 duplicate_carry ();
6948 - genastore ("val", curi->smode, "srcreg", curi->size, "data");
6949 + genastore ("val", curi->smode, "srcreg", curi->size, "data", xlateflag);
6950 break;
6951 case i_MOVEC2:
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);
6954 start_brace ();
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);
6958 break;
6959 case i_MOVE2C:
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);
6962 start_brace ();
6963 printf ("\tint regno = (src >> 12) & 15;\n");
6964 printf ("\tuae_u32 *regp = regs.regs + regno;\n");
6965 @@ -1856,8 +1896,8 @@
6966 case i_CAS:
6967 {
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);
6973 start_brace ();
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;
6979 start_brace ();
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);
6983 printf ("else");
6984 start_brace ();
6985 @@ -1874,7 +1914,7 @@
6986 }
6987 break;
6988 case i_CAS2:
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 @@
6995 printf ("\t}\n");
6996 }
6997 break;
6998 - case i_MOVES: /* ignore DFC and SFC because we have no MMU */
6999 + case i_MOVES:
7000 {
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;
7005 - start_brace ();
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);
7010 - printf ("else");
7011 - start_brace ();
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;
7020 +
7021 + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
7022 + start_brace();
7023 + printf ("\tif (extra & 0x0800)\n"); /* from reg to ea */
7024 + {
7025 + /* use DFC */
7026 + old_brace_level = n_braces;
7027 + start_brace ();
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);
7031 + nexti_no_inc = 0;
7032 + genastore ("src", curi->dmode, "dstreg", curi->size, "dst", XLATE_DFC);
7033 + pop_braces (old_brace_level);
7034 + }
7035 + printf ("else"); /* from ea to reg */
7036 + {
7037 + /* use SFC */
7038 + start_brace ();
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 ();
7046 + }
7047 + printf ("\t} else {\n");
7048 + genastore ("src", Dreg, "(extra >> 12) & 7", curi->size, "", XLATE_LOG);
7049 + printf ("\t}\n");
7050 + pop_braces (old_brace_level);
7051 }
7052 - printf ("\t} else {\n");
7053 - genastore ("src", Dreg, "(extra >> 12) & 7", curi->size, "");
7054 - printf ("\t}\n");
7055 - pop_braces (old_brace_level);
7056 }
7057 break;
7058 case i_BKPT: /* only needed for hardware emulators */
7059 @@ -1950,7 +2000,7 @@
7060 break;
7061 case i_TRAPcc:
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);
7066 need_endlabel = 1;
7067 break;
7068 @@ -1958,14 +2008,14 @@
7069 sync_m68k_pc ();
7070 start_brace ();
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);
7076 sync_m68k_pc ();
7077 printf ("\tm68k_divl(opcode, dst, extra, oldpc);\n");
7078 break;
7079 case i_MULL:
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);
7084 sync_m68k_pc ();
7085 printf ("\tm68k_mull(opcode, dst, extra);\n");
7086 break;
7087 @@ -1977,8 +2027,8 @@
7088 case i_BFFFO:
7089 case i_BFSET:
7090 case i_BFINS:
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);
7095 start_brace ();
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 @@
7099 }
7100 break;
7101 case i_TAS:
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);
7108 break;
7109 case i_FPP:
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);
7112 sync_m68k_pc ();
7113 printf ("\tfpp_opp(opcode,extra);\n");
7114 break;
7115 case i_FDBcc:
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);
7118 sync_m68k_pc ();
7119 printf ("\tfdbcc_opp(opcode,extra);\n");
7120 break;
7121 case i_FScc:
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);
7124 sync_m68k_pc ();
7125 printf ("\tfscc_opp(opcode,extra);\n");
7126 break;
7127 @@ -2107,7 +2157,7 @@
7128 start_brace ();
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);
7133 sync_m68k_pc ();
7134 printf ("\tftrapcc_opp(opcode,oldpc);\n");
7135 break;
7136 @@ -2115,7 +2165,7 @@
7137 sync_m68k_pc ();
7138 start_brace ();
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);
7142 sync_m68k_pc ();
7143 printf ("\tfbcc_opp(opcode,pc,extra);\n");
7144 break;
7145 @@ -2150,8 +2200,8 @@
7146 printf ("\tm68k_areg(regs, dstreg) += 16;\n");
7147 } else {
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 @@
7157 break;
7158
7159 case i_MMUOP:
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);
7162 sync_m68k_pc ();
7163 printf ("\tmmu_op(opcode,extra);\n");
7164 break;
7165 @@ -2310,8 +2360,11 @@
7166
7167 using_prefetch = 0;
7168 using_exception_3 = 0;
7169 + using_mmu = 0;
7170 +
7171 for (i = 0; i < 6; i++) {
7172 cpu_level = 4 - i;
7173 + using_mmu = cpu_level == 4;
7174 if (i == 5) {
7175 cpu_level = 0;
7176 using_prefetch = 1;
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
7180 @@ -0,0 +1,2436 @@
7181 +/*
7182 + * UAE - The Un*x Amiga Emulator
7183 + *
7184 + * MC68000 emulation generator
7185 + *
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
7192 + * call abort().
7193 + * The generated code is sometimes sub-optimal, an optimizing compiler should
7194 + * take care of this.
7195 + *
7196 + * The source for the insn timings is Markt & Technik's Amiga Magazin 8/1992.
7197 + *
7198 + * Copyright 1995, 1996, 1997, 1998, 1999, 2000 Bernd Schmidt
7199 + * vim:ts=8:sw=4:
7200 + */
7201 +
7202 +#include "sysconfig.h"
7203 +#include "sysdeps.h"
7204 +#include <ctype.h>
7205 +
7206 +#include "readcpu.h"
7207 +
7208 +#define BOOL_TYPE "int"
7209 +#define VERIFY_MMU_GENAMODE 0
7210 +
7211 +static FILE *headerfile;
7212 +static FILE *stblfile;
7213 +
7214 +static int using_prefetch;
7215 +static int using_exception_3;
7216 +static int using_mmu;
7217 +static int cpu_level;
7218 +
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;
7223 +
7224 +static int *opcode_map;
7225 +static int *opcode_next_clev;
7226 +static int *opcode_last_postfix;
7227 +static unsigned long *counts;
7228 +
7229 +
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
7236 +
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_" };
7242 +
7243 +static void read_counts (void)
7244 +{
7245 + FILE *file;
7246 + unsigned long opcode, count, total;
7247 + char name[20];
7248 + int nr = 0;
7249 + memset (counts, 0, 65536 * sizeof *counts);
7250 +
7251 + file = fopen ("frequent.68k", "r");
7252 + if (file) {
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;
7259 + }
7260 + fclose (file);
7261 + }
7262 + if (nr == nr_cpuop_funcs)
7263 + return;
7264 + for (opcode = 0; opcode < 0x10000; opcode++) {
7265 + if (table68k[opcode].handler == -1 && table68k[opcode].mnemo != i_ILLG
7266 + && counts[opcode] == 0)
7267 + {
7268 + opcode_next_clev[nr] = 4;
7269 + opcode_last_postfix[nr] = -1;
7270 + opcode_map[nr++] = opcode;
7271 + counts[opcode] = count;
7272 + }
7273 + }
7274 + if (nr != nr_cpuop_funcs)
7275 + abort ();
7276 +}
7277 +
7278 +static char endlabelstr[80];
7279 +static int endlabelno = 0;
7280 +static int need_endlabel;
7281 +
7282 +static int n_braces = 0;
7283 +static int m68k_pc_offset = 0;
7284 +static int insn_n_cycles;
7285 +
7286 +static void start_brace (void)
7287 +{
7288 + n_braces++;
7289 + printf ("{");
7290 +}
7291 +
7292 +static void close_brace (void)
7293 +{
7294 + assert (n_braces > 0);
7295 + n_braces--;
7296 + printf ("}");
7297 +}
7298 +
7299 +static void finish_braces (void)
7300 +{
7301 + while (n_braces > 0)
7302 + close_brace ();
7303 +}
7304 +
7305 +static void pop_braces (int to)
7306 +{
7307 + while (n_braces > to)
7308 + close_brace ();
7309 +}
7310 +
7311 +static int bit_size (int size)
7312 +{
7313 + switch (size) {
7314 + case sz_byte: return 8;
7315 + case sz_word: return 16;
7316 + case sz_long: return 32;
7317 + default: abort ();
7318 + }
7319 + return 0;
7320 +}
7321 +
7322 +static const char *bit_mask (int size)
7323 +{
7324 + switch (size) {
7325 + case sz_byte: return "0xff";
7326 + case sz_word: return "0xffff";
7327 + case sz_long: return "0xffffffff";
7328 + default: abort ();
7329 + }
7330 + return 0;
7331 +}
7332 +
7333 +int nexti_no_inc = 0;
7334 +
7335 +
7336 +static const char *gen_nextilong (void)
7337 +{
7338 + static char buffer[80];
7339 + int r = m68k_pc_offset;
7340 +
7341 + if (!nexti_no_inc)
7342 + m68k_pc_offset += 4;
7343 +
7344 + insn_n_cycles += 8;
7345 +
7346 + if (using_prefetch)
7347 + sprintf (buffer, "get_ilong_prefetch(%d)", r);
7348 + else
7349 + sprintf (buffer, "get_ilong(%d)", r);
7350 + return buffer;
7351 +}
7352 +
7353 +static const char *gen_nextiword (void)
7354 +{
7355 + static char buffer[80];
7356 + int r = m68k_pc_offset;
7357 +
7358 + if (!nexti_no_inc)
7359 + m68k_pc_offset += 2;
7360 +
7361 + insn_n_cycles += 4;
7362 +
7363 + if (using_prefetch)
7364 + sprintf (buffer, "get_iword_prefetch(%d)", r);
7365 + else
7366 + sprintf (buffer, "get_iword(%d)", r);
7367 + return buffer;
7368 +}
7369 +
7370 +static const char *gen_nextibyte (void)
7371 +{
7372 + static char buffer[80];
7373 + int r = m68k_pc_offset;
7374 + m68k_pc_offset += 2;
7375 +
7376 + insn_n_cycles += 4;
7377 +
7378 + if (using_prefetch)
7379 + sprintf (buffer, "get_ibyte_prefetch(%d)", r);
7380 + else
7381 + sprintf (buffer, "get_ibyte(%d)", r);
7382 + return buffer;
7383 +}
7384 +
7385 +static void fill_prefetch_0 (void)
7386 +{
7387 + if (using_prefetch)
7388 + printf ("fill_prefetch_0 ();\n");
7389 +}
7390 +
7391 +static void fill_prefetch_2 (void)
7392 +{
7393 + if (using_prefetch)
7394 + printf ("fill_prefetch_2 ();\n");
7395 +}
7396 +
7397 +static void sync_m68k_pc (void)
7398 +{
7399 + if (m68k_pc_offset == 0)
7400 + return;
7401 + printf ("m68k_incpc(%d);\n", m68k_pc_offset);
7402 + switch (m68k_pc_offset) {
7403 + case 0:
7404 + /*write_log ("refilling prefetch at 0\n"); */
7405 + break;
7406 + case 2:
7407 + fill_prefetch_2 ();
7408 + break;
7409 + default:
7410 + fill_prefetch_0 ();
7411 + break;
7412 + }
7413 + m68k_pc_offset = 0;
7414 +}
7415 +
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)
7420 +
7421 +{
7422 +
7423 + if (!using_mmu)
7424 + xlateflag = XLATE_PHYS;
7425 +
7426 + start_brace ();
7427 + switch (mode) {
7428 + case Dreg:
7429 + if (movem)
7430 + abort ();
7431 + if (getv == GENA_GETV_FETCH)
7432 + switch (size) {
7433 + case sz_byte:
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);
7438 +#else
7439 + printf ("\tuae_s8 %s = m68k_dreg(regs, %s);\n", name, reg);
7440 +#endif
7441 + break;
7442 + case sz_word:
7443 +#if defined(AMIGA) && !defined(WARPUP)
7444 + printf ("\tuae_s16 %s = ((uae_s16*)&m68k_dreg(regs, %s))[1];\n", name, reg);
7445 +#else
7446 + printf ("\tuae_s16 %s = m68k_dreg(regs, %s);\n", name, reg);
7447 +#endif
7448 + break;
7449 + case sz_long:
7450 + printf ("\tuae_s32 %s = m68k_dreg(regs, %s);\n", name, reg);
7451 + break;
7452 + default:
7453 + abort ();
7454 + }
7455 + return;
7456 + case Areg:
7457 + if (movem)
7458 + abort ();
7459 + if (getv == GENA_GETV_FETCH)
7460 + switch (size) {
7461 + case sz_word:
7462 + printf ("\tuae_s16 %s = m68k_areg(regs, %s);\n", name, reg);
7463 + break;
7464 + case sz_long:
7465 + printf ("\tuae_s32 %s = m68k_areg(regs, %s);\n", name, reg);
7466 + break;
7467 + default:
7468 + abort ();
7469 + }
7470 + return;
7471 + case Aind:
7472 + printf ("\tuaecptr %sa = m68k_areg(regs, %s);\n", name, reg);
7473 + break;
7474 + case Aipi:
7475 + printf ("\tuaecptr %sa = m68k_areg(regs, %s);\n", name, reg);
7476 + break;
7477 + case Apdi:
7478 + insn_n_cycles += 2;
7479 + switch (size) {
7480 + case sz_byte:
7481 + if (movem)
7482 + printf ("\tuaecptr %sa = m68k_areg(regs, %s);\n", name, reg);
7483 + else
7484 + printf ("\tuaecptr %sa = m68k_areg(regs, %s) - areg_byteinc[%s];\n", name, reg, reg);
7485 + break;
7486 + case sz_word:
7487 + printf ("\tuaecptr %sa = m68k_areg(regs, %s) - %d;\n", name, reg, movem ? 0 : 2);
7488 + break;
7489 + case sz_long:
7490 + printf ("\tuaecptr %sa = m68k_areg(regs, %s) - %d;\n", name, reg, movem ? 0 : 4);
7491 + break;
7492 + default:
7493 + abort ();
7494 + }
7495 + break;
7496 + case Ad16:
7497 + printf ("\tuaecptr %sa = m68k_areg(regs, %s) + (uae_s32)(uae_s16)%s;\n", name, reg, gen_nextiword ());
7498 + break;
7499 + case Ad8r:
7500 + insn_n_cycles += 2;
7501 + if (cpu_level > 1) {
7502 + if (next_cpu_level < 1)
7503 + next_cpu_level = 1;
7504 + sync_m68k_pc ();
7505 + start_brace ();
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);
7509 + } else
7510 + printf ("\tuaecptr %sa = get_disp_ea_000(m68k_areg(regs, %s), %s);\n", name, reg, gen_nextiword ());
7511 +
7512 + break;
7513 + case PC16:
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 ());
7516 + break;
7517 + case PC8r:
7518 + insn_n_cycles += 2;
7519 + if (cpu_level > 1) {
7520 + if (next_cpu_level < 1)
7521 + next_cpu_level = 1;
7522 + sync_m68k_pc ();
7523 + start_brace ();
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);
7528 + } else {
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 ());
7531 + }
7532 +
7533 + break;
7534 + case absw:
7535 + printf ("\tuaecptr %sa = (uae_s32)(uae_s16)%s;\n", name, gen_nextiword ());
7536 + break;
7537 + case absl:
7538 + printf ("\tuaecptr %sa = %s;\n", name, gen_nextilong ());
7539 + break;
7540 + case imm:
7541 + if (getv != GENA_GETV_FETCH)
7542 + abort ();
7543 + switch (size) {
7544 + case sz_byte:
7545 + printf ("\tuae_s8 %s = %s;\n", name, gen_nextibyte ());
7546 + break;
7547 + case sz_word:
7548 + printf ("\tuae_s16 %s = %s;\n", name, gen_nextiword ());
7549 + break;
7550 + case sz_long:
7551 + printf ("\tuae_s32 %s = %s;\n", name, gen_nextilong ());
7552 + break;
7553 + default:
7554 + abort ();
7555 + }
7556 + return;
7557 + case imm0:
7558 + if (getv != GENA_GETV_FETCH)
7559 + abort ();
7560 + printf ("\tuae_s8 %s = %s;\n", name, gen_nextibyte ());
7561 + return;
7562 + case imm1:
7563 + if (getv != GENA_GETV_FETCH)
7564 + abort ();
7565 + printf ("\tuae_s16 %s = %s;\n", name, gen_nextiword ());
7566 + return;
7567 + case imm2:
7568 + if (getv != GENA_GETV_FETCH)
7569 + abort ();
7570 + printf ("\tuae_s32 %s = %s;\n", name, gen_nextilong ());
7571 + return;
7572 + case immi:
7573 + if (getv != GENA_GETV_FETCH)
7574 + abort ();
7575 + printf ("\tuae_u32 %s = %s;\n", name, reg);
7576 + return;
7577 + default:
7578 + abort ();
7579 + }
7580 +
7581 + /* We get here for all non-reg non-immediate addressing modes to
7582 + * actually fetch the value. */
7583 +
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);
7591 + printf ("\t}\n");
7592 + need_endlabel = 1;
7593 + start_brace ();
7594 + }
7595 +
7596 + if (getv == GENA_GETV_FETCH) {
7597 + switch (size) {
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 ();
7602 + }
7603 + start_brace ();
7604 + switch (size) {
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 ();
7609 + }
7610 + }
7611 +
7612 + /* We now might have to fix up the register for pre-dec or post-inc
7613 + * addressing modes. */
7614 + if (!movem)
7615 + switch (mode) {
7616 + case Aipi:
7617 + switch (size) {
7618 + case sz_byte:
7619 + printf ("\tm68k_areg(regs, %s) += areg_byteinc[%s];\n", reg, reg);
7620 + break;
7621 + case sz_word:
7622 + printf ("\tm68k_areg(regs, %s) += 2;\n", reg);
7623 + break;
7624 + case sz_long:
7625 + printf ("\tm68k_areg(regs, %s) += 4;\n", reg);
7626 + break;
7627 + default:
7628 + abort ();
7629 + }
7630 + break;
7631 + case Apdi:
7632 + printf ("\tm68k_areg (regs, %s) = %sa;\n", reg, name);
7633 + break;
7634 + default:
7635 + break;
7636 + }
7637 +}
7638 +
7639 +static void genastore (char *from, amodes mode, char *reg, wordsizes size, char *to, int xlateflag)
7640 +{
7641 + switch (mode) {
7642 + case Dreg:
7643 + switch (size) {
7644 + case sz_byte:
7645 + printf ("\tm68k_dreg(regs, %s) = (m68k_dreg(regs, %s) & ~0xff) | ((%s) & 0xff);\n", reg, reg, from);
7646 + break;
7647 + case sz_word:
7648 + printf ("\tm68k_dreg(regs, %s) = (m68k_dreg(regs, %s) & ~0xffff) | ((%s) & 0xffff);\n", reg, reg, from);
7649 + break;
7650 + case sz_long:
7651 + printf ("\tm68k_dreg(regs, %s) = (%s);\n", reg, from);
7652 + break;
7653 + default:
7654 + abort ();
7655 + }
7656 + break;
7657 + case Areg:
7658 + switch (size) {
7659 + case sz_word:
7660 + write_log ("Foo\n");
7661 + printf ("\tm68k_areg(regs, %s) = (uae_s32)(uae_s16)(%s);\n", reg, from);
7662 + break;
7663 + case sz_long:
7664 + printf ("\tm68k_areg(regs, %s) = (%s);\n", reg, from);
7665 + break;
7666 + default:
7667 + abort ();
7668 + }
7669 + break;
7670 + case Aind:
7671 + case Aipi:
7672 + case Apdi:
7673 + case Ad16:
7674 + case Ad8r:
7675 + case absw:
7676 + case absl:
7677 + case PC16:
7678 + case PC8r:
7679 + if (using_prefetch)
7680 + sync_m68k_pc ();
7681 + switch (size) {
7682 + case sz_byte:
7683 + insn_n_cycles += 4;
7684 + printf ("\t%sput_byte(%sa,%s);\n", mem_prefix[xlateflag], to, from);
7685 + break;
7686 + case sz_word:
7687 + insn_n_cycles += 4;
7688 + if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
7689 + abort ();
7690 + printf ("\t%sput_word(%sa,%s);\n", mem_prefix[xlateflag], to, from);
7691 + break;
7692 + case sz_long:
7693 + insn_n_cycles += 8;
7694 + if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
7695 + abort ();
7696 + printf ("\t%sput_long(%sa,%s);\n", mem_prefix[xlateflag], to, from);
7697 + break;
7698 + default:
7699 + abort ();
7700 + }
7701 + break;
7702 + case imm:
7703 + case imm0:
7704 + case imm1:
7705 + case imm2:
7706 + case immi:
7707 + abort ();
7708 + break;
7709 + default:
7710 + abort ();
7711 + }
7712 +}
7713 +
7714 +static void genmovemel (uae_u16 opcode)
7715 +{
7716 + char getcode[100];
7717 + int size = table68k[opcode].size == sz_long ? 4 : 2;
7718 + int xlateflag = using_mmu ? XLATE_LOG : XLATE_PHYS;
7719 +
7720 + if (table68k[opcode].size == sz_long) {
7721 + strcpy (getcode, mem_prefix[xlateflag]);
7722 + strcat (getcode, "get_long(srca)");
7723 + } else {
7724 + strcpy (getcode, "(uae_s32)(uae_s16)");
7725 + strcat (getcode, mem_prefix[xlateflag]);
7726 + strcat (getcode, "get_word(srca)");
7727 + }
7728 +
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);
7732 + start_brace ();
7733 + printf ("\twhile (dmask) { m68k_dreg(regs, movem_index1[dmask]) = %s; srca += %d; dmask = movem_next[dmask]; }\n",
7734 + getcode, size);
7735 + printf ("\twhile (amask) { m68k_areg(regs, movem_index1[amask]) = %s; srca += %d; amask = movem_next[amask]; }\n",
7736 + getcode, size);
7737 +
7738 + if (table68k[opcode].dmode == Aipi)
7739 + printf ("\tm68k_areg(regs, dstreg) = srca;\n");
7740 +}
7741 +
7742 +static void genmovemle (uae_u16 opcode)
7743 +{
7744 + char putcode[100];
7745 + int size = table68k[opcode].size == sz_long ? 4 : 2;
7746 + int noxlate = using_mmu ? XLATE_LOG : XLATE_PHYS;
7747 +
7748 + strcpy(putcode, mem_prefix[noxlate]);
7749 +
7750 + if (table68k[opcode].size == sz_long) {
7751 + strcat (putcode, "put_long(srca,");
7752 + } else {
7753 + strcat (putcode, "put_word(srca,");
7754 + }
7755 +
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)
7760 + sync_m68k_pc ();
7761 +
7762 + start_brace ();
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",
7766 + size, putcode);
7767 + printf ("\twhile (dmask) { srca -= %d; %s m68k_dreg(regs, movem_index2[dmask])); dmask = movem_next[dmask]; }\n",
7768 + size, putcode);
7769 + printf ("\tm68k_areg(regs, dstreg) = srca;\n");
7770 + } else {
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",
7773 + putcode, size);
7774 + printf ("\twhile (amask) { %s m68k_areg(regs, movem_index1[amask])); srca += %d; amask = movem_next[amask]; }\n",
7775 + putcode, size);
7776 + }
7777 +}
7778 +
7779 +static void duplicate_carry (void)
7780 +{
7781 + printf ("\tCOPY_CARRY;\n");
7782 +}
7783 +
7784 +typedef enum
7785 +{
7786 + flag_logical_noclobber, flag_logical, flag_add, flag_sub, flag_cmp, flag_addx, flag_subx, flag_zn,
7787 + flag_av, flag_sv
7788 +}
7789 +flagtypes;
7790 +
7791 +static void genflags_normal (flagtypes type, wordsizes size, char *value, char *src, char *dst)
7792 +{
7793 + char vstr[100], sstr[100], dstr[100];
7794 + char usstr[100], udstr[100];
7795 + char unsstr[100], undstr[100];
7796 +
7797 + switch (size) {
7798 + case sz_byte:
7799 + strcpy (vstr, "((uae_s8)(");
7800 + strcpy (usstr, "((uae_u8)(");
7801 + break;
7802 + case sz_word:
7803 + strcpy (vstr, "((uae_s16)(");
7804 + strcpy (usstr, "((uae_u16)(");
7805 + break;
7806 + case sz_long:
7807 + strcpy (vstr, "((uae_s32)(");
7808 + strcpy (usstr, "((uae_u32)(");
7809 + break;
7810 + default:
7811 + abort ();
7812 + }
7813 + strcpy (unsstr, usstr);
7814 +
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, "))");
7823 +
7824 + strcpy (udstr, usstr);
7825 + strcat (udstr, dst);
7826 + strcat (udstr, "))");
7827 + strcat (usstr, src);
7828 + strcat (usstr, "))");
7829 +
7830 + strcpy (undstr, unsstr);
7831 + strcat (unsstr, "-");
7832 + strcat (undstr, "~");
7833 + strcat (undstr, dst);
7834 + strcat (undstr, "))");
7835 + strcat (unsstr, src);
7836 + strcat (unsstr, "))");
7837 +
7838 + switch (type) {
7839 + case flag_logical_noclobber:
7840 + case flag_logical:
7841 + case flag_zn:
7842 + case flag_av:
7843 + case flag_sv:
7844 + case flag_addx:
7845 + case flag_subx:
7846 + break;
7847 +
7848 + case flag_add:
7849 + start_brace ();
7850 + printf ("uae_u32 %s = %s + %s;\n", value, dstr, sstr);
7851 + break;
7852 + case flag_sub:
7853 + case flag_cmp:
7854 + start_brace ();
7855 + printf ("uae_u32 %s = %s - %s;\n", value, dstr, sstr);
7856 + break;
7857 + }
7858 +
7859 + switch (type) {
7860 + case flag_logical_noclobber:
7861 + case flag_logical:
7862 + case flag_zn:
7863 + break;
7864 +
7865 + case flag_add:
7866 + case flag_sub:
7867 + case flag_addx:
7868 + case flag_subx:
7869 + case flag_cmp:
7870 + case flag_av:
7871 + case flag_sv:
7872 + start_brace ();
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);
7876 + break;
7877 + }
7878 +
7879 + switch (type) {
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);
7884 + break;
7885 + case flag_logical_noclobber:
7886 + printf ("\tSET_ZFLG (%s == 0);\n", vstr);
7887 + printf ("\tSET_NFLG (%s < 0);\n", vstr);
7888 + break;
7889 + case flag_av:
7890 + printf ("\tSET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));\n");
7891 + break;
7892 + case flag_sv:
7893 + printf ("\tSET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));\n");
7894 + break;
7895 + case flag_zn:
7896 + printf ("\tSET_ZFLG (GET_ZFLG & (%s == 0));\n", vstr);
7897 + printf ("\tSET_NFLG (%s < 0);\n", vstr);
7898 + break;
7899 + case flag_add:
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");
7905 + break;
7906 + case flag_sub:
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");
7912 + break;
7913 + case flag_addx:
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 ();
7917 + break;
7918 + case flag_subx:
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 ();
7922 + break;
7923 + case flag_cmp:
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");
7928 + break;
7929 + }
7930 +}
7931 +
7932 +static void genflags (flagtypes type, wordsizes size, char *value, char *src, char *dst)
7933 +{
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
7938 + switch (type) {
7939 + case flag_add:
7940 + case flag_sub:
7941 + start_brace ();
7942 + printf ("\tuae_u32 %s;\n", value);
7943 + break;
7944 +
7945 + default:
7946 + break;
7947 + }
7948 +
7949 + /* At least some of those casts are fairly important! */
7950 + switch (type) {
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");
7955 + } else {
7956 + switch (size) {
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;
7960 + }
7961 + printf ("\tIOR_CZNV (oldcznv);\n");
7962 + }
7963 + printf ("\t}\n");
7964 + return;
7965 + case flag_logical:
7966 + if (strcmp (value, "0") == 0) {
7967 + printf ("\tSET_CZNV (FLAGVAL_Z);\n");
7968 + } else {
7969 + switch (size) {
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;
7973 + }
7974 + }
7975 + return;
7976 +
7977 + case flag_add:
7978 + switch (size) {
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;
7982 + }
7983 + return;
7984 +
7985 + case flag_sub:
7986 + switch (size) {
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;
7990 + }
7991 + return;
7992 +
7993 + case flag_cmp:
7994 + switch (size) {
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;
7998 + }
7999 + return;
8000 +
8001 + default:
8002 + break;
8003 + }
8004 +#endif
8005 +
8006 + genflags_normal (type, size, value, src, dst);
8007 +}
8008 +
8009 +static void force_range_for_rox (const char *var, wordsizes size)
8010 +{
8011 + /* Could do a modulo operation here... which one is faster? */
8012 + switch (size) {
8013 + case sz_long:
8014 + printf ("\tif (%s >= 33) %s -= 33;\n", var, var);
8015 + break;
8016 + case sz_word:
8017 + printf ("\tif (%s >= 34) %s -= 34;\n", var, var);
8018 + printf ("\tif (%s >= 17) %s -= 17;\n", var, var);
8019 + break;
8020 + case sz_byte:
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);
8024 + break;
8025 + }
8026 +}
8027 +
8028 +static const char *cmask (wordsizes size)
8029 +{
8030 + switch (size) {
8031 + case sz_byte: return "0x80";
8032 + case sz_word: return "0x8000";
8033 + case sz_long: return "0x80000000";
8034 + default: abort ();
8035 + }
8036 +}
8037 +
8038 +static int source_is_imm1_8 (struct instr *i)
8039 +{
8040 + return i->stype == 3;
8041 +}
8042 +
8043 +static void gen_opcode (unsigned long int opcode)
8044 +{
8045 + struct instr *curi = table68k + opcode;
8046 + int xlateflag = using_mmu ? XLATE_LOG : XLATE_PHYS;
8047 + insn_n_cycles = 4;
8048 +
8049 + start_brace ();
8050 +#if 0
8051 + printf ("uae_u8 *m68k_pc = regs.pc_p;\n");
8052 +#endif
8053 + m68k_pc_offset = 2;
8054 + switch (curi->plev) {
8055 + case 0: /* not privileged */
8056 + break;
8057 + case 1: /* unprivileged only on 68000 */
8058 + if (cpu_level == 0)
8059 + break;
8060 + if (next_cpu_level < 0)
8061 + next_cpu_level = 0;
8062 +
8063 + /* fall through */
8064 + case 2: /* priviledged */
8065 + printf ("if (!regs.s) { Exception(8,0); goto %s; }\n", endlabelstr);
8066 + need_endlabel = 1;
8067 + start_brace ();
8068 + break;
8069 + case 3: /* privileged if size == word */
8070 + if (curi->size == sz_byte)
8071 + break;
8072 + printf ("if (!regs.s) { Exception(8,0); goto %s; }\n", endlabelstr);
8073 + need_endlabel = 1;
8074 + start_brace ();
8075 + break;
8076 + }
8077 + switch (curi->mnemo) {
8078 + case i_OR:
8079 + case i_AND:
8080 + case i_EOR:
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);
8086 + break;
8087 + case i_ORSR:
8088 + case i_EORSR:
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");
8093 + }
8094 + printf ("\tregs.sr %c= src;\n", curi->mnemo == i_EORSR ? '^' : '|');
8095 + printf ("\tMakeFromSR();\n");
8096 + break;
8097 + case i_ANDSR:
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");
8102 + }
8103 + printf ("\tregs.sr &= src;\n");
8104 + printf ("\tMakeFromSR();\n");
8105 + break;
8106 + case i_SUB:
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);
8109 + start_brace ();
8110 + genflags (flag_sub, curi->size, "newv", "src", "dst");
8111 + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
8112 + break;
8113 + case i_SUBA:
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);
8116 + start_brace ();
8117 + printf ("\tuae_u32 newv = dst - src;\n");
8118 + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", xlateflag);
8119 + break;
8120 + case i_SUBX:
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);
8123 + start_brace ();
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);
8128 + break;
8129 + case i_SBCD:
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);
8132 + start_brace ();
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);
8145 + break;
8146 + case i_ADD:
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);
8149 + start_brace ();
8150 + genflags (flag_add, curi->size, "newv", "src", "dst");
8151 + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
8152 + break;
8153 + case i_ADDA:
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);
8156 + start_brace ();
8157 + printf ("\tuae_u32 newv = dst + src;\n");
8158 + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", xlateflag);
8159 + break;
8160 + case i_ADDX:
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);
8163 + start_brace ();
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);
8168 + break;
8169 + case i_ABCD:
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);
8172 + start_brace ();
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);
8186 + break;
8187 + case i_NEG:
8188 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8189 + start_brace ();
8190 + genflags (flag_sub, curi->size, "dst", "src", "0");
8191 + genastore ("dst", curi->smode, "srcreg", curi->size, "src", xlateflag);
8192 + break;
8193 + case i_NEGX:
8194 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8195 + start_brace ();
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);
8200 + break;
8201 + case i_NBCD:
8202 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8203 + start_brace ();
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);
8216 + break;
8217 + case i_CLR:
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);
8221 + break;
8222 + case i_NOT:
8223 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8224 + start_brace ();
8225 + printf ("\tuae_u32 dst = ~src;\n");
8226 + genflags (flag_logical, curi->size, "dst", "", "");
8227 + genastore ("dst", curi->smode, "srcreg", curi->size, "src", xlateflag);
8228 + break;
8229 + case i_TST:
8230 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8231 + genflags (flag_logical, curi->size, "src", "", "");
8232 + break;
8233 + case i_BTST:
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");
8238 + else
8239 + printf ("\tsrc &= 31;\n");
8240 + printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n");
8241 + break;
8242 + case i_BCHG:
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");
8247 + else
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);
8252 + break;
8253 + case i_BCLR:
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");
8258 + else
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);
8263 + break;
8264 + case i_BSET:
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");
8269 + else
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);
8274 + break;
8275 + case i_CMPM:
8276 + case i_CMP:
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);
8279 + start_brace ();
8280 + genflags (flag_cmp, curi->size, "newv", "src", "dst");
8281 + break;
8282 + case i_CMPA:
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);
8285 + start_brace ();
8286 + genflags (flag_cmp, sz_long, "newv", "src", "dst");
8287 + break;
8288 + /* The next two are coded a little unconventional, but they are doing
8289 + * weird things... */
8290 + case i_MVPRM:
8291 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8292 +
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");
8296 + } else {
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");
8299 + }
8300 + break;
8301 + case i_MVPMR:
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");
8306 + } else {
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");
8309 + }
8310 + genastore ("val", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
8311 + break;
8312 + case i_MOVE:
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);
8317 + break;
8318 + case i_MOVEA:
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");
8323 + } else {
8324 + printf ("\tuae_u32 val = src;\n");
8325 + }
8326 + genastore ("val", curi->dmode, "dstreg", sz_long, "dst", xlateflag);
8327 + break;
8328 + case i_MVSR2:
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);
8333 + else
8334 + genastore ("regs.sr", curi->smode, "srcreg", sz_word, "src", xlateflag);
8335 + break;
8336 + case i_MV2SR:
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");
8340 + else {
8341 + printf ("\tregs.sr = src;\n");
8342 + }
8343 + printf ("\tMakeFromSR();\n");
8344 + break;
8345 + case i_SWAP:
8346 + genamode (curi->smode, "srcreg", sz_long, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8347 + start_brace ();
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);
8351 + break;
8352 + case i_EXG:
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);
8357 + break;
8358 + case i_EXT:
8359 + genamode (curi->smode, "srcreg", sz_long, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8360 + start_brace ();
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 ();
8366 + }
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);
8371 + break;
8372 + case i_MVMEL:
8373 + genmovemel (opcode);
8374 + break;
8375 + case i_MVMLE:
8376 + genmovemle (opcode);
8377 + break;
8378 + case i_TRAP:
8379 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8380 + sync_m68k_pc ();
8381 + printf ("\tException(src+32,0);\n");
8382 + m68k_pc_offset = 0;
8383 + break;
8384 + case i_MVR2USP:
8385 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8386 + printf ("\tregs.usp = src;\n");
8387 + break;
8388 + case i_MVUSP2R:
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);
8391 + break;
8392 + case i_RESET:
8393 + printf ("\tcustomreset();\n");
8394 + break;
8395 + case i_NOP:
8396 + break;
8397 + case i_STOP:
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");
8402 + break;
8403 + case i_RTE:
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");
8410 + } else {
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;
8434 + }
8435 + /* PC is set and prefetch filled. */
8436 + m68k_pc_offset = 0;
8437 + break;
8438 + case i_RTD:
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;
8447 + break;
8448 + case i_LINK:
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");
8455 + break;
8456 + case i_UNLK:
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);
8461 + break;
8462 + case i_RTS:
8463 + printf ("\tm68k_do_rts();\n");
8464 + fill_prefetch_0 ();
8465 + m68k_pc_offset = 0;
8466 + break;
8467 + case i_TRAPV:
8468 + sync_m68k_pc ();
8469 + printf ("\tif (GET_VFLG) { Exception(7,m68k_getpc()); goto %s; }\n", endlabelstr);
8470 + need_endlabel = 1;
8471 + break;
8472 + case i_RTR:
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;
8482 + break;
8483 + case i_JSR:
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;
8488 + break;
8489 + case i_JMP:
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;
8494 + break;
8495 + case i_BSR:
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);
8503 + printf ("\t}\n");
8504 + need_endlabel = 1;
8505 + }
8506 + printf ("\tm68k_do_bsr(m68k_getpc() + %d, s);\n", m68k_pc_offset);
8507 + fill_prefetch_0 ();
8508 + m68k_pc_offset = 0;
8509 + break;
8510 + case i_Bcc:
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;
8519 + } else {
8520 + if (next_cpu_level < 1)
8521 + next_cpu_level = 1;
8522 + }
8523 + }
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);
8531 + printf ("\t}\n");
8532 + need_endlabel = 1;
8533 + }
8534 +#ifdef USE_COMPILER
8535 + printf ("\tm68k_setpc_bcc(m68k_getpc() + 2 + (uae_s32)src);\n");
8536 +#else
8537 + printf ("\tm68k_incpc ((uae_s32)src + 2);\n");
8538 +#endif
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;
8544 + break;
8545 + case i_LEA:
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);
8549 + break;
8550 + case i_PEA:
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);
8554 + break;
8555 + case i_DBcc:
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);
8558 +
8559 + printf ("\tif (!cctrue(%d)) {\n", curi->cc);
8560 + genastore ("(src-1)", curi->smode, "srcreg", curi->size, "src", xlateflag);
8561 +
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;
8570 + }
8571 +#ifdef USE_COMPILER
8572 + printf ("\t\t\tm68k_setpc_bcc(m68k_getpc() + (uae_s32)offs + 2);\n");
8573 +#else
8574 + printf ("\t\t\tm68k_incpc((uae_s32)offs + 2);\n");
8575 +#endif
8576 + fill_prefetch_0 ();
8577 + /* ??? Cycle count is a guess. */
8578 + printf ("\t\treturn 6 * CYCLE_UNIT;\n");
8579 + printf ("\t\t}\n");
8580 + printf ("\t}\n");
8581 + insn_n_cycles = 12;
8582 + need_endlabel = 1;
8583 + break;
8584 + case i_Scc:
8585 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG);
8586 + start_brace ();
8587 + printf ("\tint val = cctrue(%d) ? 0xff : 0;\n", curi->cc);
8588 + genastore ("val", curi->smode, "srcreg", curi->size, "src", xlateflag);
8589 + break;
8590 + case i_DIVU:
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);
8594 + sync_m68k_pc ();
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.
8601 + * Weird. */
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);
8606 + printf ("\t}\n");
8607 + printf ("\t}\n");
8608 + insn_n_cycles += 136;
8609 + need_endlabel = 1;
8610 + break;
8611 + case i_DIVS:
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);
8615 + sync_m68k_pc ();
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);
8624 + printf ("\t}\n");
8625 + printf ("\t}\n");
8626 + insn_n_cycles += 154;
8627 + need_endlabel = 1;
8628 + break;
8629 + case i_MULU:
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);
8632 + start_brace ();
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;
8637 + break;
8638 + case i_MULS:
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);
8641 + start_brace ();
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;
8646 + break;
8647 + case i_CHK:
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;
8654 + break;
8655 +
8656 + case i_CHK2:
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) {
8662 + case sz_byte:
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");
8665 + break;
8666 + case sz_word:
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");
8669 + break;
8670 + case sz_long:
8671 + printf ("\tlower=get_long(dsta); upper = get_long(dsta+4);\n");
8672 + break;
8673 + default:
8674 + abort ();
8675 + }
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;
8680 + break;
8681 +
8682 + case i_ASR:
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);
8685 + start_brace ();
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 ();
8691 + }
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");
8701 + else
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));
8711 + printf ("\t}\n");
8712 + genflags (flag_logical_noclobber, curi->size, "val", "", "");
8713 + genastore ("val", curi->dmode, "dstreg", curi->size, "data", xlateflag);
8714 + break;
8715 + case i_ASL:
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);
8718 + start_brace ();
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 ();
8724 + }
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");
8735 + else
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));
8747 + printf ("\t}\n");
8748 + genflags (flag_logical_noclobber, curi->size, "val", "", "");
8749 + genastore ("val", curi->dmode, "dstreg", curi->size, "data", xlateflag);
8750 + break;
8751 + case i_LSR:
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);
8754 + start_brace ();
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 ();
8760 + }
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");
8770 + else
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");
8776 + printf ("\t}\n");
8777 + genflags (flag_logical_noclobber, curi->size, "val", "", "");
8778 + genastore ("val", curi->dmode, "dstreg", curi->size, "data", xlateflag);
8779 + break;
8780 + case i_LSL:
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);
8783 + start_brace ();
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 ();
8789 + }
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");
8799 + else
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));
8806 + printf ("\t}\n");
8807 + genflags (flag_logical_noclobber, curi->size, "val", "", "");
8808 + genastore ("val", curi->dmode, "dstreg", curi->size, "data", xlateflag);
8809 + break;
8810 + case i_ROL:
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);
8813 + start_brace ();
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 ();
8819 + }
8820 + printf ("\tcnt &= 63;\n");
8821 + printf ("\tCLEAR_CZNV;\n");
8822 + if (source_is_imm1_8 (curi))
8823 + printf ("{");
8824 + else
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");
8833 + printf ("}\n");
8834 + genflags (flag_logical_noclobber, curi->size, "val", "", "");
8835 + genastore ("val", curi->dmode, "dstreg", curi->size, "data", xlateflag);
8836 + break;
8837 + case i_ROR:
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);
8840 + start_brace ();
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 ();
8846 + }
8847 + printf ("\tcnt &= 63;\n");
8848 + printf ("\tCLEAR_CZNV;\n");
8849 + if (source_is_imm1_8 (curi))
8850 + printf ("{");
8851 + else
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);
8860 + printf ("\t}\n");
8861 + genflags (flag_logical_noclobber, curi->size, "val", "", "");
8862 + genastore ("val", curi->dmode, "dstreg", curi->size, "data", xlateflag);
8863 + break;
8864 + case i_ROXL:
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);
8867 + start_brace ();
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 ();
8873 + }
8874 + printf ("\tcnt &= 63;\n");
8875 + printf ("\tCLEAR_CZNV;\n");
8876 + if (source_is_imm1_8 (curi))
8877 + printf ("{");
8878 + else {
8879 + force_range_for_rox ("cnt", curi->size);
8880 + printf ("\tif (cnt > 0) {\n");
8881 + }
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);
8893 + break;
8894 + case i_ROXR:
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);
8897 + start_brace ();
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 ();
8903 + }
8904 + printf ("\tcnt &= 63;\n");
8905 + printf ("\tCLEAR_CZNV;\n");
8906 + if (source_is_imm1_8 (curi))
8907 + printf ("{");
8908 + else {
8909 + force_range_for_rox ("cnt", curi->size);
8910 + printf ("\tif (cnt > 0) {\n");
8911 + }
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);
8926 + break;
8927 + case i_ASRW:
8928 + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8929 + start_brace ();
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 ();
8935 + }
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);
8943 + break;
8944 + case i_ASLW:
8945 + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8946 + start_brace ();
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 ();
8952 + }
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 ();
8960 +
8961 + printf ("\tSET_VFLG (GET_VFLG | (sign2 != sign));\n");
8962 + genastore ("val", curi->smode, "srcreg", curi->size, "data", xlateflag);
8963 + break;
8964 + case i_LSRW:
8965 + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8966 + start_brace ();
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 ();
8972 + }
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);
8979 + break;
8980 + case i_LSLW:
8981 + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8982 + start_brace ();
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 ();
8988 + }
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);
8995 + break;
8996 + case i_ROLW:
8997 + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
8998 + start_brace ();
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 ();
9004 + }
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);
9011 + break;
9012 + case i_RORW:
9013 + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9014 + start_brace ();
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 ();
9020 + }
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);
9027 + break;
9028 + case i_ROXLW:
9029 + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9030 + start_brace ();
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 ();
9036 + }
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);
9044 + break;
9045 + case i_ROXRW:
9046 + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9047 + start_brace ();
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 ();
9053 + }
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);
9061 + break;
9062 + case i_MOVEC2:
9063 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9064 + start_brace ();
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);
9068 + break;
9069 + case i_MOVE2C:
9070 + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9071 + start_brace ();
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);
9075 + break;
9076 + case i_CAS:
9077 + {
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);
9081 + start_brace ();
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;
9087 + start_brace ();
9088 + genastore ("(m68k_dreg(regs, ru))", curi->dmode, "dstreg", curi->size, "dst", xlateflag);
9089 + pop_braces (old_brace_level);
9090 + printf ("else");
9091 + start_brace ();
9092 + printf ("m68k_dreg(regs, rc) = dst;\n");
9093 + pop_braces (old_brace_level);
9094 + }
9095 + break;
9096 + case i_CAS2:
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");
9114 + printf ("\t}\n");
9115 + } else {
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");
9129 + printf ("\t}\n");
9130 + }
9131 + break;
9132 + case i_MOVES:
9133 + {
9134 + int old_brace_level;
9135 +
9136 + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9137 + start_brace();
9138 + printf ("\tif (extra & 0x0800)\n"); /* from reg to ea */
9139 + {
9140 + /* use DFC */
9141 + old_brace_level = n_braces;
9142 + start_brace ();
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);
9146 + nexti_no_inc = 0;
9147 + genastore ("src", curi->dmode, "dstreg", curi->size, "dst", XLATE_DFC);
9148 + pop_braces (old_brace_level);
9149 + }
9150 + printf ("else"); /* from ea to reg */
9151 + {
9152 + /* use SFC */
9153 + start_brace ();
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 ();
9161 + }
9162 + printf ("\t} else {\n");
9163 + genastore ("src", Dreg, "(extra >> 12) & 7", curi->size, "", XLATE_LOG);
9164 + printf ("\t}\n");
9165 + pop_braces (old_brace_level);
9166 + }
9167 + }
9168 + break;
9169 + case i_BKPT: /* only needed for hardware emulators */
9170 + sync_m68k_pc ();
9171 + printf ("\top_illg(opcode);\n");
9172 + break;
9173 + case i_CALLM: /* not present in 68030 */
9174 + sync_m68k_pc ();
9175 + printf ("\top_illg(opcode);\n");
9176 + break;
9177 + case i_RTM: /* not present in 68030 */
9178 + sync_m68k_pc ();
9179 + printf ("\top_illg(opcode);\n");
9180 + break;
9181 + case i_TRAPcc:
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;
9186 + break;
9187 + case i_DIVL:
9188 + sync_m68k_pc ();
9189 + start_brace ();
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);
9193 + sync_m68k_pc ();
9194 + printf ("\tm68k_divl(opcode, dst, extra, oldpc);\n");
9195 + break;
9196 + case i_MULL:
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);
9199 + sync_m68k_pc ();
9200 + printf ("\tm68k_mull(opcode, dst, extra);\n");
9201 + break;
9202 + case i_BFTST:
9203 + case i_BFEXTU:
9204 + case i_BFCHG:
9205 + case i_BFEXTS:
9206 + case i_BFCLR:
9207 + case i_BFFFO:
9208 + case i_BFSET:
9209 + case i_BFINS:
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);
9212 + start_brace ();
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");
9217 + } else {
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");
9222 + }
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) {
9227 + case i_BFTST:
9228 + break;
9229 + case i_BFEXTU:
9230 + printf ("\tm68k_dreg(regs, (extra >> 12) & 7) = tmp;\n");
9231 + break;
9232 + case i_BFCHG:
9233 + printf ("\ttmp = ~tmp;\n");
9234 + break;
9235 + case i_BFEXTS:
9236 + printf ("\tif (GET_NFLG) tmp |= width == 32 ? 0 : (-1 << width);\n");
9237 + printf ("\tm68k_dreg(regs, (extra >> 12) & 7) = tmp;\n");
9238 + break;
9239 + case i_BFCLR:
9240 + printf ("\ttmp = 0;\n");
9241 + break;
9242 + case i_BFFFO:
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");
9246 + break;
9247 + case i_BFSET:
9248 + printf ("\ttmp = 0xffffffff;\n");
9249 + break;
9250 + case i_BFINS:
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");
9254 + break;
9255 + default:
9256 + break;
9257 + }
9258 + if (curi->mnemo == i_BFCHG
9259 + || curi->mnemo == i_BFCLR
9260 + || curi->mnemo == i_BFSET
9261 + || curi->mnemo == i_BFINS)
9262 + {
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");
9270 + } else {
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");
9280 + printf ("\t}\n");
9281 + }
9282 + }
9283 + break;
9284 + case i_PACK:
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");
9288 + } else {
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");
9296 + }
9297 + break;
9298 + case i_UNPK:
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");
9303 + } else {
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");
9312 + }
9313 + break;
9314 + case i_TAS:
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);
9319 + break;
9320 + case i_FPP:
9321 + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9322 + sync_m68k_pc ();
9323 + printf ("\tfpp_opp(opcode,extra);\n");
9324 + break;
9325 + case i_FDBcc:
9326 + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9327 + sync_m68k_pc ();
9328 + printf ("\tfdbcc_opp(opcode,extra);\n");
9329 + break;
9330 + case i_FScc:
9331 + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9332 + sync_m68k_pc ();
9333 + printf ("\tfscc_opp(opcode,extra);\n");
9334 + break;
9335 + case i_FTRAPcc:
9336 + sync_m68k_pc ();
9337 + start_brace ();
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);
9341 + sync_m68k_pc ();
9342 + printf ("\tftrapcc_opp(opcode,oldpc);\n");
9343 + break;
9344 + case i_FBcc:
9345 + sync_m68k_pc ();
9346 + start_brace ();
9347 + printf ("\tuaecptr pc = m68k_getpc();\n");
9348 + genamode (curi->dmode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9349 + sync_m68k_pc ();
9350 + printf ("\tfbcc_opp(opcode,pc,extra);\n");
9351 + break;
9352 + case i_FSAVE:
9353 + sync_m68k_pc ();
9354 + printf ("\tfsave_opp(opcode);\n");
9355 + break;
9356 + case i_FRESTORE:
9357 + sync_m68k_pc ();
9358 + printf ("\tfrestore_opp(opcode);\n");
9359 + break;
9360 +
9361 + case i_CINVL:
9362 + case i_CINVP:
9363 + case i_CINVA:
9364 + case i_CPUSHL:
9365 + case i_CPUSHP:
9366 + case i_CPUSHA:
9367 + break;
9368 + case i_MOVE16:
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");
9381 + } else {
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");
9395 + }
9396 + break;
9397 +
9398 + case i_MMUOP:
9399 + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG);
9400 + sync_m68k_pc ();
9401 + printf ("\tmmu_op(opcode,extra);\n");
9402 + break;
9403 + default:
9404 + abort ();
9405 + break;
9406 + }
9407 + finish_braces ();
9408 + sync_m68k_pc ();
9409 +}
9410 +
9411 +static void generate_includes (FILE * f)
9412 +{
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");
9422 +
9423 + fprintf (f, "#define CPUFUNC(x) x##_ff\n"
9424 + "#ifdef NOFLAGS\n"
9425 + "#include \"noflags.h\"\n"
9426 + "#endif\n");
9427 +}
9428 +
9429 +static int postfix;
9430 +
9431 +static void generate_one_opcode (int rp)
9432 +{
9433 + int i;
9434 + uae_u16 smsk, dmsk;
9435 + long int opcode = opcode_map[rp];
9436 +
9437 + if (table68k[opcode].mnemo == i_ILLG
9438 + || table68k[opcode].clev > cpu_level)
9439 + return;
9440 +
9441 + for (i = 0; lookuptab[i].name[0]; i++) {
9442 + if (table68k[opcode].mnemo == lookuptab[i].mnemo)
9443 + break;
9444 + }
9445 +
9446 + if (table68k[opcode].handler != -1)
9447 + return;
9448 +
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);
9452 + return;
9453 + }
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);
9458 +
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 ();
9468 + }
9469 + dmsk = 7;
9470 +
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)
9477 + {
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);
9481 + else
9482 + printf ("\tuae_u32 srcreg = %d;\n", (int) table68k[opcode].sreg);
9483 + } else {
9484 + char source[100];
9485 + int pos = table68k[opcode].spos;
9486 +
9487 + if (pos)
9488 + sprintf (source, "((opcode >> %d) & %d)", pos, smsk);
9489 + else
9490 + sprintf (source, "(opcode & %d)", smsk);
9491 +
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);
9496 + else
9497 + printf ("\tuae_u32 srcreg = %s;\n", source);
9498 + }
9499 + }
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)
9505 + {
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);
9509 + else
9510 + printf ("\tuae_u32 dstreg = %d;\n", (int) table68k[opcode].dreg);
9511 + } else {
9512 + int pos = table68k[opcode].dpos;
9513 +#if 0
9514 + /* Check that we can do the little endian optimization safely. */
9515 + if (pos < 8 && (dmsk >> (8 - pos)) != 0)
9516 + abort ();
9517 +#endif
9518 + if (pos)
9519 + printf ("\tuae_u32 dstreg = (opcode >> %d) & %d;\n",
9520 + pos, dmsk);
9521 + else
9522 + printf ("\tuae_u32 dstreg = opcode & %d;\n", dmsk);
9523 + }
9524 + }
9525 + need_endlabel = 0;
9526 + endlabelno++;
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);
9532 + printf ("}\n");
9533 + opcode_next_clev[rp] = next_cpu_level;
9534 + opcode_last_postfix[rp] = postfix;
9535 +}
9536 +
9537 +static void generate_func (void)
9538 +{
9539 + int i, j, rp;
9540 +
9541 + using_prefetch = 0;
9542 + using_exception_3 = 0;
9543 + using_mmu = 0;
9544 +
9545 + for (i = 0; i < 6; i++) {
9546 + cpu_level = 4 - i;
9547 + using_mmu = cpu_level == 4;
9548 + if (i == 5) {
9549 + cpu_level = 0;
9550 + using_prefetch = 1;
9551 + using_exception_3 = 1;
9552 + for (rp = 0; rp < nr_cpuop_funcs; rp++)
9553 + opcode_next_clev[rp] = 0;
9554 + }
9555 +
9556 + postfix = i;
9557 + fprintf (stblfile, "struct cputbl CPUFUNC(op_smalltbl_%d)[] = {\n", postfix);
9558 +
9559 + /* sam: this is for people with low memory (eg. me :)) */
9560 + printf ("\n"
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)"
9565 + "\n"
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"
9574 + "#endif\n\n");
9575 +
9576 + rp = 0;
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");
9583 + }
9584 +
9585 + fprintf (stblfile, "{ 0, 0, 0 }};\n");
9586 + }
9587 +
9588 +}
9589 +
9590 +int main (int argc, char **argv)
9591 +{
9592 + read_table68k ();
9593 + do_merges ();
9594 +
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));
9599 + read_counts ();
9600 +
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. */
9604 +
9605 + headerfile = fopen ("cputbl.h", "wb");
9606 + stblfile = fopen ("cpustbl.c", "wb");
9607 + freopen ("cpuemu.c", "wb", stdout);
9608 +
9609 + generate_includes (stdout);
9610 + generate_includes (stblfile);
9611 +
9612 + generate_func ();
9613 +
9614 + free (table68k);
9615 + return 0;
9616 +}
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
9620 @@ -149,6 +149,7 @@
9621
9622 #endif
9623
9624 +#if 0
9625 STATIC_INLINE uae_u32 get_long(uaecptr addr)
9626 {
9627 return longget_1(addr);
9628 @@ -173,13 +174,14 @@
9629 {
9630 byteput_1(addr, b);
9631 }
9632 +#endif
9633
9634 -STATIC_INLINE uae_u8 *get_real_address(uaecptr addr)
9635 +STATIC_INLINE uae_u8 *phys_get_real_address(uaecptr addr)
9636 {
9637 return get_mem_bank(addr).xlateaddr(addr);
9638 }
9639
9640 -STATIC_INLINE int valid_address(uaecptr addr, uae_u32 size)
9641 +STATIC_INLINE int phys_valid_address(uaecptr addr, uae_u32 size)
9642 {
9643 return get_mem_bank(addr).check(addr, size);
9644 }
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
9648 @@ -0,0 +1,216 @@
9649 + /*
9650 + * UAE - The Un*x Amiga Emulator
9651 + *
9652 + * memory management
9653 + *
9654 + * Copyright 1995 Bernd Schmidt
9655 + * vim:ts=8:sw=4:
9656 + */
9657 +
9658 +extern void memory_reset (void);
9659 +
9660 +extern int special_mem;
9661 +#define S_READ 1
9662 +#define S_WRITE 2
9663 +
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;
9668 +
9669 +extern char *address_space, *good_address_map;
9670 +extern uae_u8 *chipmemory;
9671 +
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;
9678 +
9679 +#undef DIRECT_MEMFUNCS_SUCCESSFUL
9680 +#include "machdep/maccess.h"
9681 +
9682 +#ifndef CAN_MAP_MEMORY
9683 +#undef USE_COMPILER
9684 +#endif
9685 +
9686 +#if defined(USE_COMPILER) && !defined(USE_MAPPED_MEMORY)
9687 +#define USE_MAPPED_MEMORY
9688 +#endif
9689 +
9690 +#define kickmem_size 0x080000
9691 +
9692 +#define chipmem_start 0x00000000
9693 +#define bogomem_start 0x00C00000
9694 +#define a3000mem_start 0x07000000
9695 +#define kickmem_start 0x00F80000
9696 +
9697 +extern int ersatzkickfile;
9698 +extern int cloanto_rom;
9699 +
9700 +extern uae_u8* baseaddr[];
9701 +
9702 +typedef struct {
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
9709 + * abort(). */
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 */
9715 + check_func check;
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. */
9720 + uae_u8 *baseaddr;
9721 +} addrbank;
9722 +
9723 +extern uae_u8 *filesysory;
9724 +extern uae_u8 *rtarea;
9725 +
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;
9735 +
9736 +extern void rtarea_init (void);
9737 +extern void rtarea_setup (void);
9738 +extern void expamem_init (void);
9739 +extern void expamem_reset (void);
9740 +
9741 +extern uae_u32 gfxmem_start;
9742 +extern uae_u8 *gfxmemory;
9743 +extern uae_u32 gfxmem_mask;
9744 +extern int address_space_24;
9745 +
9746 +/* Default memory access functions */
9747 +
9748 +extern int default_check(uaecptr addr, uae_u32 size) REGPARAM;
9749 +extern uae_u8 *default_xlate(uaecptr addr) REGPARAM;
9750 +
9751 +#define bankindex(addr) (((uaecptr)(addr)) >> 16)
9752 +
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); \
9760 + else \
9761 + baseaddr[bankindex(addr)] = (uae_u8*)(((long)b)+1); \
9762 +} while (0)
9763 +
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);
9767 +
9768 +#ifndef NO_INLINE_MEMORY_ACCESS
9769 +
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))
9776 +
9777 +#else
9778 +
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);
9787 +
9788 +#endif
9789 +
9790 +
9791 +#ifndef MD_HAVE_MEM_1_FUNCS
9792 +
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
9799 +
9800 +#endif
9801 +
9802 +#if 0
9803 +STATIC_INLINE uae_u32 get_long(uaecptr addr)
9804 +{
9805 + return longget_1(addr);
9806 +}
9807 +STATIC_INLINE uae_u32 get_word(uaecptr addr)
9808 +{
9809 + return wordget_1(addr);
9810 +}
9811 +STATIC_INLINE uae_u32 get_byte(uaecptr addr)
9812 +{
9813 + return byteget_1(addr);
9814 +}
9815 +STATIC_INLINE void put_long(uaecptr addr, uae_u32 l)
9816 +{
9817 + longput_1(addr, l);
9818 +}
9819 +STATIC_INLINE void put_word(uaecptr addr, uae_u32 w)
9820 +{
9821 + wordput_1(addr, w);
9822 +}
9823 +STATIC_INLINE void put_byte(uaecptr addr, uae_u32 b)
9824 +{
9825 + byteput_1(addr, b);
9826 +}
9827 +#endif
9828 +
9829 +STATIC_INLINE uae_u8 *phys_get_real_address(uaecptr addr)
9830 +{
9831 + return get_mem_bank(addr).xlateaddr(addr);
9832 +}
9833 +
9834 +STATIC_INLINE int phys_valid_address(uaecptr addr, uae_u32 size)
9835 +{
9836 + return get_mem_bank(addr).check(addr, size);
9837 +}
9838 +
9839 +
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;
9847 +
9848 +#ifdef NATMEM_OFFSET
9849 +
9850 +typedef struct shmpiece_reg {
9851 + uae_u8 *native_address;
9852 + int id;
9853 + uae_u32 size;
9854 + struct shmpiece_reg *next;
9855 + struct shmpiece_reg *prev;
9856 +} shmpiece;
9857 +
9858 +extern shmpiece *shm_start;
9859 +extern int canbang;
9860 +
9861 +#endif
9862 +
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
9868 @@ -0,0 +1,245 @@
9869 +
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
9874 +
9875 +#define HAVE_MMU (currprefs.cpu_level == 4)
9876 +
9877 +extern void mmu_dump_tables(void);
9878 +
9879 +#define MMU_PAGE_8KB 1
9880 +#define MMU_PAGE_4KB 0
9881 +
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)
9893 +
9894 +#define MMU_UDT_MASK 3
9895 +#define MMU_PDT_MASK 3
9896 +
9897 +#define MMU_DES_WP 4
9898 +#define MMU_DES_USED 8
9899 +
9900 +/* page descriptors only */
9901 +#define MMU_DES_MODIFIED 16
9902 +#define MMU_DES_SUPER (1 << 7)
9903 +#define MMU_DES_GLOBAL (1 << 10)
9904 +
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
9908 +
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
9915 +
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)
9927 +
9928 +struct mmu_atc_line {
9929 + int v, umode, g, s, cm, m, w, r, fc2;
9930 + uaecptr phys, log;
9931 +};
9932 +
9933 +extern struct mmu_atc_line atc[64];
9934 +
9935 +#define TTR_I0 4
9936 +#define TTR_I1 5
9937 +#define TTR_D0 6
9938 +#define TTR_D1 7
9939 +
9940 +#define TTR_NO_MATCH 0
9941 +#define TTR_NO_WRITE 1
9942 +#define TTR_OK_MATCH 2
9943 +
9944 +STATIC_INLINE void mmu_set_tc(uae_u16 tc)
9945 +{
9946 + extern void activate_debugger (void);
9947 + regs.tc = tc;
9948 +
9949 + if (currprefs.cpu_level >= 4)
9950 + {
9951 +#if 0
9952 + if (tc & 0x8000)
9953 + {
9954 + uaecptr nextpc;
9955 + m68k_disasm(stdout, m68k_getpc(), &nextpc, 10);
9956 + }
9957 +#endif
9958 +
9959 + regs.mmu_enabled = tc & 0x8000 ? 1 : 0;
9960 + regs.mmu_pagesize = tc & 0x4000 ? MMU_PAGE_8KB : MMU_PAGE_4KB;
9961 +
9962 + write_log("MMU: enabled=%d page=%d\n", regs.mmu_enabled, regs.mmu_pagesize);
9963 +
9964 +
9965 + }
9966 +
9967 +}
9968 +
9969 +extern void mmu_make_transparent_region(uaecptr baseaddr, uae_u32 size, int datamode);
9970 +
9971 +STATIC_INLINE void mmu_set_ttr(int regno, uae_u32 val)
9972 +{
9973 + uae_u32 * ttr;
9974 + switch(regno) {
9975 + case TTR_I0: ttr = &regs.itt0; break;
9976 + case TTR_I1: ttr = &regs.itt1; break;
9977 + case TTR_D0: ttr = &regs.dtt0; break;
9978 + case TTR_D1: ttr = &regs.dtt1; break;
9979 + default: abort();
9980 + }
9981 + *ttr = val;
9982 +}
9983 +
9984 +STATIC_INLINE void mmu_set_mmusr(uae_u32 val)
9985 +{
9986 + regs.mmusr = val;
9987 +}
9988 +
9989 +STATIC_INLINE void mmu_set_root_pointer(int regno, uae_u32 val)
9990 +{
9991 + uae_u32 * rp;
9992 + switch(regno) {
9993 + case 0x806: rp = &regs.urp; break;
9994 + case 0x807: rp = &regs.srp; break;
9995 + default: abort();
9996 + }
9997 + *rp = val;
9998 +}
9999 +
10000 +
10001 +/* MMU related stuff */
10002 +
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);
10010 +#endif
10011 +
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)
10018 +
10019 +STATIC_INLINE uae_u32 get_long(uaecptr addr)
10020 +{
10021 + return phys_get_long(HAVE_MMU ?
10022 + mmu_translate(addr, FC_DATA, 0, m68k_getpc(), sz_long, 0)
10023 + : addr);
10024 +}
10025 +STATIC_INLINE uae_u16 get_word(uaecptr addr)
10026 +{
10027 + return phys_get_word(HAVE_MMU ?
10028 + mmu_translate(addr, FC_DATA, 0, m68k_getpc(), sz_word, 0)
10029 + : addr);
10030 +}
10031 +STATIC_INLINE uae_u8 get_byte(uaecptr addr)
10032 +{
10033 + return phys_get_byte(HAVE_MMU ?
10034 + mmu_translate(addr, FC_DATA, 0, m68k_getpc(), sz_byte, 0)
10035 + : addr);
10036 +}
10037 +
10038 +STATIC_INLINE void put_long(uaecptr addr, uae_u32 l)
10039 +{
10040 + phys_put_long(HAVE_MMU ?
10041 + mmu_translate(addr, FC_DATA, 1, m68k_getpc(), sz_long, 0)
10042 + : addr,
10043 + l);
10044 +}
10045 +STATIC_INLINE void put_word(uaecptr addr, uae_u16 w)
10046 +{
10047 + phys_put_word(HAVE_MMU ?
10048 + mmu_translate(addr, FC_DATA, 1, m68k_getpc(), sz_word, 0)
10049 + : addr,
10050 + w);
10051 +}
10052 +STATIC_INLINE void put_byte(uaecptr addr, uae_u16 b)
10053 +{
10054 + phys_put_byte(HAVE_MMU ?
10055 + mmu_translate(addr, FC_DATA, 1, m68k_getpc(), sz_byte, 0)
10056 + : addr,
10057 + b);
10058 +}
10059 +
10060 +STATIC_INLINE uae_u8 *get_real_address(uaecptr addr)
10061 +{
10062 + return phys_get_real_address(HAVE_MMU ? mmu_translate(addr, FC_DATA, 0, 0, sz_byte, 0) : addr);
10063 +}
10064 +
10065 +STATIC_INLINE int valid_address(uaecptr addr, uae_u32 size)
10066 +{
10067 + return phys_valid_address(HAVE_MMU ? mmu_translate(addr, FC_DATA, 0, 0, sz_byte, 0) : addr, size);
10068 +}
10069 +
10070 +
10071 +STATIC_INLINE uae_u32 sfc_get_long(uaecptr addr)
10072 +{
10073 + return phys_get_long(HAVE_MMU ?
10074 + mmu_translate(addr, regs.sfc, 0, m68k_getpc(), sz_long, 0)
10075 + : addr);
10076 +}
10077 +STATIC_INLINE uae_u16 sfc_get_word(uaecptr addr)
10078 +{
10079 + return phys_get_word(HAVE_MMU ?
10080 + mmu_translate(addr, regs.sfc, 0, m68k_getpc(), sz_word, 0)
10081 + : addr);
10082 +}
10083 +STATIC_INLINE uae_u8 sfc_get_byte(uaecptr addr)
10084 +{
10085 + return phys_get_byte(HAVE_MMU ?
10086 + mmu_translate(addr, regs.sfc, 0, m68k_getpc(), sz_byte, 0)
10087 + : addr);
10088 +}
10089 +
10090 +
10091 +STATIC_INLINE void dfc_put_long(uaecptr addr, uae_u32 l)
10092 +{
10093 + phys_put_long(HAVE_MMU ?
10094 + mmu_translate(addr, regs.dfc, 1, m68k_getpc(), sz_long, 0)
10095 + : addr,
10096 + l);
10097 +}
10098 +STATIC_INLINE void dfc_put_word(uaecptr addr, uae_u16 w)
10099 +{
10100 + phys_put_word(HAVE_MMU ?
10101 + mmu_translate(addr, regs.dfc, 1, m68k_getpc(), sz_word, 0)
10102 + : addr,
10103 + w);
10104 +}
10105 +STATIC_INLINE void dfc_put_byte(uaecptr addr, uae_u16 b)
10106 +{
10107 + phys_put_byte(HAVE_MMU ?
10108 + mmu_translate(addr, regs.dfc, 1, m68k_getpc(), sz_byte, 0)
10109 + : addr,
10110 + b);
10111 +}
10112 +
10113 +
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
10117 @@ -8,6 +8,7 @@
10118
10119 #include "readcpu.h"
10120 #include "machdep/m68k.h"
10121 +#include <setjmp.h>
10122
10123 #ifndef SET_CFLG
10124
10125 @@ -99,6 +100,12 @@
10126
10127 uae_u32 prefetch_pc;
10128 uae_u32 prefetch;
10129 +
10130 + uae_u32 caar, cacr, itt0, itt1, dtt0, dtt1, tc, mmusr, urp, srp;
10131 +
10132 + int mmu_enabled, mmu_pagesize;
10133 + uae_u32 mmu_fslw, mmu_fault_addr;
10134 + uae_u16 mmu_ssw;
10135 } regs, lastint_regs;
10136
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)])
10141
10142 +STATIC_INLINE uaecptr m68k_getpc (void)
10143 +{
10144 + return regs.pc + ((char *)regs.pc_p - (char *)regs.pc_oldp);
10145 +}
10146 +
10147 +STATIC_INLINE uaecptr m68k_getpc_p (uae_u8 *p)
10148 +{
10149 + return regs.pc + ((char *)p - (char *)regs.pc_oldp);
10150 +}
10151 +
10152 +
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);
10158 +
10159 +/* function codes for mmu_translation */
10160 +
10161 +#define FC_DATA regs.s ? 5 : 1
10162 +#define FC_INST regs.s ? 6 : 2
10163 +
10164 +extern uaecptr mmu_translate(uaecptr addr,
10165 + int fc,
10166 + int write,
10167 + uaecptr pc,
10168 + int size, /* sz_xxx */
10169 + int test
10170 + ) REGPARAM;
10171 +#include "mmu.h"
10172 +
10173 #if !defined USE_COMPILER
10174 STATIC_INLINE void m68k_setpc (uaecptr newpc)
10175 {
10176 @@ -124,19 +162,64 @@
10177 extern void m68k_setpc (uaecptr newpc);
10178 #endif
10179
10180 -STATIC_INLINE uaecptr m68k_getpc (void)
10181 +
10182 +#if 0
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)))
10186 +#endif
10187 +
10188 +STATIC_INLINE uae_u8 get_ibyte(uae_u32 o)
10189 {
10190 - return regs.pc + ((char *)regs.pc_p - (char *)regs.pc_oldp);
10191 + if (HAVE_MMU) {
10192 + uaecptr addr = m68k_getpc() + o + 1;
10193 + return phys_get_byte(mmu_translate(addr, FC_INST, 0, addr, sz_byte, 0));
10194 + }
10195 + return do_get_mem_byte((uae_u8 *)(regs.pc_p + (o) + 1));
10196 +}
10197 +STATIC_INLINE uae_u16 get_iword(uae_u32 o)
10198 +{
10199 + if (HAVE_MMU) {
10200 + uaecptr addr = m68k_getpc() + o;
10201 + return phys_get_word(mmu_translate(addr, FC_INST, 0, addr, sz_word, 0));
10202 + }
10203 + return do_get_mem_word((uae_u16 *)(regs.pc_p + (o)));
10204 +}
10205 +STATIC_INLINE uae_u32 get_ilong(uae_u32 o)
10206 +{
10207 + if (HAVE_MMU) {
10208 + uaecptr addr = m68k_getpc() + o;
10209 + return phys_get_long(mmu_translate(addr, FC_INST, 0, addr, sz_long, 0));
10210 + }
10211 + return do_get_mem_long((uae_u32 *)(regs.pc_p + (o)));
10212 }
10213
10214 -STATIC_INLINE uaecptr m68k_getpc_p (uae_u8 *p)
10215 +
10216 +STATIC_INLINE uae_u8 get_ibyte_1(uae_u32 o)
10217 {
10218 - return regs.pc + ((char *)p - (char *)regs.pc_oldp);
10219 + if (HAVE_MMU) {
10220 + uaecptr addr = m68k_getpc() + o + 1;
10221 + return phys_get_byte(mmu_translate(addr, FC_INST, 0, addr, sz_byte, 0));
10222 + }
10223 + return byteget_1(regs.pc + (regs.pc_p - regs.pc_oldp) + (o) + 1);
10224 +}
10225 +STATIC_INLINE uae_u16 get_iword_1(uae_u32 o)
10226 +{
10227 + if (HAVE_MMU) {
10228 + uaecptr addr = m68k_getpc() + o;
10229 + return phys_get_word(mmu_translate(addr, FC_INST, 0, addr, sz_word, 0));
10230 + }
10231 + return wordget_1(regs.pc + (regs.pc_p - regs.pc_oldp) + (o));
10232 }
10233
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)
10238 +{
10239 + if (HAVE_MMU) {
10240 + uaecptr addr = m68k_getpc() + o;
10241 + return phys_get_long(mmu_translate(addr, FC_INST, 0, addr, sz_long, 0));
10242 + }
10243 + return longget_1(regs.pc + (regs.pc_p - regs.pc_oldp) + (o));
10244 +}
10245
10246 STATIC_INLINE void refill_prefetch (uae_u32 currpc, uae_u32 offs)
10247 {
10248 @@ -144,6 +227,16 @@
10249 uae_s32 pc_p_offs = t - currpc;
10250 uae_u8 *ptr = regs.pc_p + pc_p_offs;
10251 uae_u32 r;
10252 +
10253 + regs.prefetch_pc = t;
10254 +
10255 + if (HAVE_MMU) {
10256 + t = mmu_translate(t, FC_INST, 0, t, sz_long, 0);
10257 + r = phys_get_long(t);
10258 + do_put_mem_long(&regs.prefetch, r);
10259 + return;
10260 + }
10261 +
10262 #ifdef UNALIGNED_PROFITABLE
10263 r = *(uae_u32 *)ptr;
10264 regs.prefetch = r;
10265 @@ -152,7 +245,6 @@
10266 do_put_mem_long (&regs.prefetch, r);
10267 #endif
10268 /* printf ("PC %lx T %lx PCPOFFS %d R %lx\n", currpc, t, pc_p_offs, r); */
10269 - regs.prefetch_pc = t;
10270 }
10271
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 *)&regs.prefetch) + offs));
10275 if (offs >= 2)
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); */
10279 return v;
10280 }
10281 STATIC_INLINE uae_u32 get_ilong_prefetch (uae_s32 o)
10282 @@ -252,7 +344,6 @@
10283
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);
10297
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
10302 @@ -0,0 +1,399 @@
10303 + /*
10304 + * UAE - The Un*x Amiga Emulator
10305 + *
10306 + * MC68000 emulation
10307 + *
10308 + * Copyright 1995 Bernd Schmidt
10309 + */
10310 +
10311 +#include "readcpu.h"
10312 +#include "machdep/m68k.h"
10313 +#include <setjmp.h>
10314 +
10315 +#ifndef SET_CFLG
10316 +
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))
10322 +
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
10328 +
10329 +#define CLEAR_CZNV do { \
10330 + SET_CFLG (0); \
10331 + SET_ZFLG (0); \
10332 + SET_NFLG (0); \
10333 + SET_VFLG (0); \
10334 +} while (0)
10335 +
10336 +#define COPY_CARRY (SET_XFLG (GET_CFLG))
10337 +#endif
10338 +
10339 +extern int areg_byteinc[];
10340 +extern int imm8_table[];
10341 +
10342 +extern int movem_index1[256];
10343 +extern int movem_index2[256];
10344 +extern int movem_next[256];
10345 +
10346 +extern int fpp_movem_index1[256];
10347 +extern int fpp_movem_index2[256];
10348 +extern int fpp_movem_next[256];
10349 +
10350 +extern int broken_in;
10351 +
10352 +typedef unsigned long cpuop_func (uae_u32) REGPARAM;
10353 +
10354 +struct cputbl {
10355 + cpuop_func *handler;
10356 + int specific;
10357 + uae_u16 opcode;
10358 +};
10359 +
10360 +extern unsigned long op_illg (uae_u32) REGPARAM;
10361 +
10362 +typedef char flagtype;
10363 +
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
10366 + apps */
10367 +#define USE_LONG_DOUBLE 0
10368 +
10369 +#if USE_LONG_DOUBLE
10370 +typedef long double fptype;
10371 +#else
10372 +typedef double fptype;
10373 +#endif
10374 +
10375 +extern struct regstruct
10376 +{
10377 + uae_u32 regs[16];
10378 + uaecptr usp,isp,msp;
10379 + uae_u16 sr;
10380 + flagtype t1;
10381 + flagtype t0;
10382 + flagtype s;
10383 + flagtype m;
10384 + flagtype x;
10385 + flagtype stopped;
10386 + int intmask;
10387 +
10388 + uae_u32 pc;
10389 + uae_u8 *pc_p;
10390 + uae_u8 *pc_oldp;
10391 +
10392 + uae_u32 vbr,sfc,dfc;
10393 +
10394 + fptype fp[8];
10395 + fptype fp_result;
10396 +
10397 + uae_u32 fpcr,fpsr,fpiar;
10398 + uae_u32 fpsr_highbyte;
10399 +
10400 + uae_u32 spcflags;
10401 + uae_u32 kick_mask;
10402 +
10403 + uae_u32 prefetch_pc;
10404 + uae_u32 prefetch;
10405 +
10406 + uae_u32 caar, cacr, itt0, itt1, dtt0, dtt1, tc, mmusr, urp, srp;
10407 +
10408 + int mmu_enabled, mmu_pagesize;
10409 + uae_u32 mmu_fslw, mmu_fault_addr;
10410 + uae_u16 mmu_ssw;
10411 +} regs, lastint_regs;
10412 +
10413 +STATIC_INLINE void set_special (uae_u32 x)
10414 +{
10415 + regs.spcflags |= x;
10416 +}
10417 +
10418 +STATIC_INLINE void unset_special (uae_u32 x)
10419 +{
10420 + regs.spcflags &= ~x;
10421 +}
10422 +
10423 +#define m68k_dreg(r,num) ((r).regs[(num)])
10424 +#define m68k_areg(r,num) (((r).regs + 8)[(num)])
10425 +
10426 +STATIC_INLINE uaecptr m68k_getpc (void)
10427 +{
10428 + return regs.pc + ((char *)regs.pc_p - (char *)regs.pc_oldp);
10429 +}
10430 +
10431 +STATIC_INLINE uaecptr m68k_getpc_p (uae_u8 *p)
10432 +{
10433 + return regs.pc + ((char *)p - (char *)regs.pc_oldp);
10434 +}
10435 +
10436 +
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);
10442 +
10443 +/* function codes for mmu_translation */
10444 +
10445 +#define FC_DATA regs.s ? 5 : 1
10446 +#define FC_INST regs.s ? 6 : 2
10447 +
10448 +extern uaecptr mmu_translate(uaecptr addr,
10449 + int fc,
10450 + int write,
10451 + uaecptr pc,
10452 + int size, /* sz_xxx */
10453 + int test
10454 + ) REGPARAM;
10455 +#include "mmu.h"
10456 +
10457 +#if !defined USE_COMPILER
10458 +STATIC_INLINE void m68k_setpc (uaecptr newpc)
10459 +{
10460 + regs.pc_p = regs.pc_oldp = get_real_address (newpc);
10461 + regs.pc = newpc;
10462 +}
10463 +#else
10464 +extern void m68k_setpc (uaecptr newpc);
10465 +#endif
10466 +
10467 +
10468 +#if 0
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)))
10472 +#endif
10473 +
10474 +STATIC_INLINE uae_u8 get_ibyte(uae_u32 o)
10475 +{
10476 + if (HAVE_MMU) {
10477 + uaecptr addr = m68k_getpc() + o + 1;
10478 + return phys_get_byte(mmu_translate(addr, FC_INST, 0, addr, sz_byte, 0));
10479 + }
10480 + return do_get_mem_byte((uae_u8 *)(regs.pc_p + (o) + 1));
10481 +}
10482 +STATIC_INLINE uae_u16 get_iword(uae_u32 o)
10483 +{
10484 + if (HAVE_MMU) {
10485 + uaecptr addr = m68k_getpc() + o;
10486 + return phys_get_word(mmu_translate(addr, FC_INST, 0, addr, sz_word, 0));
10487 + }
10488 + return do_get_mem_word((uae_u16 *)(regs.pc_p + (o)));
10489 +}
10490 +STATIC_INLINE uae_u32 get_ilong(uae_u32 o)
10491 +{
10492 + if (HAVE_MMU) {
10493 + uaecptr addr = m68k_getpc() + o;
10494 + return phys_get_long(mmu_translate(addr, FC_INST, 0, addr, sz_long, 0));
10495 + }
10496 + return do_get_mem_long((uae_u32 *)(regs.pc_p + (o)));
10497 +}
10498 +
10499 +
10500 +STATIC_INLINE uae_u8 get_ibyte_1(uae_u32 o)
10501 +{
10502 + if (HAVE_MMU) {
10503 + uaecptr addr = m68k_getpc() + o + 1;
10504 + return phys_get_byte(mmu_translate(addr, FC_INST, 0, addr, sz_byte, 0));
10505 + }
10506 + return byteget_1(regs.pc + (regs.pc_p - regs.pc_oldp) + (o) + 1);
10507 +}
10508 +STATIC_INLINE uae_u16 get_iword_1(uae_u32 o)
10509 +{
10510 + if (HAVE_MMU) {
10511 + uaecptr addr = m68k_getpc() + o;
10512 + return phys_get_word(mmu_translate(addr, FC_INST, 0, addr, sz_word, 0));
10513 + }
10514 + return wordget_1(regs.pc + (regs.pc_p - regs.pc_oldp) + (o));
10515 +}
10516 +
10517 +STATIC_INLINE uae_u32 get_ilong_1(uae_u32 o)
10518 +{
10519 + if (HAVE_MMU) {
10520 + uaecptr addr = m68k_getpc() + o;
10521 + return phys_get_long(mmu_translate(addr, FC_INST, 0, addr, sz_long, 0));
10522 + }
10523 + return longget_1(regs.pc + (regs.pc_p - regs.pc_oldp) + (o));
10524 +}
10525 +
10526 +
10527 +
10528 +
10529 +STATIC_INLINE void refill_prefetch (uae_u32 currpc, uae_u32 offs)
10530 +{
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;
10534 + uae_u32 r;
10535 +
10536 + regs.prefetch_pc = t;
10537 +
10538 + if (HAVE_MMU) {
10539 + t = mmu_translate(t, FC_INST, 0, t, sz_long, 0);
10540 + r = phys_get_long(t);
10541 + do_put_mem_long(&regs.prefetch, r);
10542 + return;
10543 + }
10544 +
10545 +#ifdef UNALIGNED_PROFITABLE
10546 + r = *(uae_u32 *)ptr;
10547 + regs.prefetch = r;
10548 +#else
10549 + r = do_get_mem_long ((uae_u32 *)ptr);
10550 + do_put_mem_long (&regs.prefetch, r);
10551 +#endif
10552 + /* printf ("PC %lx T %lx PCPOFFS %d R %lx\n", currpc, t, pc_p_offs, r); */
10553 +}
10554 +
10555 +STATIC_INLINE uae_u32 get_ibyte_prefetch (uae_s32 o)
10556 +{
10557 + uae_u32 currpc = m68k_getpc ();
10558 + uae_u32 addr = currpc + o + 1;
10559 + uae_u32 offs = addr - regs.prefetch_pc;
10560 + uae_u32 v;
10561 + if (offs > 3) {
10562 + refill_prefetch (currpc, o + 1);
10563 + offs = addr - regs.prefetch_pc;
10564 + }
10565 + v = do_get_mem_byte (((uae_u8 *)&regs.prefetch) + offs);
10566 + if (offs >= 2)
10567 + refill_prefetch (currpc, 4);
10568 + /* printf ("get_ibyte PC %lx ADDR %lx OFFS %lx V %lx\n", currpc, addr, offs, v); */
10569 + return v;
10570 +}
10571 +STATIC_INLINE uae_u32 get_iword_prefetch (uae_s32 o)
10572 +{
10573 + uae_u32 currpc = m68k_getpc ();
10574 + uae_u32 addr = currpc + o;
10575 + uae_u32 offs = addr - regs.prefetch_pc;
10576 + uae_u32 v;
10577 + if (offs > 3) {
10578 + refill_prefetch (currpc, o);
10579 + offs = addr - regs.prefetch_pc;
10580 + }
10581 + v = do_get_mem_word ((uae_u16 *)(((uae_u8 *)&regs.prefetch) + offs));
10582 + if (offs >= 2)
10583 + refill_prefetch (currpc, 4);
10584 +/* printf ("get_iword_prefetch PC %lx ADDR %lx OFFS %lx V %lx\n", currpc, addr, offs, v); */
10585 + return v;
10586 +}
10587 +STATIC_INLINE uae_u32 get_ilong_prefetch (uae_s32 o)
10588 +{
10589 + uae_u32 v = get_iword_prefetch (o);
10590 + v <<= 16;
10591 + v |= get_iword_prefetch (o + 2);
10592 + return v;
10593 +}
10594 +
10595 +#define m68k_incpc(o) (regs.pc_p += (o))
10596 +
10597 +STATIC_INLINE void fill_prefetch_0 (void)
10598 +{
10599 +}
10600 +
10601 +#define fill_prefetch_2 fill_prefetch_0
10602 +
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)
10606 +{
10607 + uae_u32 r = get_ibyte (0);
10608 + m68k_incpc (2);
10609 + return r;
10610 +}
10611 +
10612 +STATIC_INLINE uae_u32 next_iword (void)
10613 +{
10614 + uae_u32 r = get_iword (0);
10615 + m68k_incpc (2);
10616 + return r;
10617 +}
10618 +
10619 +STATIC_INLINE uae_u32 next_ilong (void)
10620 +{
10621 + uae_u32 r = get_ilong (0);
10622 + m68k_incpc (4);
10623 + return r;
10624 +}
10625 +
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);
10630 +#else
10631 +#define m68k_setpc_fast m68k_setpc
10632 +#define m68k_setpc_bcc m68k_setpc
10633 +#define m68k_setpc_rte m68k_setpc
10634 +#endif
10635 +
10636 +STATIC_INLINE void m68k_setstopped (int stop)
10637 +{
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;
10643 +}
10644 +
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);
10647 +
10648 +extern uae_s32 ShowEA (FILE *, int reg, amodes mode, wordsizes size, char *buf);
10649 +
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);
10660 +
10661 +extern void mmu_op (uae_u32, uae_u16);
10662 +
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);
10670 +
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;
10677 +
10678 +#define CPU_OP_NAME(a) op ## a
10679 +
10680 +/* 68040 */
10681 +extern struct cputbl op_smalltbl_0_ff[];
10682 +/* 68020 + 68881 */
10683 +extern struct cputbl op_smalltbl_1_ff[];
10684 +/* 68020 */
10685 +extern struct cputbl op_smalltbl_2_ff[];
10686 +/* 68010 */
10687 +extern struct cputbl op_smalltbl_3_ff[];
10688 +/* 68000 */
10689 +extern struct cputbl op_smalltbl_4_ff[];
10690 +/* 68000 slow but compatible. */
10691 +extern struct cputbl op_smalltbl_5_ff[];
10692 +
10693 +extern cpuop_func *cpufunctbl[65536] ASM_SYM_FOR_FUNC ("cpufunctbl");
10694 +
10695 +#ifdef JIT
10696 +#else
10697 +#define flush_icache(X) do {} while (0)
10698 +#endif
10699 +
10700 +
10701 +
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 @@
10706
10707 uae_u8 REGPARAM2 *default_xlate (uaecptr a)
10708 {
10709 - write_log ("Your Amiga program just did something terribly stupid\n");
10710 - uae_reset ();
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);
10714 + Exception(2, 0);
10715 + longjmp(m68k_exception, 0);
10716 }
10717
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
10722 @@ -0,0 +1,1402 @@
10723 + /*
10724 + * UAE - The Un*x Amiga Emulator
10725 + *
10726 + * Memory management
10727 + *
10728 + * (c) 1995 Bernd Schmidt
10729 + */
10730 +
10731 +#include "sysconfig.h"
10732 +#include "sysdeps.h"
10733 +
10734 +#include "config.h"
10735 +#include "options.h"
10736 +#include "uae.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"
10745 +
10746 +#ifdef USE_MAPPED_MEMORY
10747 +#include <sys/mman.h>
10748 +#endif
10749 +
10750 +/* Set by each memory handler that does not simply access real memory. */
10751 +int special_mem;
10752 +
10753 +int ersatzkickfile = 0;
10754 +
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;
10761 +
10762 +static long chip_filepos;
10763 +static long bogo_filepos;
10764 +static long rom_filepos;
10765 +
10766 +addrbank *mem_banks[65536];
10767 +
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). */
10773 +
10774 +uae_u8 *baseaddr[65536];
10775 +
10776 +#ifdef NO_INLINE_MEMORY_ACCESS
10777 +__inline__ uae_u32 longget (uaecptr addr)
10778 +{
10779 + return call_mem_get_func (get_mem_bank (addr).lget, addr);
10780 +}
10781 +__inline__ uae_u32 wordget (uaecptr addr)
10782 +{
10783 + return call_mem_get_func (get_mem_bank (addr).wget, addr);
10784 +}
10785 +__inline__ uae_u32 byteget (uaecptr addr)
10786 +{
10787 + return call_mem_get_func (get_mem_bank (addr).bget, addr);
10788 +}
10789 +__inline__ void longput (uaecptr addr, uae_u32 l)
10790 +{
10791 + call_mem_put_func (get_mem_bank (addr).lput, addr, l);
10792 +}
10793 +__inline__ void wordput (uaecptr addr, uae_u32 w)
10794 +{
10795 + call_mem_put_func (get_mem_bank (addr).wput, addr, w);
10796 +}
10797 +__inline__ void byteput (uaecptr addr, uae_u32 b)
10798 +{
10799 + call_mem_put_func (get_mem_bank (addr).bput, addr, b);
10800 +}
10801 +#endif
10802 +
10803 +uae_u32 chipmem_mask, kickmem_mask, extendedkickmem_mask, bogomem_mask, a3000mem_mask;
10804 +
10805 +static int illegal_count;
10806 +/* A dummy bank that only contains zeros */
10807 +
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;
10815 +
10816 +uae_u32 REGPARAM2 dummy_lget (uaecptr addr)
10817 +{
10818 + special_mem |= S_READ;
10819 + if (currprefs.illegal_mem) {
10820 + if (illegal_count < 20) {
10821 + illegal_count++;
10822 + write_log ("Illegal lget at %08lx\n", addr);
10823 + }
10824 + }
10825 +
10826 + return 0xFFFFFFFF;
10827 +}
10828 +
10829 +uae_u32 REGPARAM2 dummy_wget (uaecptr addr)
10830 +{
10831 + special_mem |= S_READ;
10832 + if (currprefs.illegal_mem) {
10833 + if (illegal_count < 20) {
10834 + illegal_count++;
10835 + write_log ("Illegal wget at %08lx\n", addr);
10836 + }
10837 + }
10838 +
10839 + return 0xFFFF;
10840 +}
10841 +
10842 +uae_u32 REGPARAM2 dummy_bget (uaecptr addr)
10843 +{
10844 + special_mem |= S_READ;
10845 + if (currprefs.illegal_mem) {
10846 + if (illegal_count < 20) {
10847 + illegal_count++;
10848 + write_log ("Illegal bget at %08lx\n", addr);
10849 + }
10850 + }
10851 +
10852 + return 0xFF;
10853 +}
10854 +
10855 +void REGPARAM2 dummy_lput (uaecptr addr, uae_u32 l)
10856 +{
10857 + special_mem |= S_WRITE;
10858 + if (currprefs.illegal_mem) {
10859 + if (illegal_count < 20) {
10860 + illegal_count++;
10861 + write_log ("Illegal lput at %08lx\n", addr);
10862 + }
10863 + }
10864 +}
10865 +void REGPARAM2 dummy_wput (uaecptr addr, uae_u32 w)
10866 +{
10867 + special_mem |= S_WRITE;
10868 + if (currprefs.illegal_mem) {
10869 + if (illegal_count < 20) {
10870 + illegal_count++;
10871 + write_log ("Illegal wput at %08lx\n", addr);
10872 + }
10873 + }
10874 +}
10875 +void REGPARAM2 dummy_bput (uaecptr addr, uae_u32 b)
10876 +{
10877 + special_mem |= S_WRITE;
10878 + if (currprefs.illegal_mem) {
10879 + if (illegal_count < 20) {
10880 + illegal_count++;
10881 + write_log ("Illegal bput at %08lx\n", addr);
10882 + }
10883 + }
10884 +}
10885 +
10886 +int REGPARAM2 dummy_check (uaecptr addr, uae_u32 size)
10887 +{
10888 + special_mem |= S_READ;
10889 + if (currprefs.illegal_mem) {
10890 + if (illegal_count < 20) {
10891 + illegal_count++;
10892 + write_log ("Illegal check at %08lx\n", addr);
10893 + }
10894 + }
10895 +
10896 + return 0;
10897 +}
10898 +
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;
10907 +
10908 +static int mbres_val = 0;
10909 +
10910 +uae_u32 REGPARAM2 mbres_lget (uaecptr addr)
10911 +{
10912 + special_mem |= S_READ;
10913 + if (currprefs.illegal_mem)
10914 + write_log ("Illegal lget at %08lx\n", addr);
10915 +
10916 + return 0;
10917 +}
10918 +
10919 +uae_u32 REGPARAM2 mbres_wget (uaecptr addr)
10920 +{
10921 + special_mem |= S_READ;
10922 + if (currprefs.illegal_mem)
10923 + write_log ("Illegal wget at %08lx\n", addr);
10924 +
10925 + return 0;
10926 +}
10927 +
10928 +uae_u32 REGPARAM2 mbres_bget (uaecptr addr)
10929 +{
10930 + special_mem |= S_READ;
10931 + if (currprefs.illegal_mem)
10932 + write_log ("Illegal bget at %08lx\n", addr);
10933 +
10934 + return (addr & 0xFFFF) == 3 ? mbres_val : 0;
10935 +}
10936 +
10937 +void REGPARAM2 mbres_lput (uaecptr addr, uae_u32 l)
10938 +{
10939 + special_mem |= S_WRITE;
10940 + if (currprefs.illegal_mem)
10941 + write_log ("Illegal lput at %08lx\n", addr);
10942 +}
10943 +void REGPARAM2 mbres_wput (uaecptr addr, uae_u32 w)
10944 +{
10945 + special_mem |= S_WRITE;
10946 + if (currprefs.illegal_mem)
10947 + write_log ("Illegal wput at %08lx\n", addr);
10948 +}
10949 +void REGPARAM2 mbres_bput (uaecptr addr, uae_u32 b)
10950 +{
10951 + special_mem |= S_WRITE;
10952 + if (currprefs.illegal_mem)
10953 + write_log ("Illegal bput at %08lx\n", addr);
10954 +
10955 + if ((addr & 0xFFFF) == 3)
10956 + mbres_val = b;
10957 +}
10958 +
10959 +int REGPARAM2 mbres_check (uaecptr addr, uae_u32 size)
10960 +{
10961 + if (currprefs.illegal_mem)
10962 + write_log ("Illegal check at %08lx\n", addr);
10963 +
10964 + return 0;
10965 +}
10966 +
10967 +/* Chip memory */
10968 +
10969 +uae_u8 *chipmemory;
10970 +
10971 +static int chipmem_check (uaecptr addr, uae_u32 size) REGPARAM;
10972 +static uae_u8 *chipmem_xlate (uaecptr addr) REGPARAM;
10973 +
10974 +uae_u32 REGPARAM2 chipmem_lget (uaecptr addr)
10975 +{
10976 + uae_u32 *m;
10977 +
10978 + addr -= chipmem_start & chipmem_mask;
10979 + addr &= chipmem_mask;
10980 + m = (uae_u32 *)(chipmemory + addr);
10981 + return do_get_mem_long (m);
10982 +}
10983 +
10984 +uae_u32 REGPARAM2 chipmem_wget (uaecptr addr)
10985 +{
10986 + uae_u16 *m;
10987 +
10988 + addr -= chipmem_start & chipmem_mask;
10989 + addr &= chipmem_mask;
10990 + m = (uae_u16 *)(chipmemory + addr);
10991 + return do_get_mem_word (m);
10992 +}
10993 +
10994 +uae_u32 REGPARAM2 chipmem_bget (uaecptr addr)
10995 +{
10996 + addr -= chipmem_start & chipmem_mask;
10997 + addr &= chipmem_mask;
10998 + return chipmemory[addr];
10999 +}
11000 +
11001 +void REGPARAM2 chipmem_lput (uaecptr addr, uae_u32 l)
11002 +{
11003 + uae_u32 *m;
11004 +
11005 + addr -= chipmem_start & chipmem_mask;
11006 + addr &= chipmem_mask;
11007 + m = (uae_u32 *)(chipmemory + addr);
11008 + do_put_mem_long (m, l);
11009 +}
11010 +
11011 +void REGPARAM2 chipmem_wput (uaecptr addr, uae_u32 w)
11012 +{
11013 + uae_u16 *m;
11014 +
11015 + addr -= chipmem_start & chipmem_mask;
11016 + addr &= chipmem_mask;
11017 + m = (uae_u16 *)(chipmemory + addr);
11018 + do_put_mem_word (m, w);
11019 +}
11020 +
11021 +void REGPARAM2 chipmem_bput (uaecptr addr, uae_u32 b)
11022 +{
11023 + addr -= chipmem_start & chipmem_mask;
11024 + addr &= chipmem_mask;
11025 + chipmemory[addr] = b;
11026 +}
11027 +
11028 +int REGPARAM2 chipmem_check (uaecptr addr, uae_u32 size)
11029 +{
11030 + addr -= chipmem_start & chipmem_mask;
11031 + addr &= chipmem_mask;
11032 + return (addr + size) <= allocated_chipmem;
11033 +}
11034 +
11035 +uae_u8 REGPARAM2 *chipmem_xlate (uaecptr addr)
11036 +{
11037 + addr -= chipmem_start & chipmem_mask;
11038 + addr &= chipmem_mask;
11039 + return chipmemory + addr;
11040 +}
11041 +
11042 +/* Slow memory */
11043 +
11044 +static uae_u8 *bogomemory;
11045 +
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;
11054 +
11055 +uae_u32 REGPARAM2 bogomem_lget (uaecptr addr)
11056 +{
11057 + uae_u32 *m;
11058 + addr -= bogomem_start & bogomem_mask;
11059 + addr &= bogomem_mask;
11060 + m = (uae_u32 *)(bogomemory + addr);
11061 + return do_get_mem_long (m);
11062 +}
11063 +
11064 +uae_u32 REGPARAM2 bogomem_wget (uaecptr addr)
11065 +{
11066 + uae_u16 *m;
11067 + addr -= bogomem_start & bogomem_mask;
11068 + addr &= bogomem_mask;
11069 + m = (uae_u16 *)(bogomemory + addr);
11070 + return do_get_mem_word (m);
11071 +}
11072 +
11073 +uae_u32 REGPARAM2 bogomem_bget (uaecptr addr)
11074 +{
11075 + addr -= bogomem_start & bogomem_mask;
11076 + addr &= bogomem_mask;
11077 + return bogomemory[addr];
11078 +}
11079 +
11080 +void REGPARAM2 bogomem_lput (uaecptr addr, uae_u32 l)
11081 +{
11082 + uae_u32 *m;
11083 + addr -= bogomem_start & bogomem_mask;
11084 + addr &= bogomem_mask;
11085 + m = (uae_u32 *)(bogomemory + addr);
11086 + do_put_mem_long (m, l);
11087 +}
11088 +
11089 +void REGPARAM2 bogomem_wput (uaecptr addr, uae_u32 w)
11090 +{
11091 + uae_u16 *m;
11092 + addr -= bogomem_start & bogomem_mask;
11093 + addr &= bogomem_mask;
11094 + m = (uae_u16 *)(bogomemory + addr);
11095 + do_put_mem_word (m, w);
11096 +}
11097 +
11098 +void REGPARAM2 bogomem_bput (uaecptr addr, uae_u32 b)
11099 +{
11100 + addr -= bogomem_start & bogomem_mask;
11101 + addr &= bogomem_mask;
11102 + bogomemory[addr] = b;
11103 +}
11104 +
11105 +int REGPARAM2 bogomem_check (uaecptr addr, uae_u32 size)
11106 +{
11107 + addr -= bogomem_start & bogomem_mask;
11108 + addr &= bogomem_mask;
11109 + return (addr + size) <= allocated_bogomem;
11110 +}
11111 +
11112 +uae_u8 REGPARAM2 *bogomem_xlate (uaecptr addr)
11113 +{
11114 + addr -= bogomem_start & bogomem_mask;
11115 + addr &= bogomem_mask;
11116 + return bogomemory + addr;
11117 +}
11118 +
11119 +/* A3000 motherboard fast memory */
11120 +
11121 +static uae_u8 *a3000memory;
11122 +
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;
11131 +
11132 +uae_u32 REGPARAM2 a3000mem_lget (uaecptr addr)
11133 +{
11134 + uae_u32 *m;
11135 + addr -= a3000mem_start & a3000mem_mask;
11136 + addr &= a3000mem_mask;
11137 + m = (uae_u32 *)(a3000memory + addr);
11138 + return do_get_mem_long (m);
11139 +}
11140 +
11141 +uae_u32 REGPARAM2 a3000mem_wget (uaecptr addr)
11142 +{
11143 + uae_u16 *m;
11144 + addr -= a3000mem_start & a3000mem_mask;
11145 + addr &= a3000mem_mask;
11146 + m = (uae_u16 *)(a3000memory + addr);
11147 + return do_get_mem_word (m);
11148 +}
11149 +
11150 +uae_u32 REGPARAM2 a3000mem_bget (uaecptr addr)
11151 +{
11152 + addr -= a3000mem_start & a3000mem_mask;
11153 + addr &= a3000mem_mask;
11154 + return a3000memory[addr];
11155 +}
11156 +
11157 +void REGPARAM2 a3000mem_lput (uaecptr addr, uae_u32 l)
11158 +{
11159 + uae_u32 *m;
11160 + addr -= a3000mem_start & a3000mem_mask;
11161 + addr &= a3000mem_mask;
11162 + m = (uae_u32 *)(a3000memory + addr);
11163 + do_put_mem_long (m, l);
11164 +}
11165 +
11166 +void REGPARAM2 a3000mem_wput (uaecptr addr, uae_u32 w)
11167 +{
11168 + uae_u16 *m;
11169 + addr -= a3000mem_start & a3000mem_mask;
11170 + addr &= a3000mem_mask;
11171 + m = (uae_u16 *)(a3000memory + addr);
11172 + do_put_mem_word (m, w);
11173 +}
11174 +
11175 +void REGPARAM2 a3000mem_bput (uaecptr addr, uae_u32 b)
11176 +{
11177 + addr -= a3000mem_start & a3000mem_mask;
11178 + addr &= a3000mem_mask;
11179 + a3000memory[addr] = b;
11180 +}
11181 +
11182 +int REGPARAM2 a3000mem_check (uaecptr addr, uae_u32 size)
11183 +{
11184 + addr -= a3000mem_start & a3000mem_mask;
11185 + addr &= a3000mem_mask;
11186 + return (addr + size) <= allocated_a3000mem;
11187 +}
11188 +
11189 +uae_u8 REGPARAM2 *a3000mem_xlate (uaecptr addr)
11190 +{
11191 + addr -= a3000mem_start & a3000mem_mask;
11192 + addr &= a3000mem_mask;
11193 + return a3000memory + addr;
11194 +}
11195 +
11196 +/* Kick memory */
11197 +
11198 +uae_u8 *kickmemory;
11199 +
11200 +/*
11201 + * A1000 kickstart RAM handling
11202 + *
11203 + * RESET instruction unhides boot ROM and disables write protection
11204 + * write access to boot ROM hides boot ROM and enables write protection
11205 + *
11206 + */
11207 +static int a1000_kickstart_mode;
11208 +static uae_u8 *a1000_bootrom;
11209 +static void a1000_handle_kickstart (int mode)
11210 +{
11211 + if (mode == 0) {
11212 + a1000_kickstart_mode = 0;
11213 + memcpy (kickmemory, kickmemory + 262144, 262144);
11214 + } else {
11215 + a1000_kickstart_mode = 1;
11216 + memset (kickmemory, 0, 262144);
11217 + memcpy (kickmemory, a1000_bootrom, 8192);
11218 + memcpy (kickmemory + 131072, a1000_bootrom, 8192);
11219 + }
11220 +}
11221 +
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;
11230 +
11231 +uae_u32 REGPARAM2 kickmem_lget (uaecptr addr)
11232 +{
11233 + uae_u32 *m;
11234 + addr -= kickmem_start & kickmem_mask;
11235 + addr &= kickmem_mask;
11236 + m = (uae_u32 *)(kickmemory + addr);
11237 + return do_get_mem_long (m);
11238 +}
11239 +
11240 +uae_u32 REGPARAM2 kickmem_wget (uaecptr addr)
11241 +{
11242 + uae_u16 *m;
11243 + addr -= kickmem_start & kickmem_mask;
11244 + addr &= kickmem_mask;
11245 + m = (uae_u16 *)(kickmemory + addr);
11246 + return do_get_mem_word (m);
11247 +}
11248 +
11249 +uae_u32 REGPARAM2 kickmem_bget (uaecptr addr)
11250 +{
11251 + addr -= kickmem_start & kickmem_mask;
11252 + addr &= kickmem_mask;
11253 + return kickmemory[addr];
11254 +}
11255 +
11256 +void REGPARAM2 kickmem_lput (uaecptr addr, uae_u32 b)
11257 +{
11258 + uae_u32 *m;
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);
11265 + return;
11266 + } else
11267 + a1000_handle_kickstart (0);
11268 + } else if (currprefs.illegal_mem)
11269 + write_log ("Illegal kickmem lput at %08lx\n", addr);
11270 +}
11271 +
11272 +void REGPARAM2 kickmem_wput (uaecptr addr, uae_u32 b)
11273 +{
11274 + uae_u16 *m;
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);
11281 + return;
11282 + } else
11283 + a1000_handle_kickstart (0);
11284 + } else if (currprefs.illegal_mem)
11285 + write_log ("Illegal kickmem wput at %08lx\n", addr);
11286 +}
11287 +
11288 +void REGPARAM2 kickmem_bput (uaecptr addr, uae_u32 b)
11289 +{
11290 + if (a1000_kickstart_mode) {
11291 + if (addr >= 0xfc0000) {
11292 + addr -= kickmem_start & kickmem_mask;
11293 + addr &= kickmem_mask;
11294 + kickmemory[addr] = b;
11295 + return;
11296 + } else
11297 + a1000_handle_kickstart (0);
11298 + } else if (currprefs.illegal_mem)
11299 + write_log ("Illegal kickmem lput at %08lx\n", addr);
11300 +}
11301 +
11302 +int REGPARAM2 kickmem_check (uaecptr addr, uae_u32 size)
11303 +{
11304 + addr -= kickmem_start & kickmem_mask;
11305 + addr &= kickmem_mask;
11306 + return (addr + size) <= kickmem_size;
11307 +}
11308 +
11309 +uae_u8 REGPARAM2 *kickmem_xlate (uaecptr addr)
11310 +{
11311 + addr -= kickmem_start & kickmem_mask;
11312 + addr &= kickmem_mask;
11313 + return kickmemory + addr;
11314 +}
11315 +
11316 +/* CD32/CDTV extended kick memory */
11317 +
11318 +uae_u8 *extendedkickmemory;
11319 +static int extendedkickmem_size;
11320 +static uae_u32 extendedkickmem_start;
11321 +
11322 +#define EXTENDED_ROM_CD32 1
11323 +#define EXTENDED_ROM_CDTV 2
11324 +
11325 +static int extromtype (void)
11326 +{
11327 + switch (extendedkickmem_size) {
11328 + case 524288:
11329 + return EXTENDED_ROM_CD32;
11330 + case 262144:
11331 + return EXTENDED_ROM_CDTV;
11332 + }
11333 + return 0;
11334 +}
11335 +
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;
11344 +
11345 +uae_u32 REGPARAM2 extendedkickmem_lget (uaecptr addr)
11346 +{
11347 + uae_u32 *m;
11348 + addr -= extendedkickmem_start & extendedkickmem_mask;
11349 + addr &= extendedkickmem_mask;
11350 + m = (uae_u32 *)(extendedkickmemory + addr);
11351 + return do_get_mem_long (m);
11352 +}
11353 +
11354 +uae_u32 REGPARAM2 extendedkickmem_wget (uaecptr addr)
11355 +{
11356 + uae_u16 *m;
11357 + addr -= extendedkickmem_start & extendedkickmem_mask;
11358 + addr &= extendedkickmem_mask;
11359 + m = (uae_u16 *)(extendedkickmemory + addr);
11360 + return do_get_mem_word (m);
11361 +}
11362 +
11363 +uae_u32 REGPARAM2 extendedkickmem_bget (uaecptr addr)
11364 +{
11365 + addr -= extendedkickmem_start & extendedkickmem_mask;
11366 + addr &= extendedkickmem_mask;
11367 + return extendedkickmemory[addr];
11368 +}
11369 +
11370 +void REGPARAM2 extendedkickmem_lput (uaecptr addr, uae_u32 b)
11371 +{
11372 + if (currprefs.illegal_mem)
11373 + write_log ("Illegal extendedkickmem lput at %08lx\n", addr);
11374 +}
11375 +
11376 +void REGPARAM2 extendedkickmem_wput (uaecptr addr, uae_u32 b)
11377 +{
11378 + if (currprefs.illegal_mem)
11379 + write_log ("Illegal extendedkickmem wput at %08lx\n", addr);
11380 +}
11381 +
11382 +void REGPARAM2 extendedkickmem_bput (uaecptr addr, uae_u32 b)
11383 +{
11384 + if (currprefs.illegal_mem)
11385 + write_log ("Illegal extendedkickmem lput at %08lx\n", addr);
11386 +}
11387 +
11388 +int REGPARAM2 extendedkickmem_check (uaecptr addr, uae_u32 size)
11389 +{
11390 + addr -= extendedkickmem_start & extendedkickmem_mask;
11391 + addr &= extendedkickmem_mask;
11392 + return (addr + size) <= extendedkickmem_size;
11393 +}
11394 +
11395 +uae_u8 REGPARAM2 *extendedkickmem_xlate (uaecptr addr)
11396 +{
11397 + addr -= extendedkickmem_start & extendedkickmem_mask;
11398 + addr &= extendedkickmem_mask;
11399 + return extendedkickmemory + addr;
11400 +}
11401 +
11402 +/* Default memory access functions */
11403 +
11404 +int REGPARAM2 default_check (uaecptr a, uae_u32 b)
11405 +{
11406 + return 0;
11407 +}
11408 +
11409 +uae_u8 REGPARAM2 *default_xlate (uaecptr a)
11410 +{
11411 + write_log ("Your Amiga program just did something terribly stupid\n");
11412 + uae_reset ();
11413 + return kickmem_xlate (get_long (0xF80000)); /* So we don't crash. */
11414 +}
11415 +
11416 +/* Address banks */
11417 +
11418 +addrbank dummy_bank = {
11419 + dummy_lget, dummy_wget, dummy_bget,
11420 + dummy_lput, dummy_wput, dummy_bput,
11421 + default_xlate, dummy_check, NULL
11422 +};
11423 +
11424 +addrbank mbres_bank = {
11425 + mbres_lget, mbres_wget, mbres_bget,
11426 + mbres_lput, mbres_wput, mbres_bput,
11427 + default_xlate, mbres_check, NULL
11428 +};
11429 +
11430 +addrbank chipmem_bank = {
11431 + chipmem_lget, chipmem_wget, chipmem_bget,
11432 + chipmem_lput, chipmem_wput, chipmem_bput,
11433 + chipmem_xlate, chipmem_check, NULL
11434 +};
11435 +
11436 +addrbank bogomem_bank = {
11437 + bogomem_lget, bogomem_wget, bogomem_bget,
11438 + bogomem_lput, bogomem_wput, bogomem_bput,
11439 + bogomem_xlate, bogomem_check, NULL
11440 +};
11441 +
11442 +addrbank a3000mem_bank = {
11443 + a3000mem_lget, a3000mem_wget, a3000mem_bget,
11444 + a3000mem_lput, a3000mem_wput, a3000mem_bput,
11445 + a3000mem_xlate, a3000mem_check, NULL
11446 +};
11447 +
11448 +addrbank kickmem_bank = {
11449 + kickmem_lget, kickmem_wget, kickmem_bget,
11450 + kickmem_lput, kickmem_wput, kickmem_bput,
11451 + kickmem_xlate, kickmem_check, NULL
11452 +};
11453 +
11454 +addrbank extendedkickmem_bank = {
11455 + extendedkickmem_lget, extendedkickmem_wget, extendedkickmem_bget,
11456 + extendedkickmem_lput, extendedkickmem_wput, extendedkickmem_bput,
11457 + extendedkickmem_xlate, extendedkickmem_check, NULL
11458 +};
11459 +
11460 +static int decode_cloanto_rom (uae_u8 *mem, int size, int real_size)
11461 +{
11462 + FILE *keyf;
11463 + uae_u8 *p;
11464 + long cnt, t;
11465 + int keysize;
11466 +
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");
11469 + return 0;
11470 + }
11471 + keyf = zfile_open (currprefs.keyfile, "rb");
11472 + if (keyf == 0) {
11473 + write_log ("Could not find specified ROM key-file.\n");
11474 + return 0;
11475 + }
11476 +
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)
11482 + t = keysize - 1;
11483 + }
11484 + fclose (keyf);
11485 + free (p);
11486 + return 1;
11487 +}
11488 +
11489 +static int kickstart_checksum (uae_u8 *mem, int size)
11490 +{
11491 + uae_u32 cksum = 0, prevck = 0;
11492 + int i;
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];
11495 + cksum += data;
11496 + if (cksum < prevck)
11497 + cksum++;
11498 + prevck = cksum;
11499 + }
11500 + if (cksum != 0xFFFFFFFFul) {
11501 + write_log ("Kickstart checksum incorrect. You probably have a corrupted ROM image.\n");
11502 + }
11503 + return 0;
11504 +}
11505 +
11506 +static int read_kickstart (FILE *f, uae_u8 *mem, int size, int dochecksum, int *cloanto_rom)
11507 +{
11508 + unsigned char buffer[20];
11509 + int i, cr = 0;
11510 +
11511 + if (cloanto_rom)
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);
11516 + } else {
11517 + cr = 1;
11518 + }
11519 +
11520 + i = fread (mem, 1, size, f);
11521 + if (i == 8192) {
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");
11529 + zfile_close (f);
11530 + return 0;
11531 + }
11532 + zfile_close (f);
11533 +
11534 + if (cr)
11535 + decode_cloanto_rom (mem, size, i);
11536 + if (dochecksum && i >= 262144)
11537 + kickstart_checksum (mem, size);
11538 + if (cloanto_rom)
11539 + *cloanto_rom = cr;
11540 + return 1;
11541 +}
11542 +
11543 +static int load_extendedkickstart (void)
11544 +{
11545 + FILE *f;
11546 + int size;
11547 +
11548 + if (strlen (currprefs.romextfile) == 0)
11549 + return 0;
11550 + f = zfile_open (currprefs.romextfile, "rb");
11551 + if (!f) {
11552 + write_log ("No extended Kickstart ROM found");
11553 + return 0;
11554 + }
11555 +
11556 + fseek (f, 0, SEEK_END);
11557 + size = ftell (f);
11558 + if (size > 300000)
11559 + extendedkickmem_size = 524288;
11560 + else
11561 + extendedkickmem_size = 262144;
11562 + fseek (f, 0, SEEK_SET);
11563 +
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;
11568 + break;
11569 + case EXTENDED_ROM_CD32:
11570 + extendedkickmemory = (uae_u8 *) mapped_malloc (extendedkickmem_size, "rom_e0");
11571 + extendedkickmem_bank.baseaddr = (uae_u8 *) extendedkickmemory;
11572 + break;
11573 + }
11574 + read_kickstart (f, extendedkickmemory, 524288, 0, 0);
11575 + fclose (f);
11576 + return 1;
11577 +}
11578 +
11579 +
11580 +static int load_kickstart (void)
11581 +{
11582 + FILE *f = zfile_open (currprefs.romfile, "rb");
11583 +
11584 + if (f == NULL) {
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);
11591 + goto chk_sum;
11592 + }
11593 +#endif
11594 + return 0;
11595 + }
11596 +
11597 + if (!read_kickstart (f, kickmemory, kickmem_size, 1, &cloanto_rom))
11598 + return 0;
11599 +
11600 +#if defined(AMIGA)
11601 + chk_sum:
11602 +#endif
11603 +
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
11609 + */
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");
11622 + }
11623 + }
11624 + return 1;
11625 +}
11626 +
11627 +char *address_space, *good_address_map;
11628 +int good_address_fd;
11629 +
11630 +#ifndef NATMEM_OFFSET
11631 +
11632 +uae_u8 *mapped_malloc (size_t s, char *file)
11633 +{
11634 + return malloc (s);
11635 +}
11636 +
11637 +void mapped_free (uae_u8 *p)
11638 +{
11639 + free (p);
11640 +}
11641 +#else
11642 +
11643 +#include <sys/ipc.h>
11644 +#include <sys/shm.h>
11645 +#include <unistd.h>
11646 +#include <sys/mman.h>
11647 +
11648 +shmpiece *shm_start = NULL;
11649 +int canbang = 1;
11650 +
11651 +static void dumplist (void)
11652 +{
11653 + shmpiece *x = shm_start;
11654 + printf ("Start Dump:\n");
11655 + while (x) {
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);
11658 + x = x->next;
11659 + }
11660 + printf ("End Dump:\n");
11661 +}
11662 +
11663 +static shmpiece *find_shmpiece (uae_u8 *base)
11664 +{
11665 + shmpiece *x = shm_start;
11666 +
11667 + while (x && x->native_address != base)
11668 + x = x->next;
11669 + if (!x) {
11670 + printf ("NATMEM: Failure to find mapping at %p\n", base);
11671 + dumplist ();
11672 + canbang = 0;
11673 + return 0;
11674 + }
11675 + return x;
11676 +}
11677 +
11678 +static void delete_shmmaps (uae_u32 start, uae_u32 size)
11679 +{
11680 + if (!canbang)
11681 + return;
11682 +
11683 + while (size) {
11684 + uae_u8 *base = mem_banks[bankindex (start)]->baseaddr;
11685 + if (base) {
11686 + shmpiece *x;
11687 + base = ((uae_u8 *) NATMEM_OFFSET) + start;
11688 +
11689 + x = find_shmpiece (base);
11690 + if (!x)
11691 + return;
11692 +
11693 + if (x->size > size) {
11694 + printf ("NATMEM: Failure to delete mapping at %08x(size %08x, delsize %08x)\n", start, x->size, size);
11695 + dumplist ();
11696 + canbang = 0;
11697 + return;
11698 + }
11699 + shmdt (x->native_address);
11700 + size -= x->size;
11701 + start += x->size;
11702 + if (x->next)
11703 + x->next->prev = x->prev; /* remove this one from the list */
11704 + if (x->prev)
11705 + x->prev->next = x->next;
11706 + else
11707 + shm_start = x->next;
11708 + free (x);
11709 + } else {
11710 + size -= 0x10000;
11711 + start += 0x10000;
11712 + }
11713 + }
11714 +}
11715 +
11716 +static void add_shmmaps (uae_u32 start, addrbank *what)
11717 +{
11718 + shmpiece *x = shm_start;
11719 + shmpiece *y;
11720 + uae_u8 *base = what->baseaddr;
11721 +
11722 + if (!canbang)
11723 + return;
11724 + if (!base)
11725 + return;
11726 +
11727 + x = find_shmpiece (base);
11728 + if (!x)
11729 + return;
11730 + y = malloc (sizeof (shmpiece));
11731 + *y = *x;
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");
11737 + dumplist ();
11738 + canbang = 0;
11739 + return;
11740 + }
11741 + y->next = shm_start;
11742 + y->prev = NULL;
11743 + if (y->next)
11744 + y->next->prev = y;
11745 + shm_start = y;
11746 +}
11747 +
11748 +uae_u8 *mapped_malloc (size_t s, char *file)
11749 +{
11750 + int id;
11751 + void *answer;
11752 + shmpiece *x;
11753 +
11754 + if (!canbang)
11755 + return malloc (s);
11756 +
11757 + id = shmget (IPC_PRIVATE, s, 0x1ff, file);
11758 + if (id == 1) {
11759 + canbang = 0;
11760 + return mapped_malloc (s, file);
11761 + }
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;
11767 + x->id = id;
11768 + x->size = s;
11769 + x->next = shm_start;
11770 + x->prev = NULL;
11771 + if (x->next)
11772 + x->next->prev = x;
11773 + shm_start = x;
11774 +
11775 + return answer;
11776 + }
11777 + canbang = 0;
11778 + return mapped_malloc (s, file);
11779 +}
11780 +
11781 +void mapped_free (uae_u8 *base)
11782 +{
11783 + shmpiece *x = find_shmpiece (base);
11784 + if (!x)
11785 + abort ();
11786 + shmdt (x->native_address);
11787 +}
11788 +
11789 +#endif
11790 +
11791 +static void init_mem_banks (void)
11792 +{
11793 + int i;
11794 + for (i = 0; i < 65536; i++)
11795 + put_mem_bank (i << 16, &dummy_bank, 0);
11796 +}
11797 +
11798 +static void allocate_memory (void)
11799 +{
11800 + if (allocated_chipmem != currprefs.chipmem_size) {
11801 + if (chipmemory)
11802 + mapped_free (chipmemory);
11803 + chipmemory = 0;
11804 +
11805 + allocated_chipmem = currprefs.chipmem_size;
11806 + chipmem_mask = allocated_chipmem - 1;
11807 +
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;
11812 + } else
11813 + do_put_mem_long ((uae_u32 *)(chipmemory + 4), 0);
11814 + }
11815 +
11816 + if (allocated_bogomem != currprefs.bogomem_size) {
11817 + if (bogomemory)
11818 + mapped_free (bogomemory);
11819 + bogomemory = 0;
11820 +
11821 + allocated_bogomem = currprefs.bogomem_size;
11822 + bogomem_mask = allocated_bogomem - 1;
11823 +
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;
11829 + }
11830 + }
11831 + }
11832 + if (allocated_a3000mem != currprefs.a3000mem_size) {
11833 + if (a3000memory)
11834 + mapped_free (a3000memory);
11835 + a3000memory = 0;
11836 +
11837 + allocated_a3000mem = currprefs.a3000mem_size;
11838 + a3000mem_mask = allocated_a3000mem - 1;
11839 +
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;
11845 + }
11846 + }
11847 + }
11848 +
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);
11855 + }
11856 + }
11857 + chipmem_bank.baseaddr = chipmemory;
11858 + bogomem_bank.baseaddr = bogomemory;
11859 +}
11860 +
11861 +void memory_reset (void)
11862 +{
11863 + int i, custom_start;
11864 +
11865 +#ifdef NATMEM_OFFSET
11866 + delete_shmmaps (0, 0xFFFF0000);
11867 +#endif
11868 + init_mem_banks ();
11869 +
11870 + currprefs.chipmem_size = changed_prefs.chipmem_size;
11871 + currprefs.bogomem_size = changed_prefs.bogomem_size;
11872 + currprefs.a3000mem_size = changed_prefs.a3000mem_size;
11873 +
11874 + allocate_memory ();
11875 +
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;
11885 + }
11886 + }
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);
11890 +
11891 + custom_start = 0xC0;
11892 +
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);
11896 +
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); */
11904 +
11905 + if (bogomemory != 0) {
11906 + int t = allocated_bogomem >> 16;
11907 + if (t > 0x1C)
11908 + t = 0x1C;
11909 + map_banks (&bogomem_bank, 0xC0, t, allocated_bogomem);
11910 + }
11911 + if (a3000memory != 0)
11912 + map_banks (&a3000mem_bank, a3000mem_start >> 16, allocated_a3000mem >> 16, allocated_a3000mem);
11913 +
11914 + map_banks (&rtarea_bank, RTAREA_BASE >> 16, 1, 0);
11915 +
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);
11920 +
11921 + switch (extromtype ()) {
11922 + case EXTENDED_ROM_CDTV:
11923 + map_banks (&extendedkickmem_bank, 0xF0, 4, 0);
11924 + break;
11925 + case EXTENDED_ROM_CD32:
11926 + map_banks (&extendedkickmem_bank, 0xE0, 8, 0);
11927 + break;
11928 + default:
11929 + if (cloanto_rom)
11930 + map_banks (&kickmem_bank, 0xE0, 8, 0);
11931 + }
11932 +}
11933 +
11934 +void memory_init (void)
11935 +{
11936 + allocated_chipmem = 0;
11937 + allocated_bogomem = 0;
11938 + allocated_a3000mem = 0;
11939 + kickmemory = 0;
11940 + extendedkickmemory = 0;
11941 + chipmemory = 0;
11942 + a3000memory = 0;
11943 + bogomemory = 0;
11944 +
11945 + kickmemory = mapped_malloc (kickmem_size, "kick");
11946 + kickmem_bank.baseaddr = kickmemory;
11947 +
11948 + load_extendedkickstart ();
11949 + if (!load_kickstart ()) {
11950 + init_ersatz_rom (kickmemory);
11951 + ersatzkickfile = 1;
11952 + }
11953 +
11954 + init_mem_banks ();
11955 + memory_reset ();
11956 +
11957 + kickmem_mask = kickmem_size - 1;
11958 + extendedkickmem_mask = extendedkickmem_size - 1;
11959 +}
11960 +
11961 +void memory_cleanup (void)
11962 +{
11963 + if (a3000memory)
11964 + mapped_free (a3000memory);
11965 + if (bogomemory)
11966 + mapped_free (bogomemory);
11967 + if (kickmemory)
11968 + mapped_free (kickmemory);
11969 + if (a1000_bootrom)
11970 + free (a1000_bootrom);
11971 + if (chipmemory)
11972 + mapped_free (chipmemory);
11973 +
11974 + a3000memory = 0;
11975 + bogomemory = 0;
11976 + kickmemory = 0;
11977 + a1000_bootrom = 0;
11978 + chipmemory = 0;
11979 +}
11980 +
11981 +void map_banks (addrbank *bank, int start, int size, int realsize)
11982 +{
11983 + int bnr;
11984 + unsigned long int hioffs = 0, endhioffs = 0x100;
11985 + addrbank *orgbank = bank;
11986 + uae_u32 realstart = start;
11987 +
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);
11991 +#endif
11992 +
11993 + if (!realsize)
11994 + realsize = size << 16;
11995 +
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");
12001 + abort ();
12002 + }
12003 +
12004 + if (start >= 0x100) {
12005 + int real_left = 0;
12006 + for (bnr = start; bnr < start + size; bnr++) {
12007 + if (!real_left) {
12008 + realstart = bnr;
12009 + real_left = realsize >> 16;
12010 +#ifdef NATMEM_OFFSET
12011 + add_shmmaps (realstart << 16, bank);
12012 +#endif
12013 + }
12014 + put_mem_bank (bnr << 16, bank, realstart << 16);
12015 + real_left--;
12016 + }
12017 + return;
12018 + }
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);
12029 +#endif
12030 + }
12031 + put_mem_bank ((bnr + hioffs) << 16, bank, realstart << 16);
12032 + real_left--;
12033 + }
12034 + }
12035 +}
12036 +
12037 +
12038 +/* memory save/restore code */
12039 +
12040 +uae_u8 *save_cram (int *len)
12041 +{
12042 + *len = allocated_chipmem;
12043 + return chipmemory;
12044 +}
12045 +
12046 +uae_u8 *save_bram (int *len)
12047 +{
12048 + *len = allocated_bogomem;
12049 + return bogomemory;
12050 +}
12051 +
12052 +void restore_cram (int len, long filepos)
12053 +{
12054 + chip_filepos = filepos;
12055 + changed_prefs.chipmem_size = len;
12056 +}
12057 +
12058 +void restore_bram (int len, long filepos)
12059 +{
12060 + bogo_filepos = filepos;
12061 + changed_prefs.bogomem_size = len;
12062 +}
12063 +
12064 +uae_u8 *restore_rom (uae_u8 *src)
12065 +{
12066 + restore_u32 ();
12067 + restore_u32 ();
12068 + restore_u32 ();
12069 + restore_u32 ();
12070 + restore_u32 ();
12071 +
12072 + return src;
12073 +}
12074 +
12075 +uae_u8 *save_rom (int first, int *len)
12076 +{
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;
12081 +
12082 + saverom = 0;
12083 + if (first)
12084 + count = 0;
12085 + for (;;) {
12086 + mem_type = count;
12087 + switch (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))
12095 + break;
12096 + }
12097 + if (i == mem_size / 2 - 4) {
12098 + mem_size /= 2;
12099 + mem_start += 262144;
12100 + }
12101 + mem_type = 0;
12102 + break;
12103 + default:
12104 + return 0;
12105 + }
12106 + count++;
12107 + if (mem_size)
12108 + break;
12109 + }
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 */
12115 + save_u32 (0);
12116 + sprintf (dst, "Kickstart %d.%d", wordget (mem_start + 12), wordget (mem_start + 14));
12117 + dst += strlen (dst) + 1;
12118 + if (saverom) {
12119 + for (i = 0; i < mem_size; i++)
12120 + *dst++ = byteget (mem_start + i);
12121 + }
12122 + *len = dst - dstbak;
12123 + return dstbak;
12124 +}
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
12128 @@ -0,0 +1,733 @@
12129 +#include "sysconfig.h"
12130 +#include "sysdeps.h"
12131 +
12132 +#include "config.h"
12133 +#include "options.h"
12134 +#include "events.h"
12135 +#include "uae.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"
12143 +#include "gui.h"
12144 +#include "savestate.h"
12145 +
12146 +#define DBG_MMU_VERBOSE 1
12147 +#define DBG_MMU_SANITY 0
12148 +
12149 +static void mmu_dump_ttr(const char * label, uae_u32 ttr)
12150 +{
12151 + uae_u32 from_addr, to_addr;
12152 +
12153 + from_addr = ttr & MMU_TTR_LOGICAL_BASE;
12154 + to_addr = (ttr & MMU_TTR_LOGICAL_MASK) << 8;
12155 +
12156 + printf("%s: [%08lx] %08lx - %08lx enabled=%d supervisor=%d wp=%d cm=%02d\n",
12157 + label, ttr,
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
12163 + );
12164 +}
12165 +
12166 +extern void mmu_make_transparent_region(uaecptr baseaddr, uae_u32 size, int datamode)
12167 +{
12168 + uae_u32 * ttr;
12169 + uae_u32 * ttr0 = datamode ? &regs.dtt0 : &regs.itt0;
12170 + uae_u32 * ttr1 = datamode ? &regs.dtt1 : &regs.itt1;
12171 +
12172 + if ((*ttr1 & MMU_TTR_BIT_ENABLED) == 0)
12173 + ttr = ttr1;
12174 + else if ((*ttr0 & MMU_TTR_BIT_ENABLED) == 0)
12175 + ttr = ttr0;
12176 + else
12177 + return;
12178 +
12179 + *ttr = baseaddr & MMU_TTR_LOGICAL_BASE;
12180 + *ttr |= ((baseaddr + size - 1) & MMU_TTR_LOGICAL_BASE) >> 8;
12181 + *ttr |= MMU_TTR_BIT_ENABLED;
12182 +
12183 + write_log("MMU: map transparent mapping of %08x\n", *ttr);
12184 +}
12185 +
12186 +/* check if an address matches a ttr */
12187 +STATIC_INLINE int mmu_match_ttr(uae_u32 ttr, uaecptr addr, int write, int test)
12188 +{
12189 + if (ttr & MMU_TTR_BIT_ENABLED) { /* TTR enabled */
12190 + uae_u8 msb, match, mask;
12191 +
12192 + msb = (addr & MMU_TTR_LOGICAL_BASE) >> 24;
12193 + match = (ttr & MMU_TTR_LOGICAL_BASE) >> 24;
12194 + mask = (ttr & MMU_TTR_LOGICAL_MASK) >> 16;
12195 +
12196 + if ((msb & ~mask) == match) {
12197 +
12198 + if ((ttr & MMU_TTR_BIT_SFIELD_ENABLED) == 0) {
12199 + if ((ttr & MMU_TTR_BIT_SFIELD_SUPER) && !regs.s) {
12200 + return TTR_NO_MATCH;
12201 + }
12202 + if ((ttr & MMU_TTR_BIT_SFIELD_SUPER) == 0 && regs.s) {
12203 + return TTR_NO_MATCH;
12204 + }
12205 + }
12206 +
12207 + if (test) {
12208 + regs.mmusr = MMU_MMUSR_T | MMU_MMUSR_R;
12209 + }
12210 +
12211 + if ((ttr & MMU_TTR_BIT_WRITE_PROTECT) && write)
12212 + return TTR_NO_WRITE;
12213 + return TTR_OK_MATCH;
12214 + }
12215 + }
12216 + return TTR_NO_MATCH;
12217 +}
12218 +
12219 +struct mmu_atc_line atc[64];
12220 +static int atc_rand = 0;
12221 +static int atc_last_hit = -1;
12222 +
12223 +/* {{{ mmu_dump_table */
12224 +static void mmu_dump_table(const char * label, uaecptr root_ptr)
12225 +{
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;
12236 +
12237 + printf("%s: root=%lx\n", label, root_ptr);
12238 +
12239 + for (root_idx = 0; root_idx < ROOT_TABLE_SIZE; root_idx++) {
12240 + root_des = phys_get_long(root_ptr + root_idx);
12241 +
12242 + if ((root_des & 2) == 0)
12243 + continue; /* invalid */
12244 +
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,
12248 + root_des & 3
12249 + );
12250 +
12251 + root_log = root_idx << 25;
12252 +
12253 + ptr_des_addr = root_des & MMU_ROOT_PTR_ADDR_MASK;
12254 +
12255 + for (ptr_idx = 0; ptr_idx < PTR_TABLE_SIZE; ptr_idx++) {
12256 + struct {
12257 + uaecptr log, phys;
12258 + int start_idx, n_pages; /* number of pages covered by this entry */
12259 + uae_u32 match;
12260 + } page_info[PAGE_TABLE_SIZE];
12261 + int n_pages_used;
12262 +
12263 + ptr_des = phys_get_long(ptr_des_addr + ptr_idx);
12264 + ptr_log = root_log | (ptr_idx << 18);
12265 +
12266 + if ((ptr_des & 2) == 0)
12267 + continue; /* invalid */
12268 +
12269 + page_addr = ptr_des & (regs.mmu_pagesize ? MMU_PTR_PAGE_ADDR_MASK_8 : MMU_PTR_PAGE_ADDR_MASK_4);
12270 +
12271 + n_pages_used = -1;
12272 + for (page_idx = 0; page_idx < PAGE_TABLE_SIZE; page_idx++) {
12273 +
12274 + page_des = phys_get_long(page_addr + page_idx);
12275 + page_log = ptr_log | (page_idx << 2);
12276 +
12277 + switch (page_des & 3) {
12278 + case 0: /* invalid */
12279 + continue;
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 */
12284 + n_pages_used++;
12285 +
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;
12290 + }
12291 + else {
12292 + page_info[n_pages_used].n_pages++;
12293 + }
12294 + break;
12295 + }
12296 + }
12297 +
12298 + if (n_pages_used == -1)
12299 + continue;
12300 +
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,
12304 + ptr_des & 3
12305 + );
12306 +
12307 +
12308 + for (page_idx = 0; page_idx <= n_pages_used; page_idx++) {
12309 + page_des = page_info[page_idx].match;
12310 +
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
12317 + );
12318 +
12319 + }
12320 + else {
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
12334 + );
12335 + }
12336 + }
12337 + }
12338 +
12339 + }
12340 +}
12341 +/* }}} */
12342 +
12343 +/* {{{ mmu_dump_atc */
12344 +void mmu_dump_atc(void)
12345 +{
12346 + int i;
12347 + for (i = 0; i < 64; i++) {
12348 + if (!atc[i].v)
12349 + continue;
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,
12353 + atc[i].log,
12354 + atc[i].phys
12355 + );
12356 + }
12357 +}
12358 +/* }}} */
12359 +
12360 +/* {{{ mmu_dump_tables */
12361 +void mmu_dump_tables(void)
12362 +{
12363 + if (currprefs.cpu_level != 4) {
12364 + printf("This CPU has no MMU hardware\n");
12365 + return;
12366 + }
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);
12372 + mmu_dump_atc();
12373 + //mmu_dump_table("SRP", regs.srp);
12374 +}
12375 +/* }}} */
12376 +
12377 +static void phys_dump_mem (uaecptr addr, int lines)
12378 +{
12379 + for (;lines--;) {
12380 + int i;
12381 + printf ("%08lx ", addr);
12382 + for (i = 0; i < 16; i++) {
12383 + printf ("%04x ", phys_get_word(addr)); addr += 2;
12384 + }
12385 + printf ("\n");
12386 + }
12387 +}
12388 +
12389 +
12390 +uaecptr REGPARAM2 mmu_translate(uaecptr theaddr, int fc, int write, uaecptr pc, int size, int test)
12391 +{
12392 + uae_u32
12393 + atc_hit_addr = 0,
12394 + root_ptr,
12395 + root_des, root_des_addr,
12396 + ptr_des = 0, ptr_des_addr = 0,
12397 + page_des = 0, page_des_addr = 0,
12398 + phys_addr = 0,
12399 + fslw = 0;
12400 + uae_u8 ri, pi, pgi, wp = 0;
12401 + uae_u16 ssw = 0;
12402 + uae_u32 page_frame;
12403 + int supervisor, datamode =0;
12404 + int i, atc_sel, atc_index = -1, n_table_searches = 0;
12405 +
12406 +// if (theaddr == 0x40000000) test |= MMU_TEST_VERBOSE;
12407 +
12408 + supervisor = fc & 4;
12409 +
12410 + switch(fc) {
12411 + case 0: /* data cache push */
12412 + case 1:
12413 + case 3:
12414 + case 5:
12415 + datamode = 1;
12416 + break;
12417 + case 2:
12418 + case 4:
12419 + case 6:
12420 + datamode = 0;
12421 + break;
12422 + case 7:
12423 + default:
12424 + write_log("FC=%d should not happen\n", datamode);
12425 + abort();
12426 + }
12427 +
12428 + root_ptr = supervisor ? regs.srp : regs.urp;
12429 +
12430 + /* check ttr0 */
12431 +
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);
12440 + goto bus_err;
12441 + case TTR_OK_MATCH:
12442 + return theaddr;
12443 + }
12444 + /* check ttr1 */
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);
12448 + goto bus_err;
12449 + case TTR_OK_MATCH:
12450 + return theaddr;
12451 + }
12452 + }
12453 +
12454 + if (!regs.mmu_enabled)
12455 + return theaddr;
12456 +
12457 +
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;
12464 + }
12465 + else {
12466 + pgi = (theaddr & 0x3f000) >> 12;
12467 + page_frame = theaddr & 0xfffff000;
12468 + atc_sel = ((theaddr & 0xf000) >> 12) & 0xf;
12469 + }
12470 +check_atc:
12471 +
12472 + atc_rand++; /* for random replacement */
12473 +
12474 + if (test & MMU_TEST_FORCE_TABLE_SEARCH)
12475 + goto table_search;
12476 +
12477 + for (i = 0; i < 4; i++) {
12478 + atc_index = atc_sel + (4 * i);
12479 +
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);
12487 +#endif
12488 +
12489 +
12490 + if (atc[atc_index].v && (atc[atc_index].log == page_frame) && atc[atc_index].fc2 == (fc & 4))
12491 + break;
12492 + atc_index = -1;
12493 + }
12494 +
12495 + if (atc_index != -1) {
12496 +atc_matched:
12497 +
12498 + /* it's a hit! */
12499 +
12500 + if (!atc[atc_index].r) {
12501 +#if DBG_MMU_VERBOSE
12502 + write_log("MMU: non-resident page!\n");
12503 +#endif
12504 + goto bus_err;
12505 + }
12506 +
12507 +
12508 + wp = atc[atc_index].w;
12509 +
12510 + atc_hit_addr = atc[atc_index].phys | ((regs.mmu_pagesize == MMU_PAGE_8KB)
12511 + ? (theaddr & 0x1fff)
12512 + : (theaddr & 0x0fff));
12513 +
12514 + if (test) {
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;
12525 +
12526 + regs.mmusr |= atc[atc_index].phys & MMU_MMUSR_ADDR_MASK;
12527 + }
12528 +
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);
12538 +
12539 + }
12540 +#endif
12541 +
12542 + if (atc[atc_index].s && !supervisor) {
12543 + write_log("MMU: Supervisor only\n");
12544 + fslw |= (1 << 8);
12545 + goto bus_err;
12546 + }
12547 + if (wp && write) {
12548 + write_log("MMU: write protected!\n");
12549 + fslw |= (1 << 7);
12550 + goto bus_err;
12551 + }
12552 +
12553 + if (!atc[atc_index].m && write) {
12554 + /* we need to update the M bit of the final descriptor */
12555 + goto table_search;
12556 + }
12557 +#if 0
12558 + goto table_search;
12559 +#endif
12560 + return atc_hit_addr;
12561 + }
12562 + atc_index = -1;
12563 +
12564 +table_search:
12565 +
12566 + if (n_table_searches++ > 3) {
12567 + write_log("MMU: apparently looping during table search.\n");
12568 + abort();
12569 + }
12570 +
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);
12576 + break;
12577 + }
12578 + }
12579 + /* random choice */
12580 + if (atc_index == -1) {
12581 + atc_index = atc_sel + (4 * (atc_rand & 2));
12582 + }
12583 + }
12584 +
12585 + fslw |= (1 << 6); /* TWE: flag as being in table search */
12586 +
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);
12591 +#endif
12592 +
12593 + /* root descriptor */
12594 + root_des_addr = (root_ptr & MMU_ROOT_PTR_ADDR_MASK) | (ri << 2);
12595 +
12596 +#if DBG_MMU_SANITY
12597 + if (!phys_valid_address(root_des_addr, sz_long))
12598 + goto bus_err;
12599 +#endif
12600 +
12601 + root_des = phys_get_long(root_des_addr);
12602 +
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);
12607 + }
12608 +#endif
12609 +
12610 + switch(root_des & MMU_UDT_MASK) {
12611 + case 0x0:
12612 + case 0x1:
12613 + write_log("MMU: invalid root descriptor for %lx\n", theaddr);
12614 + fslw |= (1 << 12); /* PTA */
12615 + goto make_non_resident_atc;
12616 + }
12617 +
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);
12623 + }
12624 +
12625 +
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))
12629 + goto bus_err;
12630 +#endif
12631 +
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);
12637 +#endif
12638 +
12639 + switch(ptr_des & MMU_UDT_MASK) {
12640 + case 0x0:
12641 + case 0x1:
12642 + write_log("MMU: invalid ptr descriptor for %lx\n", theaddr);
12643 + fslw |= (1 << 11); /* PTB */
12644 + goto make_non_resident_atc;
12645 + }
12646 + wp |= ptr_des & MMU_DES_WP;
12647 + /* touch */
12648 + if (!wp && (ptr_des & MMU_DES_USED) == 0) {
12649 + ptr_des |= MMU_DES_USED;
12650 + phys_put_long(ptr_des_addr, ptr_des);
12651 + }
12652 +
12653 + if (regs.mmu_pagesize == MMU_PAGE_8KB)
12654 + page_des_addr = (ptr_des & MMU_PTR_PAGE_ADDR_MASK_8) | (pgi << 2);
12655 + else
12656 + page_des_addr = (ptr_des & MMU_PTR_PAGE_ADDR_MASK_4) | (pgi << 2);
12657 +
12658 +get_page_descriptor:
12659 +#if DBG_MMU_SANITY
12660 + if (!phys_valid_address(page_des_addr, sz_long))
12661 + goto bus_err;
12662 +#endif
12663 +
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);
12669 + }
12670 +#endif
12671 +
12672 + switch(page_des & MMU_PDT_MASK) {
12673 + case 0x0:
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;
12677 + case 0x1:
12678 + case 0x3:
12679 + /* resident page */
12680 + break;
12681 + case 0x2:
12682 + default:
12683 + /* indirect */
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;
12687 + }
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;
12691 + }
12692 +
12693 + wp |= page_des & MMU_DES_WP;
12694 + if (!wp) {
12695 + int modify = 0;
12696 + if ((page_des & MMU_DES_USED) == 0) {
12697 + page_des |= MMU_DES_USED;
12698 + modify = 1;
12699 + }
12700 + /* set the modified bit */
12701 + if (write && (page_des & MMU_DES_MODIFIED) == 0) {
12702 + page_des |= MMU_DES_MODIFIED;
12703 + modify = 1;
12704 + }
12705 + if (modify)
12706 + phys_put_long(page_des_addr, page_des);
12707 + }
12708 +
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);
12717 +
12718 + atc[atc_index].m = (page_des & MMU_DES_MODIFIED) ? 1 : 0;
12719 +
12720 +
12721 +#if 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();
12726 + }
12727 +#endif
12728 + /* re-use the end of the atc code */
12729 + goto atc_matched;
12730 +
12731 +bus_err:
12732 +
12733 + ssw |= (1 << 10); /* ATC */
12734 + if (!write)
12735 + ssw |= (1 << 8);
12736 +
12737 + fslw |= (1 << (write ? 23 : 24));
12738 + if (!datamode) {
12739 + fslw |= (1 << 15); /* IO */
12740 +
12741 + if (supervisor)
12742 + ssw |= 0x6;
12743 + else
12744 + ssw |= 0x2;
12745 + }
12746 +#if 0
12747 + if (regs.t0)
12748 + fslw |= (1 << 19);
12749 + if (regs.t1)
12750 + fslw |= (1 << 20);
12751 +#endif
12752 +
12753 + ssw |= fc & 7; /* Copy TM */
12754 +
12755 + regs.mmu_fault_addr = theaddr;
12756 + regs.mmu_fslw = fslw;
12757 + regs.mmu_ssw = ssw;
12758 +
12759 + if (test)
12760 + regs.mmusr |= MMU_MMUSR_B;
12761 +
12762 + write_log("BUS ERROR: fc=%d w=%d log=%08x ssw=%04x fslw=%08x\n", fc, write, theaddr, ssw, fslw);
12763 +
12764 + if ((test & MMU_TEST_NO_BUSERR) == 0) {
12765 + Exception(2, pc);
12766 + longjmp(m68k_exception, 0);
12767 + }
12768 + return 0;
12769 +
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);
12781 +#endif
12782 +
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;
12787 + goto bus_err;
12788 +}
12789 +
12790 +void mmu_op(uae_u32 opcode, uae_u16 extra)
12791 +{
12792 + if ((opcode & 0xFE0) == 0x0500) {
12793 + int i, regno, didflush = 0;
12794 + /* PFLUSH */
12795 + mmu_set_mmusr(0);
12796 +
12797 + regno = opcode & 7;
12798 +
12799 + switch((opcode & 24) >> 3) {
12800 + case 0:
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)
12806 + {
12807 + atc[i].v = 0;
12808 + didflush++;
12809 + }
12810 + }
12811 + break;
12812 + case 1:
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)
12818 + {
12819 + atc[i].v = 0;
12820 + didflush++;
12821 + }
12822 + }
12823 +
12824 + break;
12825 +
12826 + case 2:
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)))
12831 + atc[i].v = 0;
12832 + }
12833 + break;
12834 +
12835 + case 3:
12836 + /* PFLUSHA flush all entries */
12837 + write_log ("PFLUSHA\n");
12838 + for (i = 0; i < 64; i++) {
12839 + if (atc[i].v)
12840 + didflush++;
12841 + atc[i].v = 0;
12842 + }
12843 + atc_last_hit = -1;
12844 + break;
12845 + }
12846 + if (didflush)
12847 + write_log(" -> flushed %d matching entries\n", didflush);
12848 +
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);
12857 + } else
12858 + op_illg (opcode);
12859 +}
12860 +
12861 +
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
12865 @@ -24,6 +24,14 @@
12866 #include "savestate.h"
12867 #include "blitter.h"
12868
12869 +#define SANITY_CHECK_ATC 1
12870 +#define MMU_SETJMP_EXCEPTIONS 1
12871 +
12872 +#if MMU_SETJMP_EXCEPTIONS
12873 +jmp_buf m68k_exception;
12874 +#endif
12875 +
12876 +
12877 /* Opcode of faulting instruction */
12878 uae_u16 last_op_for_exception_3;
12879 /* PC at fault time */
12880 @@ -46,7 +54,7 @@
12881
12882 #define COUNT_INSTRS 0
12883
12884 -#if COUNT_INSTRS
12885 +#if COUNT_INSTRS /* {{{ */
12886 static unsigned long int instrcount[65536];
12887 static uae_u16 opcodenums[65536];
12888
12889 @@ -94,7 +102,7 @@
12890 void dump_counts (void)
12891 {
12892 }
12893 -#endif
12894 +#endif /* }}} */
12895
12896 int broken_in;
12897
12898 @@ -106,6 +114,7 @@
12899 return 4;
12900 }
12901
12902 +/* {{{ CPU init/table building */
12903 static void build_cpufunctbl (void)
12904 {
12905 int i;
12906 @@ -176,6 +185,9 @@
12907 {
12908 int i;
12909
12910 + memset(&atc, 0, sizeof(atc));
12911 + regs.mmu_enabled = 0;
12912 +
12913 update_68k_cycles ();
12914
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));
12919 }
12920 -#if COUNT_INSTRS
12921 +#if COUNT_INSTRS /* {{{ */
12922 {
12923 FILE *f = fopen (icountfilename (), "r");
12924 memset (instrcount, 0, sizeof instrcount);
12925 @@ -211,7 +223,7 @@
12926 fclose(f);
12927 }
12928 }
12929 -#endif
12930 +#endif /* }}} */
12931 write_log ("Building CPU table for configuration: 68");
12932 if (currprefs.address_space_24 && currprefs.cpu_level > 1)
12933 write_log ("EC");
12934 @@ -244,6 +256,7 @@
12935
12936 build_cpufunctbl ();
12937 }
12938 +/* }}} */
12939
12940 struct regstruct regs, lastint_regs;
12941 static struct regstruct regs_backup[16];
12942 @@ -251,10 +264,6 @@
12943 static long int m68kpc_offset;
12944 int lastint_no;
12945
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))
12949 -
12950 uae_s32 ShowEA (FILE *f, int reg, amodes mode, wordsizes size, char *buf)
12951 {
12952 uae_u16 dp;
12953 @@ -681,6 +690,45 @@
12954 unset_special (SPCFLAG_TRACE);
12955 }
12956
12957 +/* for building exception frames */
12958 +STATIC_INLINE void exc_push_word(uae_u16 w)
12959 +{
12960 + m68k_areg(regs, 7) -= 2;
12961 + put_word(m68k_areg(regs, 7), w);
12962 +}
12963 +STATIC_INLINE void exc_push_long(uae_u32 l)
12964 +{
12965 + m68k_areg(regs, 7) -= 4;
12966 + put_long (m68k_areg(regs, 7), l);
12967 +}
12968 +
12969 +STATIC_INLINE void exc_make_frame(
12970 + int format,
12971 + uae_u16 sr,
12972 + uae_u32 currpc,
12973 + int nr,
12974 + uae_u32 x0,
12975 + uae_u32 x1
12976 +)
12977 +{
12978 + switch(format) {
12979 + case 4:
12980 + exc_push_long(x1);
12981 + exc_push_long(x0);
12982 + break;
12983 + case 3:
12984 + case 2:
12985 + exc_push_long(x0);
12986 + break;
12987 + }
12988 +
12989 + exc_push_word((format << 12) + (nr * 4)); /* format | vector */
12990 + exc_push_long(currpc);
12991 + exc_push_word(sr);
12992 +}
12993 +
12994 +int in_exception_2 = 0;
12995 +
12996 void Exception(int nr, uaecptr oldpc)
12997 {
12998 uae_u32 currpc = m68k_getpc ();
12999 @@ -696,56 +744,107 @@
13000 m68k_areg(regs, 7) = regs.isp;
13001 regs.s = 1;
13002 }
13003 +
13004 + if (nr == 2 && in_exception_2++) {
13005 + write_log("HALT: Double Bus Error means bad news!\n");
13006 + abort();
13007 + }
13008 +
13009 if (currprefs.cpu_level > 0) {
13010 - if (nr == 2 || nr == 3) {
13011 - int i;
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);
13016 + if (nr == 2) {
13017 + write_log("Exception 2!!\n");
13018 + if (currprefs.cpu_level == 5) {
13019 + /* 68060 */
13020 + exc_make_frame(4,
13021 + regs.sr,
13022 + currpc,
13023 + nr,
13024 + regs.mmu_fault_addr, /* fault address */
13025 + regs.mmu_fslw /* fault status long-word */
13026 + );
13027 }
13028 - m68k_areg(regs, 7) -= 2;
13029 - put_word (m68k_areg(regs, 7), 0xa000 + nr * 4);
13030 + else if (currprefs.cpu_level == 4) {
13031 + /* 68040 */
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,
13049 + regs.sr,
13050 + currpc,
13051 + 2,
13052 + 0,
13053 + 0);
13054 + }
13055 + }
13056 + else if (nr == 3) {
13057 + int i;
13058 +
13059 + exc_make_frame(2,
13060 + regs.sr,
13061 + last_addr_for_exception_3,
13062 + nr,
13063 + last_fault_for_exception_3 & 0xfffffffe,
13064 + 0
13065 + );
13066 +
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,
13074 + regs.sr,
13075 + currpc,
13076 + nr,
13077 + oldpc,
13078 + 0
13079 + );
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,
13089 + regs.sr,
13090 + currpc,
13091 + nr,
13092 + 0, 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);
13098 +
13099 + exc_make_frame(1, /* throwaway */
13100 + regs.sr,
13101 + currpc,
13102 + nr,
13103 + 0, 0);
13104 } else {
13105 - m68k_areg(regs, 7) -= 2;
13106 - put_word (m68k_areg(regs, 7), nr * 4);
13107 + exc_make_frame(0,
13108 + regs.sr,
13109 + currpc,
13110 + nr,
13111 + 0, 0);
13112 }
13113 } else {
13114 - if (nr == 2 || nr == 3) {
13115 - m68k_areg(regs, 7) -= 12;
13116 - /* ??????? */
13117 - if (nr == 3) {
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);
13121 - }
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);
13126 +
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);
13130 }
13131 + exc_push_word(regs.sr);
13132 }
13133 - m68k_areg(regs, 7) -= 4;
13134 - put_long (m68k_areg(regs, 7), currpc);
13135 -kludge_me_do:
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);
13146 }
13147
13148 -static uae_u32 caar, cacr, itt0, itt1, dtt0, dtt1, tc, mmusr, urp, srp;
13149
13150 int m68k_move2c (int regno, uae_u32 *regp)
13151 {
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 @@
13157 return 0;
13158 } else {
13159 switch (regno) {
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;
13175
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;
13188 default:
13189 + write_log("move2x cpu=%d regno=%lx val=%lx\n", currprefs.cpu_level, regno, *regp);
13190 op_illg (0x4E7B);
13191 return 0;
13192 }
13193 @@ -802,31 +900,34 @@
13194
13195 int m68k_movec2 (int regno, uae_u32 *regp)
13196 {
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))
13201 {
13202 + write_log("movec2 cpu=%d regno=%lx\n", currprefs.cpu_level, regno);
13203 op_illg (0x4E7A);
13204 return 0;
13205 } else {
13206 switch (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;
13233 default:
13234 + write_log("movec2 cpu=%d regno=%lx\n", currprefs.cpu_level, regno);
13235 op_illg (0x4E7A);
13236 return 0;
13237 }
13238 @@ -1091,6 +1192,8 @@
13239
13240 void m68k_reset (void)
13241 {
13242 + write_log("M68K: RESET!\n");
13243 + mmu_set_tc(regs.tc & ~0x8000); /* disable mmu */
13244 regs.kick_mask = 0x00F80000;
13245 regs.spcflags = 0;
13246 if (savestate_state == STATE_RESTORE) {
13247 @@ -1106,8 +1209,8 @@
13248 return;
13249 }
13250
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 ();
13257 regs.s = 1;
13258 @@ -1137,7 +1240,7 @@
13259 }
13260
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");
13265 broken_in = 1;
13266 set_special (SPCFLAG_BRK);
13267 @@ -1185,19 +1288,6 @@
13268 return 4;
13269 }
13270
13271 -void mmu_op(uae_u32 opcode, uae_u16 extra)
13272 -{
13273 - if ((opcode & 0xFE0) == 0x0500) {
13274 - /* PFLUSH */
13275 - mmusr = 0;
13276 - write_log ("PFLUSH\n");
13277 - } else if ((opcode & 0x0FD8) == 0x548) {
13278 - /* PTEST */
13279 - write_log ("PTEST\n");
13280 - } else
13281 - op_illg (opcode);
13282 -}
13283 -
13284 static int n_insns = 0, n_spcinsns = 0;
13285
13286 static uaecptr last_trace_ad = 0;
13287 @@ -1410,6 +1500,10 @@
13288 reset_frame_rate_hack ();
13289 update_68k_cycles ();
13290
13291 +#if MMU_SETJMP_EXCEPTIONS
13292 + setjmp(m68k_exception);
13293 +#endif
13294 +
13295 in_m68k_go++;
13296 for (;;) {
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(&regs.prefetch));
13301
13302 + fprintf (f, "this PC: %08lx\n", m68k_getpc());
13303 m68k_disasm (f, m68k_getpc (), nextpc, 1);
13304 if (nextpc)
13305 fprintf (f, "next PC: %08lx\n", *nextpc);
13306 }
13307
13308
13309 -/* CPU save/restore code */
13310 +/* {{{ CPU save/restore code */
13311
13312 #define CPUTYPE_EC 1
13313 #define CPUMODE_HALT 1
13314 @@ -1616,8 +1711,8 @@
13315 regs.vbr = restore_u32 ();
13316 }
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 ();
13323 }
13324 write_log ("CPU %d%s%03d, PC=%08.8X\n",
13325 @@ -1651,10 +1746,13 @@
13326 save_u32 (regs.vbr); /* VBR */
13327 }
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 */
13334 }
13335 *len = dst - dstbak;
13336 return dstbak;
13337 }
13338 +
13339 +/* }}} */
13340 +
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
13344 @@ -0,0 +1,1763 @@
13345 + /*
13346 + * UAE - The Un*x Amiga Emulator
13347 + *
13348 + * MC68000 emulation
13349 + *
13350 + * (c) 1995 Bernd Schmidt
13351 + */
13352 +
13353 +#include "sysconfig.h"
13354 +#include "sysdeps.h"
13355 +
13356 +#include "config.h"
13357 +#include "options.h"
13358 +#include "events.h"
13359 +#include "uae.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"
13367 +#include "gui.h"
13368 +#include "savestate.h"
13369 +#include "blitter.h"
13370 +
13371 +#define SANITY_CHECK_ATC 1
13372 +#define MMU_SETJMP_EXCEPTIONS 1
13373 +
13374 +#if MMU_SETJMP_EXCEPTIONS
13375 +jmp_buf m68k_exception;
13376 +#endif
13377 +
13378 +
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;
13385 +
13386 +int areg_byteinc[] = { 1,1,1,1,1,1,1,2 };
13387 +int imm8_table[] = { 8,1,2,3,4,5,6,7 };
13388 +
13389 +int movem_index1[256];
13390 +int movem_index2[256];
13391 +int movem_next[256];
13392 +
13393 +int fpp_movem_index1[256];
13394 +int fpp_movem_index2[256];
13395 +int fpp_movem_next[256];
13396 +
13397 +cpuop_func *cpufunctbl[65536];
13398 +
13399 +#define COUNT_INSTRS 0
13400 +
13401 +#if COUNT_INSTRS /* {{{ */
13402 +static unsigned long int instrcount[65536];
13403 +static uae_u16 opcodenums[65536];
13404 +
13405 +static int compfn (const void *el1, const void *el2)
13406 +{
13407 + return instrcount[*(const uae_u16 *)el1] < instrcount[*(const uae_u16 *)el2];
13408 +}
13409 +
13410 +static char *icountfilename (void)
13411 +{
13412 + char *name = getenv ("INSNCOUNT");
13413 + if (name)
13414 + return name;
13415 + return COUNT_INSTRS == 2 ? "frequent.68k" : "insncount";
13416 +}
13417 +
13418 +void dump_counts (void)
13419 +{
13420 + FILE *f = fopen (icountfilename (), "w");
13421 + unsigned long int total;
13422 + int i;
13423 +
13424 + write_log ("Writing instruction count file...\n");
13425 + for (i = 0; i < 65536; i++) {
13426 + opcodenums[i] = i;
13427 + total += instrcount[i];
13428 + }
13429 + qsort (opcodenums, 65536, sizeof(uae_u16), compfn);
13430 +
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;
13436 + if (!cnt)
13437 + break;
13438 + dp = table68k + opcodenums[i];
13439 + for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
13440 + ;
13441 + fprintf (f, "%04x: %lu %s\n", opcodenums[i], cnt, lookup->name);
13442 + }
13443 + fclose (f);
13444 +}
13445 +#else
13446 +void dump_counts (void)
13447 +{
13448 +}
13449 +#endif /* }}} */
13450 +
13451 +int broken_in;
13452 +
13453 +static unsigned long op_illg_1 (uae_u32 opcode) REGPARAM;
13454 +
13455 +static unsigned long REGPARAM2 op_illg_1 (uae_u32 opcode)
13456 +{
13457 + op_illg (opcode);
13458 + return 4;
13459 +}
13460 +
13461 +/* {{{ CPU init/table building */
13462 +static void build_cpufunctbl (void)
13463 +{
13464 + int i;
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);
13472 +
13473 + write_log ("Building CPU function table (%d %d %d).\n",
13474 + currprefs.cpu_level, currprefs.cpu_compatible, currprefs.address_space_24);
13475 +
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;
13481 + }
13482 + for (opcode = 0; opcode < 65536; opcode++) {
13483 + cpuop_func *f;
13484 +
13485 + if (table68k[opcode].mnemo == i_ILLG || table68k[opcode].clev > currprefs.cpu_level)
13486 + continue;
13487 +
13488 + if (table68k[opcode].handler != -1) {
13489 + f = cpufunctbl[table68k[opcode].handler];
13490 + if (f == op_illg_1)
13491 + abort();
13492 + cpufunctbl[opcode] = f;
13493 + }
13494 + }
13495 + for (i = 0; tbl[i].handler != NULL; i++) {
13496 + if (tbl[i].specific)
13497 + cpufunctbl[tbl[i].opcode] = tbl[i].handler;
13498 + }
13499 +}
13500 +
13501 +unsigned long cycles_mask, cycles_val;
13502 +
13503 +static void update_68k_cycles (void)
13504 +{
13505 + cycles_mask = 0;
13506 + cycles_val = currprefs.m68k_speed;
13507 + if (currprefs.m68k_speed < 1) {
13508 + cycles_mask = 0xFFFFFFFF;
13509 + cycles_val = 0;
13510 + }
13511 +}
13512 +
13513 +void check_prefs_changed_cpu (void)
13514 +{
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 ();
13520 + }
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 ();
13525 + }
13526 +}
13527 +
13528 +void init_m68k (void)
13529 +{
13530 + int i;
13531 +
13532 + memset(&atc, 0, sizeof(atc));
13533 + regs.mmu_enabled = 0;
13534 +
13535 + update_68k_cycles ();
13536 +
13537 + for (i = 0 ; i < 256 ; i++) {
13538 + int j;
13539 + for (j = 0 ; j < 8 ; j++) {
13540 + if (i & (1 << j)) break;
13541 + }
13542 + movem_index1[i] = j;
13543 + movem_index2[i] = 7-j;
13544 + movem_next[i] = i & (~(1 << j));
13545 + }
13546 + for (i = 0 ; i < 256 ; i++) {
13547 + int j;
13548 + for (j = 7 ; j >= 0 ; j--) {
13549 + if (i & (1 << j)) break;
13550 + }
13551 + fpp_movem_index1[i] = 7-j;
13552 + fpp_movem_index2[i] = j;
13553 + fpp_movem_next[i] = i & (~(1 << j));
13554 + }
13555 +#if COUNT_INSTRS /* {{{ */
13556 + {
13557 + FILE *f = fopen (icountfilename (), "r");
13558 + memset (instrcount, 0, sizeof instrcount);
13559 + if (f) {
13560 + uae_u32 opcode, count, total;
13561 + char name[20];
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;
13566 + }
13567 + fclose(f);
13568 + }
13569 + }
13570 +#endif /* }}} */
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) {
13575 + case 1:
13576 + write_log ("010");
13577 + break;
13578 + case 2:
13579 + write_log ("020");
13580 + break;
13581 + case 3:
13582 + write_log ("020/881");
13583 + break;
13584 + case 4:
13585 + /* Who is going to miss the MMU anyway...? :-) */
13586 + write_log ("040");
13587 + break;
13588 + default:
13589 + write_log ("000");
13590 + break;
13591 + }
13592 + if (currprefs.cpu_compatible)
13593 + write_log (" (compatible mode)");
13594 + write_log ("\n");
13595 +
13596 + read_table68k ();
13597 + do_merges ();
13598 +
13599 + write_log ("%d CPU functions\n", nr_cpuop_funcs);
13600 +
13601 + build_cpufunctbl ();
13602 +}
13603 +/* }}} */
13604 +
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;
13609 +int lastint_no;
13610 +
13611 +uae_s32 ShowEA (FILE *f, int reg, amodes mode, wordsizes size, char *buf)
13612 +{
13613 + uae_u16 dp;
13614 + uae_s8 disp8;
13615 + uae_s16 disp16;
13616 + int r;
13617 + uae_u32 dispreg;
13618 + uaecptr addr;
13619 + uae_s32 offset = 0;
13620 + char buffer[80];
13621 +
13622 + switch (mode){
13623 + case Dreg:
13624 + sprintf (buffer,"D%d", reg);
13625 + break;
13626 + case Areg:
13627 + sprintf (buffer,"A%d", reg);
13628 + break;
13629 + case Aind:
13630 + sprintf (buffer,"(A%d)", reg);
13631 + break;
13632 + case Aipi:
13633 + sprintf (buffer,"(A%d)+", reg);
13634 + break;
13635 + case Apdi:
13636 + sprintf (buffer,"-(A%d)", reg);
13637 + break;
13638 + case Ad16:
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);
13643 + break;
13644 + case Ad8r:
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;
13651 +
13652 + if (dp & 0x100) {
13653 + uae_s32 outer = 0, disp = 0;
13654 + uae_s32 base = m68k_areg(regs,reg);
13655 + char name[10];
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; }
13661 + base += disp;
13662 +
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; }
13665 +
13666 + if (!(dp & 4)) base += dispreg;
13667 + if (dp & 3) base = get_long (base);
13668 + if (dp & 4) base += dispreg;
13669 +
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),
13674 + disp,outer,
13675 + (unsigned long)addr);
13676 + } else {
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);
13682 + }
13683 + break;
13684 + case PC16:
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);
13689 + break;
13690 + case PC8r:
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;
13698 +
13699 + if (dp & 0x100) {
13700 + uae_s32 outer = 0,disp = 0;
13701 + uae_s32 base = addr;
13702 + char name[10];
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; }
13708 + base += disp;
13709 +
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; }
13712 +
13713 + if (!(dp & 4)) base += dispreg;
13714 + if (dp & 3) base = get_long (base);
13715 + if (dp & 4) base += dispreg;
13716 +
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),
13721 + disp,outer,
13722 + (unsigned long)addr);
13723 + } else {
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);
13728 + }
13729 + break;
13730 + case absw:
13731 + sprintf (buffer,"$%08lx", (unsigned long)(uae_s32)(uae_s16)get_iword_1 (m68kpc_offset));
13732 + m68kpc_offset += 2;
13733 + break;
13734 + case absl:
13735 + sprintf (buffer,"$%08lx", (unsigned long)get_ilong_1 (m68kpc_offset));
13736 + m68kpc_offset += 4;
13737 + break;
13738 + case imm:
13739 + switch (size){
13740 + case sz_byte:
13741 + sprintf (buffer,"#$%02x", (unsigned int)(get_iword_1 (m68kpc_offset) & 0xff));
13742 + m68kpc_offset += 2;
13743 + break;
13744 + case sz_word:
13745 + sprintf (buffer,"#$%04x", (unsigned int)(get_iword_1 (m68kpc_offset) & 0xffff));
13746 + m68kpc_offset += 2;
13747 + break;
13748 + case sz_long:
13749 + sprintf (buffer,"#$%08lx", (unsigned long)(get_ilong_1 (m68kpc_offset)));
13750 + m68kpc_offset += 4;
13751 + break;
13752 + default:
13753 + break;
13754 + }
13755 + break;
13756 + case imm0:
13757 + offset = (uae_s32)(uae_s8)get_iword_1 (m68kpc_offset);
13758 + m68kpc_offset += 2;
13759 + sprintf (buffer,"#$%02x", (unsigned int)(offset & 0xff));
13760 + break;
13761 + case imm1:
13762 + offset = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
13763 + m68kpc_offset += 2;
13764 + sprintf (buffer,"#$%04x", (unsigned int)(offset & 0xffff));
13765 + break;
13766 + case imm2:
13767 + offset = (uae_s32)get_ilong_1 (m68kpc_offset);
13768 + m68kpc_offset += 4;
13769 + sprintf (buffer,"#$%08lx", (unsigned long)offset);
13770 + break;
13771 + case immi:
13772 + offset = (uae_s32)(uae_s8)(reg & 0xff);
13773 + sprintf (buffer,"#$%08lx", (unsigned long)offset);
13774 + break;
13775 + default:
13776 + break;
13777 + }
13778 + if (buf == 0)
13779 + fprintf (f, "%s", buffer);
13780 + else
13781 + strcat (buf, buffer);
13782 + return offset;
13783 +}
13784 +
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)
13789 +{
13790 + uae_u16 dp;
13791 + uae_s8 disp8;
13792 + uae_s16 disp16;
13793 + int r;
13794 + uae_u32 dispreg;
13795 + uaecptr addr;
13796 + uae_s32 offset = 0;
13797 +
13798 + switch (mode){
13799 + case Dreg:
13800 + *val = m68k_dreg (regs, reg);
13801 + return 1;
13802 + case Areg:
13803 + *val = m68k_areg (regs, reg);
13804 + return 1;
13805 +
13806 + case Aind:
13807 + case Aipi:
13808 + addr = m68k_areg (regs, reg);
13809 + break;
13810 + case Apdi:
13811 + addr = m68k_areg (regs, reg);
13812 + break;
13813 + case Ad16:
13814 + disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
13815 + addr = m68k_areg(regs,reg) + (uae_s16)disp16;
13816 + break;
13817 + case Ad8r:
13818 + addr = m68k_areg (regs, reg);
13819 + d8r_common:
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;
13826 +
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; }
13834 + base += disp;
13835 +
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; }
13838 +
13839 + if (!(dp & 4)) base += dispreg;
13840 + if (dp & 3) base = get_long (base);
13841 + if (dp & 4) base += dispreg;
13842 +
13843 + addr = base + outer;
13844 + } else {
13845 + addr += (uae_s32)((uae_s8)disp8) + dispreg;
13846 + }
13847 + break;
13848 + case PC16:
13849 + addr = m68k_getpc () + m68kpc_offset;
13850 + disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
13851 + addr += (uae_s16)disp16;
13852 + break;
13853 + case PC8r:
13854 + addr = m68k_getpc () + m68kpc_offset;
13855 + goto d8r_common;
13856 + case absw:
13857 + addr = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
13858 + m68kpc_offset += 2;
13859 + break;
13860 + case absl:
13861 + addr = get_ilong_1 (m68kpc_offset);
13862 + m68kpc_offset += 4;
13863 + break;
13864 + case imm:
13865 + switch (size){
13866 + case sz_byte:
13867 + *val = get_iword_1 (m68kpc_offset) & 0xff;
13868 + m68kpc_offset += 2;
13869 + break;
13870 + case sz_word:
13871 + *val = get_iword_1 (m68kpc_offset) & 0xffff;
13872 + m68kpc_offset += 2;
13873 + break;
13874 + case sz_long:
13875 + *val = get_ilong_1 (m68kpc_offset);
13876 + m68kpc_offset += 4;
13877 + break;
13878 + default:
13879 + break;
13880 + }
13881 + return 1;
13882 + case imm0:
13883 + *val = (uae_s32)(uae_s8)get_iword_1 (m68kpc_offset);
13884 + m68kpc_offset += 2;
13885 + return 1;
13886 + case imm1:
13887 + *val = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
13888 + m68kpc_offset += 2;
13889 + return 1;
13890 + case imm2:
13891 + *val = get_ilong_1 (m68kpc_offset);
13892 + m68kpc_offset += 4;
13893 + return 1;
13894 + case immi:
13895 + *val = (uae_s32)(uae_s8)(reg & 0xff);
13896 + return 1;
13897 + default:
13898 + addr = 0;
13899 + break;
13900 + }
13901 + if ((addr & 1) == 0)
13902 + return 1;
13903 +
13904 + last_addr_for_exception_3 = m68k_getpc () + m68kpc_offset;
13905 + last_fault_for_exception_3 = addr;
13906 + return 0;
13907 +}
13908 +
13909 +uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp)
13910 +{
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;
13920 +
13921 + if ((dp & 0x30) == 0x20) base += (uae_s32)(uae_s16)next_iword();
13922 + if ((dp & 0x30) == 0x30) base += next_ilong();
13923 +
13924 + if ((dp & 0x3) == 0x2) outer = (uae_s32)(uae_s16)next_iword();
13925 + if ((dp & 0x3) == 0x3) outer = next_ilong();
13926 +
13927 + if ((dp & 0x4) == 0) base += regd;
13928 + if (dp & 0x3) base = get_long (base);
13929 + if (dp & 0x4) base += regd;
13930 +
13931 + return base + outer;
13932 + } else {
13933 + return base + (uae_s32)((uae_s8)dp) + regd;
13934 + }
13935 +}
13936 +
13937 +uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp)
13938 +{
13939 + int reg = (dp >> 12) & 15;
13940 + uae_s32 regd = regs.regs[reg];
13941 +#if 1
13942 + if ((dp & 0x800) == 0)
13943 + regd = (uae_s32)(uae_s16)regd;
13944 + return base + (uae_s8)dp + regd;
13945 +#else
13946 + /* Branch-free code... benchmark this again now that
13947 + * things are no longer inline. */
13948 + uae_s32 regd16;
13949 + uae_u32 mask;
13950 + mask = ((dp & 0x800) >> 11) - 1;
13951 + regd16 = (uae_s32)(uae_s16)regd;
13952 + regd16 &= mask;
13953 + mask = ~mask;
13954 + base += (uae_s8)dp;
13955 + regd &= mask;
13956 + regd |= regd16;
13957 + return base + regd;
13958 +#endif
13959 +}
13960 +
13961 +void MakeSR (void)
13962 +{
13963 +#if 0
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);
13973 +#endif
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)
13977 + | GET_CFLG);
13978 +}
13979 +
13980 +void MakeFromSR (void)
13981 +{
13982 + int oldm = regs.m;
13983 + int olds = regs.s;
13984 +
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) {
13997 + if (olds) {
13998 + if (oldm)
13999 + regs.msp = m68k_areg(regs, 7);
14000 + else
14001 + regs.isp = m68k_areg(regs, 7);
14002 + m68k_areg(regs, 7) = regs.usp;
14003 + } else {
14004 + regs.usp = m68k_areg(regs, 7);
14005 + m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp;
14006 + }
14007 + } else if (olds && oldm != regs.m) {
14008 + if (oldm) {
14009 + regs.msp = m68k_areg(regs, 7);
14010 + m68k_areg(regs, 7) = regs.isp;
14011 + } else {
14012 + regs.isp = m68k_areg(regs, 7);
14013 + m68k_areg(regs, 7) = regs.msp;
14014 + }
14015 + }
14016 + } else {
14017 + if (olds != regs.s) {
14018 + if (olds) {
14019 + regs.isp = m68k_areg(regs, 7);
14020 + m68k_areg(regs, 7) = regs.usp;
14021 + } else {
14022 + regs.usp = m68k_areg(regs, 7);
14023 + m68k_areg(regs, 7) = regs.isp;
14024 + }
14025 + }
14026 + }
14027 +
14028 + set_special (SPCFLAG_INT);
14029 + if (regs.t1 || regs.t0)
14030 + set_special (SPCFLAG_TRACE);
14031 + else
14032 + /* Keep SPCFLAG_DOTRACE, we still want a trace exception for
14033 + SR-modifying instructions (including STOP). */
14034 + unset_special (SPCFLAG_TRACE);
14035 +}
14036 +
14037 +/* for building exception frames */
14038 +STATIC_INLINE void exc_push_word(uae_u16 w)
14039 +{
14040 + m68k_areg(regs, 7) -= 2;
14041 + put_word(m68k_areg(regs, 7), w);
14042 +}
14043 +STATIC_INLINE void exc_push_long(uae_u32 l)
14044 +{
14045 + m68k_areg(regs, 7) -= 4;
14046 + put_long (m68k_areg(regs, 7), l);
14047 +}
14048 +
14049 +STATIC_INLINE void exc_make_frame(
14050 + int format,
14051 + uae_u16 sr,
14052 + uae_u32 currpc,
14053 + int nr,
14054 + uae_u32 x0,
14055 + uae_u32 x1
14056 +)
14057 +{
14058 + switch(format) {
14059 + case 4:
14060 + exc_push_long(x1);
14061 + exc_push_long(x0);
14062 + break;
14063 + case 3:
14064 + case 2:
14065 + exc_push_long(x0);
14066 + break;
14067 + }
14068 +
14069 + exc_push_word((format << 12) + (nr * 4)); /* format | vector */
14070 + exc_push_long(currpc);
14071 + exc_push_word(sr);
14072 +}
14073 +
14074 +int in_exception_2 = 0;
14075 +
14076 +void Exception(int nr, uaecptr oldpc)
14077 +{
14078 + uae_u32 currpc = m68k_getpc ();
14079 +
14080 + compiler_flush_jsr_stack();
14081 + MakeSR();
14082 +
14083 + if (!regs.s) {
14084 + regs.usp = m68k_areg(regs, 7);
14085 + if (currprefs.cpu_level >= 2)
14086 + m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp;
14087 + else
14088 + m68k_areg(regs, 7) = regs.isp;
14089 + regs.s = 1;
14090 + }
14091 +
14092 + if (nr == 2 && in_exception_2++) {
14093 + write_log("HALT: Double Bus Error means bad news!\n");
14094 + abort();
14095 + }
14096 +
14097 + if (currprefs.cpu_level > 0) {
14098 +
14099 + if (nr == 2) {
14100 + write_log("Exception 2!!\n");
14101 +
14102 + if (currprefs.cpu_level == 5) {
14103 + /* 68060 */
14104 + exc_make_frame(4,
14105 + regs.sr,
14106 + currpc,
14107 + nr,
14108 + regs.mmu_fault_addr, /* fault address */
14109 + regs.mmu_fslw /* fault status long-word */
14110 + );
14111 + }
14112 + else if (currprefs.cpu_level == 4) {
14113 + /* 68040 */
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,
14131 + regs.sr,
14132 + currpc,
14133 + 2,
14134 + 0,
14135 + 0);
14136 + }
14137 + }
14138 + else if (nr == 3) {
14139 + int i;
14140 +
14141 + exc_make_frame(2,
14142 + regs.sr,
14143 + last_addr_for_exception_3,
14144 + nr,
14145 + last_fault_for_exception_3 & 0xfffffffe,
14146 + 0
14147 + );
14148 +
14149 + } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) {
14150 + /* div by zero, CHK, TRAP or TRACE */
14151 + exc_make_frame(2,
14152 + regs.sr,
14153 + currpc,
14154 + nr,
14155 + oldpc,
14156 + 0
14157 + );
14158 + } else if (regs.m && nr >= 24 && nr < 32) {
14159 + /* interrupts! */
14160 + exc_make_frame(0,
14161 + regs.sr,
14162 + currpc,
14163 + nr,
14164 + 0, 0);
14165 + regs.sr |= (1 << 13);
14166 + regs.msp = m68k_areg(regs, 7);
14167 + m68k_areg(regs, 7) = regs.isp;
14168 +
14169 + exc_make_frame(1, /* throwaway */
14170 + regs.sr,
14171 + currpc,
14172 + nr,
14173 + 0, 0);
14174 + } else {
14175 + exc_make_frame(0,
14176 + regs.sr,
14177 + currpc,
14178 + nr,
14179 + 0, 0);
14180 + }
14181 + } else {
14182 + if (nr == 2 || nr == 3) {
14183 + write_log ("Exception %d! -- this code needs rewriting - good luck!\n", nr);
14184 +
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);
14188 + }
14189 + exc_push_word(regs.sr);
14190 + }
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);
14197 +}
14198 +
14199 +static void Interrupt (int nr)
14200 +{
14201 + assert(nr < 8 && nr >= 0);
14202 + lastint_regs = regs;
14203 + lastint_no = nr;
14204 + Exception(nr+24, 0);
14205 +
14206 + regs.intmask = nr;
14207 + set_special (SPCFLAG_INT);
14208 +}
14209 +
14210 +
14211 +int m68k_move2c (int regno, uae_u32 *regp)
14212 +{
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))
14217 + {
14218 + op_illg (0x4E7B);
14219 + return 0;
14220 + } else {
14221 + switch (regno) {
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;
14229 +
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;
14238 + default:
14239 + write_log("move2x cpu=%d regno=%lx val=%lx\n", currprefs.cpu_level, regno, *regp);
14240 + op_illg (0x4E7B);
14241 + return 0;
14242 + }
14243 + }
14244 + return 1;
14245 +}
14246 +
14247 +int m68k_movec2 (int regno, uae_u32 *regp)
14248 +{
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))
14253 + {
14254 + write_log("movec2 cpu=%d regno=%lx\n", currprefs.cpu_level, regno);
14255 + op_illg (0x4E7A);
14256 + return 0;
14257 + } else {
14258 + switch (regno) {
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;
14275 + default:
14276 + write_log("movec2 cpu=%d regno=%lx\n", currprefs.cpu_level, regno);
14277 + op_illg (0x4E7A);
14278 + return 0;
14279 + }
14280 + }
14281 + return 1;
14282 +}
14283 +
14284 +STATIC_INLINE int
14285 +div_unsigned(uae_u32 src_hi, uae_u32 src_lo, uae_u32 div, uae_u32 *quot, uae_u32 *rem)
14286 +{
14287 + uae_u32 q = 0, cbit = 0;
14288 + int i;
14289 +
14290 + if (div <= src_hi) {
14291 + return 1;
14292 + }
14293 + for (i = 0 ; i < 32 ; i++) {
14294 + cbit = src_hi & 0x80000000ul;
14295 + src_hi <<= 1;
14296 + if (src_lo & 0x80000000ul) src_hi++;
14297 + src_lo <<= 1;
14298 + q = q << 1;
14299 + if (cbit || div <= src_hi) {
14300 + q |= 1;
14301 + src_hi -= div;
14302 + }
14303 + }
14304 + *quot = q;
14305 + *rem = src_hi;
14306 + return 0;
14307 +}
14308 +
14309 +void m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra, uaecptr oldpc)
14310 +{
14311 +#if defined(uae_s64)
14312 + if (src == 0) {
14313 + Exception (5, oldpc);
14314 + return;
14315 + }
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;
14320 +
14321 + if (extra & 0x400) {
14322 + a &= 0xffffffffu;
14323 + a |= (uae_s64)m68k_dreg(regs, extra & 7) << 32;
14324 + }
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))
14329 + {
14330 + SET_VFLG (1);
14331 + SET_NFLG (1);
14332 + SET_CFLG (0);
14333 + } else {
14334 + if (((uae_s32)rem < 0) != ((uae_s64)a < 0)) rem = -rem;
14335 + SET_VFLG (0);
14336 + SET_CFLG (0);
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;
14341 + }
14342 + } else {
14343 + /* unsigned */
14344 + uae_u64 a = (uae_u64)(uae_u32)m68k_dreg(regs, (extra >> 12) & 7);
14345 + uae_u64 quot, rem;
14346 +
14347 + if (extra & 0x400) {
14348 + a &= 0xffffffffu;
14349 + a |= (uae_u64)m68k_dreg(regs, extra & 7) << 32;
14350 + }
14351 + rem = a % (uae_u64)src;
14352 + quot = a / (uae_u64)src;
14353 + if (quot > 0xffffffffu) {
14354 + SET_VFLG (1);
14355 + SET_NFLG (1);
14356 + SET_CFLG (0);
14357 + } else {
14358 + SET_VFLG (0);
14359 + SET_CFLG (0);
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;
14364 + }
14365 + }
14366 +#else
14367 + if (src == 0) {
14368 + Exception (5, oldpc);
14369 + return;
14370 + }
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;
14377 + uae_u32 sign;
14378 +
14379 + if (extra & 0x400) {
14380 + hi = (uae_s32)m68k_dreg(regs, extra & 7);
14381 + }
14382 + save_high = hi;
14383 + sign = (hi ^ src);
14384 + if (hi < 0) {
14385 + hi = ~hi;
14386 + lo = -lo;
14387 + if (lo == 0) hi++;
14388 + }
14389 + if ((uae_s32)src < 0) src = -src;
14390 + if (div_unsigned(hi, lo, src, &quot, &rem) ||
14391 + (sign & 0x80000000) ? quot > 0x80000000 : quot > 0x7fffffff) {
14392 + SET_VFLG (1);
14393 + SET_NFLG (1);
14394 + SET_CFLG (0);
14395 + } else {
14396 + if (sign & 0x80000000) quot = -quot;
14397 + if (((uae_s32)rem < 0) != (save_high < 0)) rem = -rem;
14398 + SET_VFLG (0);
14399 + SET_CFLG (0);
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;
14404 + }
14405 + } else {
14406 + /* unsigned */
14407 + uae_u32 lo = (uae_u32)m68k_dreg(regs, (extra >> 12) & 7);
14408 + uae_u32 hi = 0;
14409 + uae_u32 quot, rem;
14410 +
14411 + if (extra & 0x400) {
14412 + hi = (uae_u32)m68k_dreg(regs, extra & 7);
14413 + }
14414 + if (div_unsigned(hi, lo, src, &quot, &rem)) {
14415 + SET_VFLG (1);
14416 + SET_NFLG (1);
14417 + SET_CFLG (0);
14418 + } else {
14419 + SET_VFLG (0);
14420 + SET_CFLG (0);
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;
14425 + }
14426 + }
14427 +#endif
14428 +}
14429 +
14430 +STATIC_INLINE void
14431 +mul_unsigned(uae_u32 src1, uae_u32 src2, uae_u32 *dst_hi, uae_u32 *dst_lo)
14432 +{
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);
14437 + uae_u32 lo;
14438 +
14439 + lo = r0 + ((r1 << 16) & 0xffff0000ul);
14440 + if (lo < r0) r3++;
14441 + r0 = lo;
14442 + lo = r0 + ((r2 << 16) & 0xffff0000ul);
14443 + if (lo < r0) r3++;
14444 + r3 += ((r1 >> 16) & 0xffff) + ((r2 >> 16) & 0xffff);
14445 + *dst_lo = lo;
14446 + *dst_hi = r3;
14447 +}
14448 +
14449 +void m68k_mull (uae_u32 opcode, uae_u32 src, uae_u16 extra)
14450 +{
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);
14455 +
14456 + a *= (uae_s64)(uae_s32)src;
14457 + SET_VFLG (0);
14458 + SET_CFLG (0);
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))
14465 + {
14466 + SET_VFLG (1);
14467 + }
14468 + m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a;
14469 + } else {
14470 + /* unsigned */
14471 + uae_u64 a = (uae_u64)(uae_u32)m68k_dreg(regs, (extra >> 12) & 7);
14472 +
14473 + a *= (uae_u64)src;
14474 + SET_VFLG (0);
14475 + SET_CFLG (0);
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) {
14481 + SET_VFLG (1);
14482 + }
14483 + m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a;
14484 + }
14485 +#else
14486 + if (extra & 0x800) {
14487 + /* signed variant */
14488 + uae_s32 src1,src2;
14489 + uae_u32 dst_lo,dst_hi;
14490 + uae_u32 sign;
14491 +
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++;
14502 + }
14503 + SET_VFLG (0);
14504 + SET_CFLG (0);
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))
14512 + {
14513 + SET_VFLG (1);
14514 + }
14515 + m68k_dreg(regs, (extra >> 12) & 7) = dst_lo;
14516 + } else {
14517 + /* unsigned */
14518 + uae_u32 dst_lo,dst_hi;
14519 +
14520 + mul_unsigned(src,(uae_u32)m68k_dreg(regs, (extra >> 12) & 7),&dst_hi,&dst_lo);
14521 +
14522 + SET_VFLG (0);
14523 + SET_CFLG (0);
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) {
14529 + SET_VFLG (1);
14530 + }
14531 + m68k_dreg(regs, (extra >> 12) & 7) = dst_lo;
14532 + }
14533 +#endif
14534 +}
14535 +static char* ccnames[] =
14536 +{ "T ","F ","HI","LS","CC","CS","NE","EQ",
14537 + "VC","VS","PL","MI","GE","LT","GT","LE" };
14538 +
14539 +void m68k_reset (void)
14540 +{
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;
14549 + MakeFromSR();
14550 + /* set stack pointer */
14551 + if (regs.s)
14552 + m68k_areg(regs, 7) = regs.isp;
14553 + else
14554 + m68k_areg(regs, 7) = regs.usp;
14555 + return;
14556 + }
14557 +
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 ();
14562 + regs.s = 1;
14563 + regs.m = 0;
14564 + regs.stopped = 0;
14565 + regs.t1 = 0;
14566 + regs.t0 = 0;
14567 + SET_ZFLG (0);
14568 + SET_XFLG (0);
14569 + SET_CFLG (0);
14570 + SET_VFLG (0);
14571 + SET_NFLG (0);
14572 + regs.intmask = 7;
14573 + regs.vbr = regs.sfc = regs.dfc = 0;
14574 + regs.fpcr = regs.fpsr = regs.fpiar = 0;
14575 +}
14576 +
14577 +unsigned long REGPARAM2 op_illg (uae_u32 opcode)
14578 +{
14579 + uaecptr pc = m68k_getpc ();
14580 +
14581 + if (cloanto_rom && (opcode & 0xF100) == 0x7100) {
14582 + m68k_dreg (regs, (opcode >> 9) & 7) = (uae_s8)(opcode & 0xFF);
14583 + m68k_incpc (2);
14584 + fill_prefetch_0 ();
14585 + return 4;
14586 + }
14587 +
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");
14591 + broken_in = 1;
14592 + set_special (SPCFLAG_BRK);
14593 + quit_program = 1;
14594 + }
14595 + if (opcode == 0xFF0D) {
14596 + if ((pc & 0xF80000) == 0xF80000) {
14597 + /* This is from the dummy Kickstart replacement */
14598 + uae_u16 arg = get_iword (2);
14599 + m68k_incpc (4);
14600 + ersatz_perform (arg);
14601 + fill_prefetch_0 ();
14602 + return 4;
14603 + } else if ((pc & 0xFFFF0000) == RTAREA_BASE) {
14604 + /* User-mode STOP replacement */
14605 + m68k_setstopped (1);
14606 + return 4;
14607 + }
14608 + }
14609 +
14610 + if ((opcode & 0xF000) == 0xA000 && (pc & 0xFFFF0000) == RTAREA_BASE) {
14611 + /* Calltrap. */
14612 + m68k_incpc(2);
14613 + call_calltrap (opcode & 0xFFF);
14614 + fill_prefetch_0 ();
14615 + return 4;
14616 + }
14617 +
14618 + if ((opcode & 0xF000) == 0xF000) {
14619 + Exception(0xB,0);
14620 + return 4;
14621 + }
14622 + if ((opcode & 0xF000) == 0xA000) {
14623 + if ((pc & 0xFFFF0000) == RTAREA_BASE) {
14624 + /* Calltrap. */
14625 + call_calltrap (opcode & 0xFFF);
14626 + }
14627 + Exception(0xA,0);
14628 + return 4;
14629 + }
14630 +#if 1
14631 + write_log ("Illegal instruction: %04x at %08lx\n", opcode, pc);
14632 +#endif
14633 + Exception (4,0);
14634 + return 4;
14635 +}
14636 +
14637 +
14638 +
14639 +static int n_insns = 0, n_spcinsns = 0;
14640 +
14641 +static uaecptr last_trace_ad = 0;
14642 +
14643 +static void do_trace (void)
14644 +{
14645 + if (regs.t0 && currprefs.cpu_level >= 2) {
14646 + uae_u16 opcode;
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))
14666 + {
14667 + last_trace_ad = m68k_getpc ();
14668 + unset_special (SPCFLAG_TRACE);
14669 + set_special (SPCFLAG_DOTRACE);
14670 + }
14671 + } else if (regs.t1) {
14672 + last_trace_ad = m68k_getpc ();
14673 + unset_special (SPCFLAG_TRACE);
14674 + set_special (SPCFLAG_DOTRACE);
14675 + }
14676 +}
14677 +
14678 +static int do_specialties (int cycles)
14679 +{
14680 + if (regs.spcflags & SPCFLAG_COPPER)
14681 + do_copper ();
14682 +
14683 + /*n_spcinsns++;*/
14684 + while ((regs.spcflags & SPCFLAG_BLTNASTY) && cycles > 0) {
14685 + int c = blitnasty();
14686 + if (!c) {
14687 + cycles -= 2 * CYCLE_UNIT;
14688 + if (cycles < CYCLE_UNIT)
14689 + cycles = 0;
14690 + c = 1;
14691 + }
14692 + do_cycles (c * CYCLE_UNIT);
14693 + if (regs.spcflags & SPCFLAG_COPPER)
14694 + do_copper ();
14695 + }
14696 +
14697 + run_compiled_code();
14698 + if (regs.spcflags & SPCFLAG_DOTRACE) {
14699 + Exception (9,last_trace_ad);
14700 + }
14701 + while (regs.spcflags & SPCFLAG_STOP) {
14702 + do_cycles (4 * CYCLE_UNIT);
14703 + if (regs.spcflags & SPCFLAG_COPPER)
14704 + do_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);
14712 + }
14713 + }
14714 + }
14715 + if (regs.spcflags & SPCFLAG_TRACE)
14716 + do_trace ();
14717 +
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;
14724 + }
14725 + }
14726 + if (regs.spcflags & SPCFLAG_INT) {
14727 + unset_special (SPCFLAG_INT);
14728 + set_special (SPCFLAG_DOINT);
14729 + }
14730 + if (regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)) {
14731 + unset_special (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE);
14732 + return 1;
14733 + }
14734 + return 0;
14735 +}
14736 +
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)
14740 +{
14741 +#ifdef DEBUG_PREFETCH
14742 + uae_u8 saved_bytes[20];
14743 + uae_u16 *oldpcp;
14744 +#endif
14745 + for (;;) {
14746 + int cycles;
14747 + uae_u32 opcode = get_iword_prefetch (0);
14748 +#ifdef DEBUG_PREFETCH
14749 + if (get_ilong (0) != do_get_mem_long (&regs.prefetch)) {
14750 + write_log ("Prefetch differs from memory.\n");
14751 + debugging = 1;
14752 + return;
14753 + }
14754 + oldpcp = regs.pc_p;
14755 + memcpy (saved_bytes, regs.pc_p, 20);
14756 +#endif
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]++;
14764 +#endif
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");
14770 +#else
14771 + cycles = (*cpufunctbl[opcode])(opcode);
14772 +#endif
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);
14777 + debugging = 1;
14778 + }
14779 +#endif
14780 + /*n_insns++;*/
14781 + cycles &= cycles_mask;
14782 + cycles |= cycles_val;
14783 + do_cycles (cycles);
14784 + if (regs.spcflags) {
14785 + if (do_specialties (cycles))
14786 + return;
14787 + }
14788 + }
14789 +}
14790 +
14791 +#define DEBUG_PREFETCH
14792 +
14793 +/* Same thing, but don't use prefetch to get opcode. */
14794 +static void m68k_run_2 (void)
14795 +{
14796 + for (;;) {
14797 + int cycles;
14798 + uae_u32 opcode = get_iword (0);
14799 +
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]++;
14807 +#endif
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");
14813 +#else
14814 + cycles = (*cpufunctbl[opcode])(opcode);
14815 +#endif
14816 +
14817 + /*n_insns++;*/
14818 + cycles &= cycles_mask;
14819 + cycles |= cycles_val;
14820 + do_cycles (cycles);
14821 + if (regs.spcflags) {
14822 + if (do_specialties (cycles))
14823 + return;
14824 + }
14825 + }
14826 +}
14827 +
14828 +#ifdef X86_ASSEMBLY
14829 +STATIC_INLINE void m68k_run1 (void (*func)(void))
14830 +{
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");
14834 +}
14835 +#else
14836 +#define m68k_run1(F) (F) ()
14837 +#endif
14838 +
14839 +int in_m68k_go = 0;
14840 +
14841 +void m68k_go (int may_quit)
14842 +{
14843 + if (in_m68k_go || !may_quit) {
14844 + write_log ("Bug! m68k_go is not reentrant.\n");
14845 + abort ();
14846 + }
14847 +
14848 + reset_frame_rate_hack ();
14849 + update_68k_cycles ();
14850 +
14851 +#if MMU_SETJMP_EXCEPTIONS
14852 + setjmp(m68k_exception);
14853 +#endif
14854 +
14855 + in_m68k_go++;
14856 + for (;;) {
14857 + if (quit_program > 0) {
14858 + if (quit_program == 1)
14859 + break;
14860 + quit_program = 0;
14861 + if (savestate_state == STATE_RESTORE) {
14862 + restore_state (savestate_filename);
14863 +#if 0
14864 + activate_debugger ();
14865 +#endif
14866 + }
14867 + m68k_reset ();
14868 + reset_all_systems ();
14869 + customreset ();
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);
14875 + }
14876 +
14877 + if (debugging)
14878 + debug ();
14879 + m68k_run1 (currprefs.cpu_compatible ? m68k_run_1 : m68k_run_2);
14880 + }
14881 + in_m68k_go--;
14882 +}
14883 +
14884 +static void m68k_verify (uaecptr addr, uaecptr *nextpc)
14885 +{
14886 + uae_u32 opcode, val;
14887 + struct instr *dp;
14888 +
14889 + opcode = get_iword_1(0);
14890 + last_op_for_exception_3 = opcode;
14891 + m68kpc_offset = 2;
14892 +
14893 + if (cpufunctbl[opcode] == op_illg_1) {
14894 + opcode = 0x4AFC;
14895 + }
14896 + dp = table68k + opcode;
14897 +
14898 + if (dp->suse) {
14899 + if (!verify_ea (dp->sreg, dp->smode, dp->size, &val)) {
14900 + Exception (3, 0);
14901 + return;
14902 + }
14903 + }
14904 + if (dp->duse) {
14905 + if (!verify_ea (dp->dreg, dp->dmode, dp->size, &val)) {
14906 + Exception (3, 0);
14907 + return;
14908 + }
14909 + }
14910 +}
14911 +
14912 +void m68k_disasm (FILE *f, uaecptr addr, uaecptr *nextpc, int cnt)
14913 +{
14914 + uaecptr newpc = 0;
14915 + m68kpc_offset = addr - m68k_getpc ();
14916 + while (cnt-- > 0) {
14917 + char instrname[20],*ccpt;
14918 + int opwords;
14919 + uae_u32 opcode;
14920 + struct mnemolookup *lookup;
14921 + struct instr *dp;
14922 +
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));
14926 + }
14927 + opcode = get_iword_1 (m68kpc_offset);
14928 + m68kpc_offset += 2;
14929 + if (cpufunctbl[opcode] == op_illg_1) {
14930 + opcode = 0x4AFC;
14931 + }
14932 + dp = table68k + opcode;
14933 + for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
14934 + ;
14935 +
14936 + strcpy (instrname, lookup->name);
14937 + ccpt = strstr (instrname, "cc");
14938 + if (ccpt != 0) {
14939 + strncpy (ccpt, ccnames[dp->cc], 2);
14940 + }
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;
14947 + }
14948 +
14949 + if (dp->suse) {
14950 + newpc = m68k_getpc () + m68kpc_offset;
14951 + newpc += ShowEA (f, dp->sreg, dp->smode, dp->size, 0);
14952 + }
14953 + if (dp->suse && dp->duse)
14954 + fprintf (f, ",");
14955 + if (dp->duse) {
14956 + newpc = m68k_getpc () + m68kpc_offset;
14957 + newpc += ShowEA (f, dp->dreg, dp->dmode, dp->size, 0);
14958 + }
14959 + if (ccpt != 0) {
14960 + if (cctrue(dp->cc))
14961 + fprintf (f, " == %08lx (TRUE)", newpc);
14962 + else
14963 + fprintf (f, " == %08lx (FALSE)", newpc);
14964 + } else if ((opcode & 0xff00) == 0x6100) /* BSR */
14965 + fprintf (f, " == %08lx", newpc);
14966 + fprintf (f, "\n");
14967 + }
14968 + if (nextpc)
14969 + *nextpc = m68k_getpc () + m68kpc_offset;
14970 +}
14971 +
14972 +void m68k_dumpstate (FILE *f, uaecptr *nextpc)
14973 +{
14974 + int i;
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");
14978 + }
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");
14982 + }
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");
14994 + }
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(&regs.prefetch));
15002 +
15003 + fprintf (f, "this PC: %08lx\n", m68k_getpc());
15004 + m68k_disasm (f, m68k_getpc (), nextpc, 1);
15005 + if (nextpc)
15006 + fprintf (f, "next PC: %08lx\n", *nextpc);
15007 +}
15008 +
15009 +
15010 +/* {{{ CPU save/restore code */
15011 +
15012 +#define CPUTYPE_EC 1
15013 +#define CPUMODE_HALT 1
15014 +
15015 +uae_u8 *restore_cpu (uae_u8 *src)
15016 +{
15017 + int i,model,flags;
15018 + uae_u32 l;
15019 +
15020 + model = restore_u32();
15021 + switch (model) {
15022 + case 68000:
15023 + currprefs.cpu_level = 0;
15024 + break;
15025 + case 68010:
15026 + currprefs.cpu_level = 1;
15027 + break;
15028 + case 68020:
15029 + currprefs.cpu_level = 2;
15030 + break;
15031 + default:
15032 + write_log ("Unknown cpu type %d\n", model);
15033 + break;
15034 + }
15035 +
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
15045 + restore. */
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);
15055 + } else
15056 + regs.stopped = 0;
15057 + if (model >= 68010) {
15058 + regs.dfc = restore_u32 ();
15059 + regs.sfc = restore_u32 ();
15060 + regs.vbr = restore_u32 ();
15061 + }
15062 + if (model >= 68020) {
15063 + regs.caar = restore_u32 ();
15064 + regs.cacr = restore_u32 ();
15065 + regs.msp = restore_u32 ();
15066 + }
15067 + write_log ("CPU %d%s%03d, PC=%08.8X\n",
15068 + model/1000, flags & 1 ? "EC" : "", model % 1000, regs.pc);
15069 +
15070 + return src;
15071 +}
15072 +
15073 +static int cpumodel[] = { 68000, 68010, 68020, 68020 };
15074 +
15075 +uae_u8 *save_cpu (int *len)
15076 +{
15077 + uae_u8 *dstbak,*dst;
15078 + int model,i;
15079 +
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 */
15087 + MakeSR ();
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 */
15096 + }
15097 + if(model >= 68020) {
15098 + save_u32 (regs.caar); /* CAAR */
15099 + save_u32 (regs.cacr); /* CACR */
15100 + save_u32 (regs.msp); /* MSP */
15101 + }
15102 + *len = dst - dstbak;
15103 + return dstbak;
15104 +}
15105 +
15106 +/* }}} */
15107 +
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 @@
15112 {
15113 int i;
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);
15117
15118 return;
15119
15120 @@ -333,7 +333,7 @@
15121 char *uaememptr = 0;
15122 int i;
15123
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;
15131 break;
15132 }
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 */
15136
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);
15142 +
15143 + if (regs.mmu_enabled) {
15144 + mmu_make_transparent_region(gfxmem_start, allocated_gfxmem, 1);
15145 + }
15146 +
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
15153 @@ -0,0 +1,2509 @@
15154 +/*
15155 + * UAE - The U*nix Amiga Emulator
15156 + *
15157 + * Picasso96 Support Module
15158 + *
15159 + * Copyright 1997 Brian King <Brian_King@Mitel.com, Brian_King@Cloanto.com>
15160 + *
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.
15179 + *
15180 + * TODO:
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.
15184 + */
15185 +
15186 +#include "sysconfig.h"
15187 +#include "sysdeps.h"
15188 +
15189 +#include "config.h"
15190 +#include "options.h"
15191 +#include "threaddep/thread.h"
15192 +#include "uae.h"
15193 +#include "memory.h"
15194 +#include "custom.h"
15195 +#include "newcpu.h"
15196 +#include "xwin.h"
15197 +#include "picasso96.h"
15198 +
15199 +#ifdef PICASSO96
15200 +
15201 +#define P96TRACING_ENABLED 0
15202 +#if P96TRACING_ENABLED
15203 +#define P96TRACE(x) do { write_log x; } while(0)
15204 +#else
15205 +#define P96TRACE(x)
15206 +#endif
15207 +
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;
15216 +
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);
15220 +
15221 +static uae_u8 all_ones_bitmap, all_zeros_bitmap;
15222 +
15223 +struct picasso96_state_struct picasso96_state;
15224 +struct picasso_vidbuf_description picasso_vidinfo;
15225 +
15226 +/* These are the maximum resolutions... They are filled in by GetSupportedResolutions() */
15227 +/* have to fill this in, otherwise problems occur
15228 + * @@@ ??? what problems?
15229 + */
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 };
15235 +
15236 +uae_u16 picasso96_pixel_format = RGBFF_CHUNKY;
15237 +
15238 +struct PicassoResolution DisplayModes[MAX_PICASSO_MODES];
15239 +
15240 +static int mode_count = 0;
15241 +
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;
15247 +
15248 +static uae_u32 p2ctab[256][2];
15249 +
15250 +/*
15251 + * Debugging dumps
15252 + */
15253 +
15254 +static void DumpModeInfoStructure (uaecptr amigamodeinfoptr)
15255 +{
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));
15281 +}
15282 +
15283 +static void DumpLibResolutionStructure (uaecptr amigalibresptr)
15284 +{
15285 + int i;
15286 + uaecptr amigamodeinfoptr;
15287 + struct LibResolution *uaememptr = (struct LibResolution *)get_real_address(amigalibresptr);
15288 +
15289 + return;
15290 +
15291 + write_log ("LibResolution Structure Dump:\n");
15292 +
15293 + if (get_long (amigalibresptr + PSSO_LibResolution_DisplayID) == 0xFFFFFFFF) {
15294 + write_log (" Finished With LibResolutions...\n");
15295 + } else {
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);
15306 + }
15307 + write_log (" BoardInfo = 0x%x\n", get_long (amigalibresptr + PSSO_LibResolution_BoardInfo));
15308 + }
15309 +}
15310 +
15311 +static char binary_byte[9];
15312 +
15313 +static char *BuildBinaryString (uae_u8 value)
15314 +{
15315 + int i;
15316 + for (i = 0; i < 8; i++) {
15317 + binary_byte[i] = (value & (1 << (7 - i))) ? '#' : '.';
15318 + }
15319 + binary_byte[8] = '\0';
15320 + return binary_byte;
15321 +}
15322 +
15323 +static void DumpPattern (struct Pattern *patt)
15324 +{
15325 + uae_u8 *mem;
15326 + int row, col;
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++));
15331 + }
15332 + write_log ("\n");
15333 + }
15334 +}
15335 +
15336 +static void DumpTemplate (struct Template *tmp, uae_u16 w, uae_u16 h)
15337 +{
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++));
15346 + }
15347 + write_log ("\n");
15348 + }
15349 +}
15350 +
15351 +int picasso_nr_resolutions (void)
15352 +{
15353 + return mode_count;
15354 +}
15355 +
15356 +static void ShowSupportedResolutions (void)
15357 +{
15358 + int i;
15359 +
15360 + return;
15361 +
15362 + for (i = 0; i < mode_count; i++)
15363 + write_log ("%s\n", DisplayModes[i].name);
15364 +}
15365 +
15366 +static uae_u8 GetBytesPerPixel (uae_u32 RGBfmt)
15367 +{
15368 + switch (RGBfmt) {
15369 + case RGBFB_CLUT:
15370 + return 1;
15371 +
15372 + case RGBFB_A8R8G8B8:
15373 + case RGBFB_A8B8G8R8:
15374 + case RGBFB_R8G8B8A8:
15375 + case RGBFB_B8G8R8A8:
15376 + return 4;
15377 +
15378 + case RGBFB_B8G8R8:
15379 + case RGBFB_R8G8B8:
15380 + return 3;
15381 +
15382 + case RGBFB_R5G5B5:
15383 + case RGBFB_R5G6B5:
15384 + case RGBFB_R5G6B5PC:
15385 + case RGBFB_R5G5B5PC:
15386 + case RGBFB_B5G6R5PC:
15387 + case RGBFB_B5G5R5PC:
15388 + return 2;
15389 + default:
15390 + write_log ("ERROR - GetBytesPerPixel() was unsuccessful with 0x%x?!\n", RGBfmt);
15391 + return 0;
15392 + }
15393 +}
15394 +
15395 +/*
15396 + * Amiga <-> native structure conversion functions
15397 + */
15398 +
15399 +static int CopyRenderInfoStructureA2U (uaecptr amigamemptr, struct RenderInfo *ri)
15400 +{
15401 + uaecptr memp = get_long (amigamemptr + PSSO_RenderInfo_Memory);
15402 +
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);
15407 + return 1;
15408 + }
15409 + write_log ("ERROR - Invalid RenderInfo memory area...\n");
15410 + return 0;
15411 +}
15412 +
15413 +static int CopyPatternStructureA2U (uaecptr amigamemptr, struct Pattern *pattern)
15414 +{
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);
15424 + return 1;
15425 + }
15426 + write_log ("ERROR - Invalid Pattern memory area...\n");
15427 + return 0;
15428 +}
15429 +
15430 +static void CopyColorIndexMappingA2U (uaecptr amigamemptr, struct ColorIndexMapping *cim)
15431 +{
15432 + int i;
15433 + cim->ColorMask = get_long (amigamemptr);
15434 + for (i = 0; i < 256; i++, amigamemptr += 4)
15435 + cim->Colors[i] = get_long (amigamemptr + 4);
15436 +}
15437 +
15438 +static int CopyBitMapStructureA2U (uaecptr amigamemptr, struct BitMap *bm)
15439 +{
15440 + int i;
15441 +
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);
15446 +
15447 + for (i = 0; i < bm->Depth; i++) {
15448 + uaecptr plane = get_long (amigamemptr + PSSO_BitMap_Planes + i * 4);
15449 + switch (plane) {
15450 + case 0:
15451 + bm->Planes[i] = &all_zeros_bitmap;
15452 + break;
15453 + case 0xFFFFFFFF:
15454 + bm->Planes[i] = &all_ones_bitmap;
15455 + break;
15456 + default:
15457 + if (valid_address (plane, bm->BytesPerRow * bm->Rows))
15458 + bm->Planes[i] = get_real_address (plane);
15459 + else
15460 + return 0;
15461 + break;
15462 + }
15463 + }
15464 + return 1;
15465 +}
15466 +
15467 +static int CopyTemplateStructureA2U (uaecptr amigamemptr, struct Template *tmpl)
15468 +{
15469 + uaecptr memp = get_long (amigamemptr + PSSO_Template_Memory);
15470 +
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);
15478 + return 1;
15479 + }
15480 + write_log ("ERROR - Invalid Template memory area...\n");
15481 + return 0;
15482 +}
15483 +
15484 +static void CopyLibResolutionStructureU2A (struct LibResolution *libres, uaecptr amigamemptr)
15485 +{
15486 + char *uaememptr = 0;
15487 + int i;
15488 +
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]);
15498 +#if 0
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);
15503 +#endif
15504 + put_long (amigamemptr + 10, amigamemptr + PSSO_LibResolution_P96ID);
15505 + put_long (amigamemptr + PSSO_LibResolution_BoardInfo, libres->BoardInfo);
15506 +}
15507 +
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)
15511 +{
15512 + uaecptr amigamemptr = 0;
15513 +
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 */
15519 +
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 */
15523 + } else {
15524 + amigamemptr = get_long (list + 8); /* get the lh_TailPred contents */
15525 +
15526 + put_long (list + 8, node); /* point the lh_TailPred to our new node */
15527 +
15528 + /* Adjust the previous lh_TailPred node */
15529 + put_long (amigamemptr, node); /* point the ln_Succ to our new node */
15530 +
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 */
15534 + }
15535 +}
15536 +
15537 +/*
15538 + * Functions to perform an action on the real screen
15539 + */
15540 +
15541 +/*
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.
15545 + */
15546 +
15547 +static void do_fillrect (uae_u8 * src, int x, int y, int width, int height,
15548 + uae_u32 pen, int Bpp, RGBFTYPE rgbtype)
15549 +{
15550 + uae_u8 *dst;
15551 +
15552 + /* Clipping. */
15553 + x -= picasso96_state.XOffset;
15554 + y -= picasso96_state.YOffset;
15555 + if (x < 0) {
15556 + width += x;
15557 + x = 0;
15558 + }
15559 + if (y < 0) {
15560 + height += y;
15561 + y = 0;
15562 + }
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;
15567 +
15568 + if (width <= 0 || height <= 0)
15569 + return;
15570 +
15571 + /* Try OS specific fillrect function here; and return if successful. */
15572 +
15573 + DX_Invalidate (y, y + height - 1);
15574 + if (!picasso_vidinfo.extra_mem)
15575 + return;
15576 +
15577 + width *= picasso96_state.BytesPerPixel;
15578 + dst = gfx_lock_picasso ();
15579 + if (!dst)
15580 + goto out;
15581 +
15582 + dst += y * picasso_vidinfo.rowbytes + x * picasso_vidinfo.pixbytes;
15583 + if (picasso_vidinfo.rgbformat == picasso96_state.RGBFormat) {
15584 + if (Bpp == 1) {
15585 + while (height-- > 0) {
15586 + memset (dst, pen, width);
15587 + dst += picasso_vidinfo.rowbytes;
15588 + }
15589 + } else {
15590 + while (height-- > 0) {
15591 + memcpy (dst, src, width);
15592 + dst += picasso_vidinfo.rowbytes;
15593 + }
15594 + }
15595 + } else {
15596 + int psiz = GetBytesPerPixel (picasso_vidinfo.rgbformat);
15597 + if (picasso96_state.RGBFormat != RGBFB_CHUNKY)
15598 + abort ();
15599 +
15600 + while (height-- > 0) {
15601 + int i;
15602 + switch (psiz) {
15603 + case 2:
15604 + for (i = 0; i < width; i++)
15605 + *((uae_u16 *) dst + i) = picasso_vidinfo.clut[src[i]];
15606 + break;
15607 + case 4:
15608 + for (i = 0; i < width; i++)
15609 + *((uae_u32 *) dst + i) = picasso_vidinfo.clut[src[i]];
15610 + break;
15611 + default:
15612 + abort ();
15613 + }
15614 + dst += picasso_vidinfo.rowbytes;
15615 + }
15616 + }
15617 + out:
15618 + gfx_unlock_picasso ();
15619 +}
15620 +
15621 +/*
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
15626 + * srcp.
15627 + */
15628 +
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)
15632 +{
15633 + int xoff = picasso96_state.XOffset;
15634 + int yoff = picasso96_state.YOffset;
15635 + uae_u8 *srcp, *dstp;
15636 +
15637 + /* Clipping. */
15638 + dstx -= xoff;
15639 + dsty -= yoff;
15640 + if (srcy < yoff || srcx < xoff
15641 + || srcx - xoff + width > picasso96_state.Width
15642 + || srcy - yoff + height > picasso96_state.Height)
15643 + {
15644 + can_do_blit = 0;
15645 + }
15646 + if (dstx < 0) {
15647 + srcx -= dstx;
15648 + width += dstx;
15649 + dstx = 0;
15650 + }
15651 + if (dsty < 0) {
15652 + srcy -= dsty;
15653 + height += dsty;
15654 + dsty = 0;
15655 + }
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)
15661 + return;
15662 +
15663 + /* If this RenderInfo points at something else than the currently visible
15664 + * screen, we must ignore the blit. */
15665 + if (can_do_blit) {
15666 + /*
15667 + * Call OS blitting function that can do it in video memory.
15668 + * Should return if it was successful
15669 + */
15670 + }
15671 +
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)
15676 + return;
15677 +
15678 + dstp = gfx_lock_picasso ();
15679 + if (dstp == 0)
15680 + goto out;
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));
15685 +
15686 + srcp = ri->Memory + srcx * Bpp + srcy * ri->BytesPerRow;
15687 + if (picasso_vidinfo.rgbformat == picasso96_state.RGBFormat) {
15688 + width *= Bpp;
15689 + while (height-- > 0) {
15690 + memcpy (dstp, srcp, width);
15691 + srcp += ri->BytesPerRow;
15692 + dstp += picasso_vidinfo.rowbytes;
15693 + }
15694 + } else {
15695 + int psiz = GetBytesPerPixel (picasso_vidinfo.rgbformat);
15696 + if (picasso96_state.RGBFormat != RGBFB_CHUNKY)
15697 + abort ();
15698 +
15699 + while (height-- > 0) {
15700 + int i;
15701 + switch (psiz) {
15702 + case 2:
15703 + for (i = 0; i < width; i++)
15704 + *((uae_u16 *) dstp + i) = picasso_vidinfo.clut[srcp[i]];
15705 + break;
15706 + case 4:
15707 + for (i = 0; i < width; i++)
15708 + *((uae_u32 *) dstp + i) = picasso_vidinfo.clut[srcp[i]];
15709 + break;
15710 + default:
15711 + abort ();
15712 + }
15713 + srcp += ri->BytesPerRow;
15714 + dstp += picasso_vidinfo.rowbytes;
15715 + }
15716 + }
15717 + out:
15718 + gfx_unlock_picasso ();
15719 +}
15720 +
15721 +/*
15722 + * Invert a rectangle on the screen.
15723 + */
15724 +
15725 +static void do_invertrect (struct RenderInfo *ri, int Bpp, int x, int y, int width, int height)
15726 +{
15727 +#if 0
15728 + /* Clipping. */
15729 + x -= picasso96_state.XOffset;
15730 + y -= picasso96_state.YOffset;
15731 + if (x < 0) {
15732 + width += x;
15733 + x = 0;
15734 + }
15735 + if (y < 0) {
15736 + height += y;
15737 + y = 0;
15738 + }
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;
15743 +
15744 + if (width <= 0 || height <= 0)
15745 + return;
15746 +
15747 +#endif
15748 + /* TODO: Try OS specific invertrect function here; and return if successful. */
15749 +
15750 + do_blit (ri, Bpp, x, y, x, y, width, height, BLIT_SRC, 0);
15751 +}
15752 +
15753 +static uaecptr wgfx_linestart;
15754 +static uaecptr wgfx_lineend;
15755 +static uaecptr wgfx_min, wgfx_max;
15756 +static long wgfx_y;
15757 +
15758 +static void wgfx_do_flushline (void)
15759 +{
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;
15765 +
15766 + wgfx_y -= picasso96_state.YOffset;
15767 + if (wgfx_y < 0 || wgfx_y >= picasso96_state.Height)
15768 + goto out1;
15769 +
15770 + DX_Invalidate (wgfx_y, wgfx_y);
15771 + if (!picasso_vidinfo.extra_mem)
15772 + goto out1;
15773 +
15774 + x0 = wgfx_min - wgfx_linestart;
15775 + width = wgfx_max - wgfx_min;
15776 + x0 -= picasso96_state.XOffset * fb_bpp;
15777 + if (x0 < 0) {
15778 + width += x0;
15779 + wgfx_min += x0;
15780 + x0 = 0;
15781 + }
15782 + if (x0 + width > picasso96_state.Width * fb_bpp)
15783 + width = picasso96_state.Width * fb_bpp - x0;
15784 +
15785 + dstp = gfx_lock_picasso ();
15786 + if (dstp == 0)
15787 + goto out;
15788 +
15789 + P96TRACE(("flushing %d\n", wgfx_y));
15790 + src = gfxmemory + wgfx_min;
15791 +
15792 + if (picasso_vidinfo.rgbformat == picasso96_state.RGBFormat) {
15793 + dstp += wgfx_y * picasso_vidinfo.rowbytes + x0;
15794 + memcpy (dstp, src, width);
15795 + } else {
15796 + int i;
15797 +
15798 + if (picasso96_state.RGBFormat != RGBFB_CHUNKY)
15799 + abort ();
15800 +
15801 + dstp += wgfx_y * picasso_vidinfo.rowbytes + x0 * Bpp;
15802 + switch (Bpp) {
15803 + case 2:
15804 + for (i = 0; i < width; i++)
15805 + *((uae_u16 *) dstp + i) = picasso_vidinfo.clut[src[i]];
15806 + break;
15807 + case 4:
15808 + for (i = 0; i < width; i++)
15809 + *((uae_u32 *) dstp + i) = picasso_vidinfo.clut[src[i]];
15810 + break;
15811 + default:
15812 + abort ();
15813 + }
15814 + }
15815 +
15816 + out:
15817 + gfx_unlock_picasso ();
15818 + out1:
15819 + wgfx_linestart = 0xFFFFFFFF;
15820 +}
15821 +
15822 +STATIC_INLINE void wgfx_flushline (void)
15823 +{
15824 + if (wgfx_linestart == 0xFFFFFFFF || !picasso_on)
15825 + return;
15826 + wgfx_do_flushline ();
15827 +}
15828 +
15829 +static int renderinfo_is_current_screen (struct RenderInfo *ri)
15830 +{
15831 + if (!picasso_on)
15832 + return 0;
15833 + if (ri->Memory != gfxmemory + (picasso96_state.Address - gfxmem_start))
15834 + return 0;
15835 +
15836 + return 1;
15837 +}
15838 +
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.
15844 + */
15845 +void picasso_refresh (void)
15846 +{
15847 + struct RenderInfo ri;
15848 +
15849 + if (!picasso_on)
15850 + return;
15851 +
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;
15860 +
15861 + if (set_panning_called) {
15862 + width = picasso96_state.VirtualWidth;
15863 + height = picasso96_state.VirtualHeight;
15864 + } else {
15865 + width = picasso96_state.Width;
15866 + height = picasso96_state.Height;
15867 + }
15868 +
15869 + do_blit (&ri, picasso96_state.BytesPerPixel, 0, 0, 0, 0, width, height, BLIT_SRC, 0);
15870 + } else
15871 + write_log ("ERROR - picasso_refresh() can't refresh!\n");
15872 +}
15873 +
15874 +/*
15875 + * BOOL FindCard(struct BoardInfo *bi); and
15876 + *
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.
15888 + */
15889 +uae_u32 picasso_FindCard (void)
15890 +{
15891 + uaecptr AmigaBoardInfo = m68k_areg (regs, 0);
15892 + /* NOTES: See BoardInfo struct definition in Picasso96 dev info */
15893 +
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);
15899 +
15900 + picasso96_state.CardFound = 1; /* mark our "card" as being found */
15901 + return -1;
15902 + } else
15903 + return 0;
15904 +}
15905 +
15906 +static void FillBoardInfo (uaecptr amigamemptr, struct LibResolution *res, struct PicassoResolution *dm)
15907 +{
15908 + char *uaememptr;
15909 + switch (dm->depth) {
15910 + case 1:
15911 + res->Modes[CHUNKY] = amigamemptr;
15912 + break;
15913 + case 2:
15914 + res->Modes[HICOLOR] = amigamemptr;
15915 + break;
15916 + case 3:
15917 + res->Modes[TRUECOLOR] = amigamemptr;
15918 + break;
15919 + default:
15920 + res->Modes[TRUEALPHA] = amigamemptr;
15921 + break;
15922 + }
15923 + uaememptr = get_real_address(amigamemptr);
15924 + memset (uaememptr, 0, PSSO_ModeInfo_sizeof); /* zero out our ModeInfo struct */
15925 +
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);
15936 +
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);
15941 +
15942 + put_byte (amigamemptr + PSSO_ModeInfo_first_union, 98);
15943 + put_byte (amigamemptr + PSSO_ModeInfo_second_union, 14);
15944 +
15945 + put_long (amigamemptr + PSSO_ModeInfo_PixelClock, dm->res.width * dm->res.height * dm->refresh);
15946 +}
15947 +
15948 +static uae_u32 AssignModeID (int i, int count)
15949 +{
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;
15968 +
15969 + return 0x50091000 + count * 0x10000;
15970 +}
15971 +
15972 +/****************************************
15973 +* InitCard()
15974 +*
15975 +* a2: BoardInfo structure ptr - Amiga-based address in Intel endian-format
15976 +*
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)
15987 +*/
15988 +uae_u32 picasso_InitCard (void)
15989 +{
15990 + struct LibResolution res;
15991 + int i;
15992 + int ModeInfoStructureCount = 1, LibResolutionStructureCount = 0;
15993 + uaecptr amigamemptr = 0;
15994 + uaecptr AmigaBoardInfo = m68k_areg (regs, 2);
15995 +
15996 + if (regs.mmu_enabled) {
15997 + mmu_make_transparent_region(gfxmem_start, allocated_gfxmem, 1);
15998 + }
15999 +
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);
16014 +
16015 + for (i = 0; i < mode_count;) {
16016 + int j = i;
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;
16036 +
16037 + do {
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]);
16044 + }
16045 + i++;
16046 + } while (i < mode_count
16047 + && DisplayModes[i].res.width == DisplayModes[j].res.width
16048 + && DisplayModes[i].res.height == DisplayModes[j].res.height);
16049 +
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);
16054 + }
16055 +
16056 + return 0;
16057 +}
16058 +
16059 +extern int x_size, y_size;
16060 +
16061 +/*
16062 + * SetSwitch:
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.
16070 + *
16071 + * NOTE: Return the opposite of the switch-state. BDK
16072 +*/
16073 +uae_u32 picasso_SetSwitch (void)
16074 +{
16075 + uae_u16 flag = m68k_dreg (regs, 0) & 0xFFFF;
16076 +
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;
16081 +#if 0
16082 + write_log ("SetSwitch() - trying to show %s screen\n", flag ? "picasso96" : "amiga");
16083 +#endif
16084 + /* Put old switch-state in D0 */
16085 + return !flag;
16086 +}
16087 +
16088 +void picasso_enablescreen (int on)
16089 +{
16090 + wgfx_linestart = 0xFFFFFFFF;
16091 + picasso_refresh ();
16092 +#if 0
16093 + write_log ("SetSwitch() - showing %s screen\n", on ? "picasso96" : "amiga");
16094 +#endif
16095 +}
16096 +
16097 +static int first_color_changed = 256;
16098 +static int last_color_changed = -1;
16099 +
16100 +void picasso_handle_vsync (void)
16101 +{
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 ();
16107 + }
16108 +
16109 + first_color_changed = 256;
16110 + last_color_changed = -1;
16111 +}
16112 +
16113 +void picasso_clip_mouse (int *px, int *py)
16114 +{
16115 + int xoff = picasso96_state.XOffset;
16116 + int yoff = picasso96_state.YOffset;
16117 + if (*px < -xoff)
16118 + *px = -xoff;
16119 + if (*px + xoff > picasso_vidinfo.width)
16120 + *px = picasso_vidinfo.width - xoff;
16121 + if (*py < -yoff)
16122 + *py = -yoff;
16123 + if (*py + yoff > picasso_vidinfo.height)
16124 + *py = picasso_vidinfo.height - yoff;
16125 +}
16126 +
16127 +/*
16128 + * SetColorArray:
16129 + * a0: struct BoardInfo
16130 + * d0.w: startindex
16131 + * d1.w: count
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.
16138 + */
16139 +uae_u32 picasso_SetColorArray (void)
16140 +{
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);
16145 + int i;
16146 + uaecptr boardinfo = m68k_areg (regs, 0);
16147 + uaecptr clut = boardinfo + PSSO_BoardInfo_CLUT + start * 3;
16148 + int changed = 0;
16149 +
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);
16154 +
16155 + changed |= (picasso96_state.CLUT[i].Red != r || picasso96_state.CLUT[i].Green != g || picasso96_state.CLUT[i].Blue != b);
16156 +
16157 + picasso96_state.CLUT[i].Red = r;
16158 + picasso96_state.CLUT[i].Green = g;
16159 + picasso96_state.CLUT[i].Blue = b;
16160 + clut += 3;
16161 + }
16162 + if (changed) {
16163 + if (start < first_color_changed)
16164 + first_color_changed = start;
16165 + if (start + count > last_color_changed)
16166 + last_color_changed = start + count;
16167 + }
16168 + /*write_log ("SetColorArray(%d,%d)\n", start, count); */
16169 + return 1;
16170 +}
16171 +
16172 +/*
16173 + * SetDAC:
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.
16179 + */
16180 +uae_u32 picasso_SetDAC (void)
16181 +{
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 */
16184 +
16185 + write_log ("SetDAC()\n");
16186 + return 1;
16187 +}
16188 +
16189 +static void init_picasso_screen (void)
16190 +{
16191 + int width = picasso96_state.Width;
16192 + int height = picasso96_state.Height;
16193 + int vwidth = picasso96_state.VirtualWidth;
16194 + int vheight = picasso96_state.VirtualHeight;
16195 + int xoff = 0;
16196 + int yoff = 0;
16197 +
16198 + if (!set_gc_called)
16199 + return;
16200 +
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;
16205 + }
16206 +
16207 + gfx_set_picasso_modeinfo (width, height, picasso96_state.GC_Depth, picasso96_state.RGBFormat);
16208 + DX_SetPalette (0, 256);
16209 +
16210 + wgfx_linestart = 0xFFFFFFFF;
16211 + picasso_refresh ();
16212 +}
16213 +
16214 +/*
16215 + * SetGC:
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
16223 + * own functions.
16224 + */
16225 +uae_u32 picasso_SetGC (void)
16226 +{
16227 + /* Fill in some static UAE related structure about this new ModeInfo setting */
16228 + uaecptr modeinfo = m68k_areg (regs, 1);
16229 +
16230 + picasso96_state.Width = get_word (modeinfo + PSSO_ModeInfo_Width);
16231 + picasso96_state.VirtualWidth = picasso96_state.Width; /* in case SetPanning doesn't get called */
16232 +
16233 + picasso96_state.Height = get_word (modeinfo + PSSO_ModeInfo_Height);
16234 + picasso96_state.VirtualHeight = picasso96_state.Height;
16235 +
16236 + picasso96_state.GC_Depth = get_byte (modeinfo + PSSO_ModeInfo_Depth);
16237 + picasso96_state.GC_Flags = get_byte (modeinfo + PSSO_ModeInfo_Flags);
16238 +
16239 + P96TRACE (("SetGC(%d,%d,%d)\n", picasso96_state.Width, picasso96_state.Height, picasso96_state.GC_Depth));
16240 +
16241 + set_gc_called = 1; /* @@@ when do we need to reset this? */
16242 + init_picasso_screen ();
16243 + return 1;
16244 +}
16245 +
16246 +/*
16247 + * SetPanning:
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.
16262 +
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.
16267 + */
16268 +uae_u32 picasso_SetPanning (void)
16269 +{
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;
16276 +#if 0
16277 + /* @@@ This is in WinUAE, but it breaks things. */
16278 + if (oldscr == 0) {
16279 + oldscr = start_of_screen;
16280 + }
16281 + if ((oldscr != start_of_screen)) {
16282 + set_gc_called = 0;
16283 + oldscr = start_of_screen;
16284 + }
16285 +#endif
16286 +
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;
16295 +
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));
16299 +
16300 + init_picasso_screen ();
16301 +
16302 + lastmx += oldxoff - picasso96_state.XOffset;
16303 + lastmy += oldyoff - picasso96_state.YOffset;
16304 +
16305 + return 1;
16306 +}
16307 +
16308 +static void do_xor8 (uae_u8 * ptr, long len, uae_u32 val)
16309 +{
16310 + int i;
16311 +#if 0 && defined ALIGN_POINTER_TO32
16312 + int align_adjust = ALIGN_POINTER_TO32 (ptr);
16313 + int len2;
16314 +
16315 + len -= align_adjust;
16316 + while (align_adjust) {
16317 + *ptr ^= val;
16318 + ptr++;
16319 + align_adjust--;
16320 + }
16321 + len2 = len >> 2;
16322 + len -= len2 << 2;
16323 + for (i = 0; i < len2; i++, ptr += 4) {
16324 + *(uae_u32 *) ptr ^= val;
16325 + }
16326 + while (len) {
16327 + *ptr ^= val;
16328 + ptr++;
16329 + len--;
16330 + }
16331 + return;
16332 +#endif
16333 + for (i = 0; i < len; i++, ptr++) {
16334 + do_put_mem_byte (ptr, do_get_mem_byte (ptr) ^ val);
16335 + }
16336 +}
16337 +
16338 +/*
16339 + * InvertRect:
16340 + *
16341 + * Inputs:
16342 + * a0:struct BoardInfo *bi
16343 + * a1:struct RenderInfo *ri
16344 + * d0.w:X
16345 + * d1.w:Y
16346 + * d2.w:Width
16347 + * d3.w:Height
16348 + * d4.l:Mask
16349 + * d7.l:RGBFormat
16350 + *
16351 + * This function is used to invert a rectangular area on the board. It is called by BltBitMap,
16352 + * BltPattern and BltTemplate.
16353 + */
16354 +uae_u32 picasso_InvertRect (void)
16355 +{
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));
16363 + uae_u32 xorval;
16364 + unsigned int lines;
16365 + struct RenderInfo ri;
16366 + uae_u8 *uae_mem;
16367 + unsigned long width_in_bytes;
16368 +
16369 + wgfx_flushline ();
16370 +
16371 + if (!CopyRenderInfoStructureA2U (renderinfo, &ri))
16372 + return 0;
16373 +
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); */
16376 +
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);
16382 + mask = 0xFF;
16383 + }
16384 + if ((mask & ~0xFF) != 0) {
16385 + write_log ("InvertRect: mask has high bits set!\n");
16386 + }
16387 + xorval = 0x01010101 * (mask & 0xFF);
16388 + width_in_bytes = Bpp * Width;
16389 + uae_mem = ri.Memory + Y * ri.BytesPerRow + X * Bpp;
16390 +
16391 + for (lines = 0; lines < Height; lines++, uae_mem += ri.BytesPerRow)
16392 + do_xor8 (uae_mem, width_in_bytes, xorval);
16393 +
16394 + if (renderinfo_is_current_screen (&ri)) {
16395 + if (mask == 0xFF)
16396 + do_invertrect (&ri, Bpp, X, Y, Width, Height);
16397 + else
16398 + do_blit (&ri, Bpp, X, Y, X, Y, Width, Height, BLIT_SRC, 0);
16399 + }
16400 +
16401 + return 1; /* 1 if supported, 0 otherwise */
16402 +}
16403 +
16404 +/* Fill a rectangle in the Amiga-memory frame buffer. */
16405 +
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)
16409 +{
16410 + uae_u8 *start, *oldstart, *dst;
16411 + long lines, cols;
16412 +
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;
16415 + switch (Bpp) {
16416 + case 1:
16417 + memset (start, Pen, Width);
16418 + break;
16419 + case 2:
16420 + for (cols = 0; cols < Width; cols++) {
16421 + do_put_mem_word ((uae_u16 *) start, Pen);
16422 + start += 2;
16423 + }
16424 + break;
16425 + case 3:
16426 + for (cols = 0; cols < Width; cols++) {
16427 + do_put_mem_byte (start, Pen & 0x000000FF);
16428 + start++;
16429 + *(uae_u16 *) (start) = (Pen & 0x00FFFF00) >> 8;
16430 + start += 2;
16431 + }
16432 + break;
16433 + case 4:
16434 + for (cols = 0; cols < Width; cols++) {
16435 + /**start = Pen; */
16436 + do_put_mem_long ((uae_u32 *) start, Pen);
16437 + start += 4;
16438 + }
16439 + break;
16440 + }
16441 +
16442 + dst = oldstart + ri->BytesPerRow;
16443 + /* next, we do the remaining line fills via memcpy() for > 1 BPP, otherwise some more memset() calls */
16444 + if (Bpp > 1) {
16445 + for (lines = 0; lines < (Height - 1); lines++, dst += ri->BytesPerRow)
16446 + memcpy (dst, oldstart, Width * Bpp);
16447 + } else {
16448 + for (lines = 0; lines < (Height - 1); lines++, dst += ri->BytesPerRow)
16449 + memset (dst, Pen, Width);
16450 + }
16451 +}
16452 +
16453 +
16454 +/***********************************************************
16455 +FillRect:
16456 +***********************************************************
16457 +* a0: struct BoardInfo *
16458 +* a1: struct RenderInfo *
16459 +* d0: WORD X
16460 +* d1: WORD Y
16461 +* d2: WORD Width
16462 +* d3: WORD Height
16463 +* d4: uae_u32 Pen
16464 +* d5: UBYTE Mask
16465 +* d7: uae_u32 RGBFormat
16466 +***********************************************************/
16467 +uae_u32 picasso_FillRect (void)
16468 +{
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);
16477 +
16478 + int Bpp;
16479 + struct RenderInfo ri;
16480 +
16481 + wgfx_flushline ();
16482 +
16483 + if (!CopyRenderInfoStructureA2U (renderinfo, &ri) || Y == 0xFFFF)
16484 + return 0;
16485 +
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));
16488 +
16489 + if (ri.RGBFormat != RGBFormat)
16490 + write_log ("Weird Stuff!\n");
16491 +
16492 + Bpp = GetBytesPerPixel (RGBFormat);
16493 +
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); */
16496 +
16497 + if (Mask == 0xFF) {
16498 + do_fillrect_frame_buffer (&ri, X, Y, Width, Height, Pen, Bpp, RGBFormat);
16499 +
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);
16503 +
16504 + return 1;
16505 + }
16506 +
16507 + /* We get here only if Mask != 0xFF */
16508 + if (Bpp != 1) {
16509 + write_log ("Picasso: mask != 0xFF in truecolor mode!\n");
16510 + return 0;
16511 + }
16512 + Pen &= Mask;
16513 + Mask = ~Mask;
16514 +
16515 + {
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);
16524 + }
16525 + }
16526 + }
16527 +
16528 + if (renderinfo_is_current_screen (&ri))
16529 + do_blit (&ri, Bpp, X, Y, X, Y, Width, Height, BLIT_SRC, 0);
16530 +
16531 + return 1;
16532 +}
16533 +
16534 +/*
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()
16537 + */
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)
16541 +{
16542 + uae_u8 *src, *dst, *tmp, *tmp2, *tmp3;
16543 + unsigned long lines;
16544 + uae_u8 Bpp = GetBytesPerPixel (ri->RGBFormat);
16545 + uae_u8 *blitsrc;
16546 + unsigned long total_width = width * Bpp;
16547 + unsigned long linewidth = (total_width + 15) & ~15;
16548 + int cant_blit = 1;
16549 +
16550 + /*
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.
16554 + *
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.
16557 + */
16558 + if (dstri == NULL) {
16559 + dstri = ri;
16560 + cant_blit = 0;
16561 + }
16562 +
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;
16566 + blitsrc = dst;
16567 + if (mask != 0xFF && Bpp > 1)
16568 + write_log ("ERROR - not obeying BlitRect() mask 0x%x properly with Bpp %d.\n", mask, Bpp);
16569 +
16570 + if (mask == 0xFF || Bpp > 1) {
16571 + /* handle normal case efficiently */
16572 + if (ri->Memory == dstri->Memory && dsty == srcy) {
16573 + unsigned long i;
16574 + for (i = 0; i < height; i++, src += ri->BytesPerRow, dst += dstri->BytesPerRow)
16575 + memmove (dst, src, total_width);
16576 + } else if (dsty < srcy) {
16577 + unsigned long i;
16578 + for (i = 0; i < height; i++, src += ri->BytesPerRow, dst += dstri->BytesPerRow)
16579 + memcpy (dst, src, total_width);
16580 + } else {
16581 + unsigned long i;
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);
16586 + }
16587 + if (cant_blit)
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);
16591 + return;
16592 + }
16593 +
16594 + tmp3 = tmp2 = tmp = xmalloc (linewidth * height); /* allocate enough memory for the src-rect */
16595 + if (!tmp)
16596 + return;
16597 +
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);
16601 + }
16602 +
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;
16609 + }
16610 + }
16611 + if (renderinfo_is_current_screen (dstri))
16612 + do_blit (dstri, Bpp, dstx, dsty, dstx, dsty, width, height, opcode, 0);
16613 +
16614 + /* free the temp-buf */
16615 + free (tmp3);
16616 +
16617 +}
16618 +
16619 +/***********************************************************
16620 +BlitRect:
16621 +***********************************************************
16622 +* a0: struct BoardInfo
16623 +* a1: struct RenderInfo
16624 +* d0: WORD SrcX
16625 +* d1: WORD SrcY
16626 +* d2: WORD DstX
16627 +* d3: WORD DstY
16628 +* d4: WORD Width
16629 +* d5: WORD Height
16630 +* d6: UBYTE Mask
16631 +* d7: uae_u32 RGBFormat
16632 +***********************************************************/
16633 +uae_u32 picasso_BlitRect (void)
16634 +{
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);
16643 +
16644 + struct RenderInfo ri;
16645 +
16646 + wgfx_flushline ();
16647 +
16648 + if (!CopyRenderInfoStructureA2U (renderinfo, &ri))
16649 + return 0;
16650 +
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); */
16654 +
16655 + return 1;
16656 +}
16657 +
16658 +/***********************************************************
16659 +BlitRectNoMaskComplete:
16660 +***********************************************************
16661 +* a0: struct BoardInfo
16662 +* a1: struct RenderInfo (src)
16663 +* a2: struct RenderInfo (dst)
16664 +* d0: WORD SrcX
16665 +* d1: WORD SrcY
16666 +* d2: WORD DstX
16667 +* d3: WORD DstY
16668 +* d4: WORD Width
16669 +* d5: WORD Height
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)
16677 +{
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;
16689 +
16690 + wgfx_flushline ();
16691 +
16692 + if (!CopyRenderInfoStructureA2U (srcri, &src_ri)
16693 + || !CopyRenderInfoStructureA2U (dstri, &dst_ri))
16694 + return 0;
16695 +
16696 + P96TRACE(("BlitRectNoMaskComplete() op 0x%2x, xy(%4d,%4d) --> xy(%4d,%4d), wh(%4d,%4d)\n",
16697 + OpCode, srcx, srcy, dstx, dsty, width, height));
16698 +
16699 + switch (OpCode) {
16700 + case 0x0C:
16701 + BlitRect (&src_ri, &dst_ri, srcx, srcy, dstx, dsty, width, height, 0xFF, OpCode);
16702 + return 1;
16703 +
16704 + default:
16705 + /* FOR NOW! */
16706 + return 0;
16707 + }
16708 +}
16709 +
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)
16712 +{
16713 + if (mask != 0xFF)
16714 + fgpen = (fgpen & mask) | (do_get_mem_byte (mem + bits) & ~mask);
16715 + do_put_mem_byte (mem + bits, fgpen);
16716 +}
16717 +
16718 +STATIC_INLINE void PixelWrite2 (uae_u8 * mem, int bits, uae_u32 fgpen)
16719 +{
16720 + do_put_mem_word (((uae_u16 *) mem) + bits, fgpen);
16721 +}
16722 +
16723 +STATIC_INLINE void PixelWrite3 (uae_u8 * mem, int bits, uae_u32 fgpen)
16724 +{
16725 + do_put_mem_byte (mem + bits * 3, fgpen & 0x000000FF);
16726 + *(uae_u16 *) (mem + bits * 3 + 1) = (fgpen & 0x00FFFF00) >> 8;
16727 +}
16728 +
16729 +STATIC_INLINE void PixelWrite4 (uae_u8 * mem, int bits, uae_u32 fgpen)
16730 +{
16731 + do_put_mem_long (((uae_u32 *) mem) + bits, fgpen);
16732 +}
16733 +
16734 +STATIC_INLINE void PixelWrite (uae_u8 * mem, int bits, uae_u32 fgpen, uae_u8 Bpp, uae_u32 mask)
16735 +{
16736 + switch (Bpp) {
16737 + case 1:
16738 + if (mask != 0xFF)
16739 + fgpen = (fgpen & mask) | (do_get_mem_byte (mem + bits) & ~mask);
16740 + do_put_mem_byte (mem + bits, fgpen);
16741 + break;
16742 + case 2:
16743 + do_put_mem_word (((uae_u16 *) mem) + bits, fgpen);
16744 + break;
16745 + case 3:
16746 + do_put_mem_byte (mem + bits * 3, fgpen & 0x000000FF);
16747 + *(uae_u16 *) (mem + bits * 3 + 1) = (fgpen & 0x00FFFF00) >> 8;
16748 + break;
16749 + case 4:
16750 + do_put_mem_long (((uae_u32 *) mem) + bits, fgpen);
16751 + break;
16752 + }
16753 +}
16754 +
16755 +/*
16756 + * BlitPattern:
16757 + *
16758 + * Synopsis:BlitPattern(bi, ri, pattern, X, Y, Width, Height, Mask, RGBFormat);
16759 + * Inputs:
16760 + * a0:struct BoardInfo *bi
16761 + * a1:struct RenderInfo *ri
16762 + * a2:struct Pattern *pattern
16763 + * d0.w:X
16764 + * d1.w:Y
16765 + * d2.w:Width
16766 + * d3.w:Height
16767 + * d4.w:Mask
16768 + * d7.l:RGBFormat
16769 + *
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.
16776 + */
16777 +uae_u32 picasso_BlitPattern (void)
16778 +{
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);
16787 +
16788 + uae_u8 Bpp = GetBytesPerPixel (RGBFmt);
16789 + int inversion = 0;
16790 + struct RenderInfo ri;
16791 + struct Pattern pattern;
16792 + unsigned long rows;
16793 + uae_u32 fgpen;
16794 + uae_u8 *uae_mem;
16795 + int xshift;
16796 + unsigned long ysize_mask;
16797 +
16798 + wgfx_flushline ();
16799 +
16800 + if (! CopyRenderInfoStructureA2U (rinf, &ri)
16801 + || !CopyPatternStructureA2U (pinf, &pattern))
16802 + return 0;
16803 +
16804 + Bpp = GetBytesPerPixel (ri.RGBFormat);
16805 + uae_mem = ri.Memory + Y * ri.BytesPerRow + X * Bpp; /* offset with address */
16806 +
16807 + if (pattern.DrawMode & INVERS)
16808 + inversion = 1;
16809 +
16810 + pattern.DrawMode &= 0x03;
16811 + if (Mask != 0xFF) {
16812 + if (Bpp > 1)
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);
16816 + return 0;
16817 + }
16818 + }
16819 +
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));
16822 +#ifdef _DEBUG
16823 + DumpPattern (&pattern);
16824 +#endif
16825 + ysize_mask = (1 << pattern.Size) - 1;
16826 + xshift = pattern.XOffset & 15;
16827 +
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;
16833 +
16834 + if (xshift != 0)
16835 + d = (d << xshift) | (d >> (16 - xshift));
16836 +
16837 + for (cols = 0; cols < W; cols += 16, uae_mem2 += Bpp << 4) {
16838 + long bits;
16839 + long max = W - cols;
16840 + unsigned int data = d;
16841 +
16842 + if (max > 16)
16843 + max = 16;
16844 +
16845 + for (bits = 0; bits < max; bits++) {
16846 + int bit_set = data & 0x8000;
16847 + data <<= 1;
16848 + switch (pattern.DrawMode) {
16849 + case JAM1:
16850 + if (inversion)
16851 + bit_set = !bit_set;
16852 + if (bit_set)
16853 + PixelWrite (uae_mem2, bits, pattern.FgPen, Bpp, Mask);
16854 + break;
16855 + case JAM2:
16856 + if (inversion)
16857 + bit_set = !bit_set;
16858 + if (bit_set)
16859 + PixelWrite (uae_mem2, bits, pattern.FgPen, Bpp, Mask);
16860 + else
16861 + PixelWrite (uae_mem2, bits, pattern.BgPen, Bpp, Mask);
16862 + break;
16863 + case COMP:
16864 + if (bit_set) {
16865 + fgpen = pattern.FgPen;
16866 +
16867 + switch (Bpp) {
16868 + case 1:
16869 + {
16870 + uae_u8 *addr = uae_mem2 + bits;
16871 + do_put_mem_byte (addr, do_get_mem_byte (addr) ^ fgpen);
16872 + }
16873 + break;
16874 + case 2:
16875 + {
16876 + uae_u16 *addr = ((uae_u16 *) uae_mem2) + bits;
16877 + do_put_mem_word (addr, do_get_mem_word (addr) ^ fgpen);
16878 + }
16879 + break;
16880 + case 3:
16881 + {
16882 + uae_u32 *addr = (uae_u32 *) (uae_mem2 + bits * 3);
16883 + do_put_mem_long (addr, do_get_mem_long (addr) ^ (fgpen & 0x00FFFFFF));
16884 + }
16885 + break;
16886 + case 4:
16887 + {
16888 + uae_u32 *addr = ((uae_u32 *) uae_mem2) + bits;
16889 + do_put_mem_long (addr, do_get_mem_long (addr) ^ fgpen);
16890 + }
16891 + break;
16892 + }
16893 + }
16894 + break;
16895 + }
16896 + }
16897 + }
16898 + }
16899 +
16900 + if (renderinfo_is_current_screen (&ri))
16901 + do_blit (&ri, Bpp, X, Y, X, Y, W, H, BLIT_SRC, 0);
16902 +
16903 + return 1;
16904 +}
16905 +
16906 +/*************************************************
16907 +BlitTemplate:
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
16913 +* d0.w: X
16914 +* d1.w: Y
16915 +* d2.w: Width
16916 +* d3.w: Height
16917 +* d4.w: Mask
16918 +* d7.l: RGBFormat
16919 +*
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)
16926 +{
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;
16938 + int bitoffset;
16939 + uae_u32 fgpen;
16940 + uae_u8 *uae_mem, Bpp;
16941 + uae_u8 *tmpl_base;
16942 +
16943 + wgfx_flushline ();
16944 +
16945 + if (!CopyRenderInfoStructureA2U (rinf, &ri)
16946 + || !CopyTemplateStructureA2U (tmpl, &tmp))
16947 + return 0;
16948 +
16949 + Bpp = GetBytesPerPixel (ri.RGBFormat);
16950 + uae_mem = ri.Memory + Y * ri.BytesPerRow + X * Bpp; /* offset into address */
16951 +
16952 + if (tmp.DrawMode & INVERS)
16953 + inversion = 1;
16954 +
16955 + tmp.DrawMode &= 0x03;
16956 + if (Mask != 0xFF) {
16957 + if (Bpp > 1)
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);
16961 + return 0;
16962 + }
16963 + }
16964 +
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));
16967 +
16968 + bitoffset = tmp.XOffset % 8;
16969 +
16970 +#ifdef _DEBUG
16971 + DumpTemplate (&tmp, W, H);
16972 +#endif
16973 +
16974 + tmpl_base = tmp.Memory + tmp.XOffset / 8;
16975 +
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;
16981 +
16982 + for (cols = 0; cols < W; cols += 8, uae_mem2 += Bpp << 3) {
16983 + unsigned int byte;
16984 + long bits;
16985 + long max = W - cols;
16986 +
16987 + if (max > 8)
16988 + max = 8;
16989 +
16990 + data <<= 8;
16991 + data |= *++tmpl_mem;
16992 +
16993 + byte = data >> (8 - bitoffset);
16994 +
16995 + for (bits = 0; bits < max; bits++) {
16996 + int bit_set = (byte & 0x80);
16997 + byte <<= 1;
16998 + switch (tmp.DrawMode) {
16999 + case JAM1:
17000 + if (inversion)
17001 + bit_set = !bit_set;
17002 + if (bit_set) {
17003 + fgpen = tmp.FgPen;
17004 + PixelWrite (uae_mem2, bits, fgpen, Bpp, Mask);
17005 + }
17006 + break;
17007 + case JAM2:
17008 + if (inversion)
17009 + bit_set = !bit_set;
17010 + fgpen = tmp.BgPen;
17011 + if (bit_set)
17012 + fgpen = tmp.FgPen;
17013 +
17014 + PixelWrite (uae_mem2, bits, fgpen, Bpp, Mask);
17015 + break;
17016 + case COMP:
17017 + if (bit_set) {
17018 + fgpen = tmp.FgPen;
17019 +
17020 + switch (Bpp) {
17021 + case 1:
17022 + {
17023 + uae_u8 *addr = uae_mem2 + bits;
17024 + do_put_mem_byte (addr, do_get_mem_byte (addr) ^ fgpen);
17025 + }
17026 + break;
17027 + case 2:
17028 + {
17029 + uae_u16 *addr = ((uae_u16 *) uae_mem2) + bits;
17030 + do_put_mem_word (addr, do_get_mem_word (addr) ^ fgpen);
17031 + }
17032 + break;
17033 + case 3:
17034 + {
17035 + uae_u32 *addr = (uae_u32 *) (uae_mem2 + bits * 3);
17036 + do_put_mem_long (addr, do_get_mem_long (addr) ^ (fgpen & 0x00FFFFFF));
17037 + }
17038 + break;
17039 + case 4:
17040 + {
17041 + uae_u32 *addr = ((uae_u32 *) uae_mem2) + bits;
17042 + do_put_mem_long (addr, do_get_mem_long (addr) ^ fgpen);
17043 + }
17044 + break;
17045 + }
17046 + }
17047 + break;
17048 + }
17049 + }
17050 + }
17051 + }
17052 +
17053 + if (renderinfo_is_current_screen (&ri))
17054 + do_blit (&ri, Bpp, X, Y, X, Y, W, H, BLIT_SRC, 0);
17055 +
17056 + return 1;
17057 +}
17058 +
17059 +/*
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.
17066 + */
17067 +uae_u32 picasso_CalculateBytesPerRow (void)
17068 +{
17069 + uae_u16 width = m68k_dreg (regs, 0);
17070 + uae_u32 type = m68k_dreg (regs, 7);
17071 +
17072 + width = GetBytesPerPixel (type) * width;
17073 + P96TRACE (("CalculateBytesPerRow() = %d\n", width));
17074 +
17075 + return width;
17076 +}
17077 +
17078 +/*
17079 + * SetDisplay:
17080 + * a0: struct BoardInfo
17081 + * d0: BOOL state
17082 + * This function enables and disables the video display.
17083 + *
17084 + * NOTE: return the opposite of the state
17085 + */
17086 +uae_u32 picasso_SetDisplay (void)
17087 +{
17088 + uae_u32 state = m68k_dreg (regs, 0);
17089 + P96TRACE (("SetDisplay(%d)\n", state));
17090 + return !state;
17091 +}
17092 +
17093 +/*
17094 + * WaitVerticalSync:
17095 + * a0: struct BoardInfo
17096 + * This function waits for the next horizontal retrace.
17097 + */
17098 +uae_u32 picasso_WaitVerticalSync (void)
17099 +{
17100 + /*write_log ("WaitVerticalSync()\n"); */
17101 + return 1;
17102 +}
17103 +
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)
17108 +{
17109 + int j;
17110 +
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;
17114 + long eol_offset;
17115 +
17116 + /* if (mask != 0xFF)
17117 + write_log ("P2C - pixel-width = %d, bit-offset = %d\n", width, bitoffset); */
17118 +
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;
17124 + PLANAR[j] = p;
17125 + if ((mask & (1 << j)) == 0)
17126 + PLANAR[j] = &all_zeros_bitmap;
17127 + }
17128 + eol_offset = (long) bm->BytesPerRow - (long) ((width + 7) >> 3);
17129 + for (rows = 0; rows < height; rows++, image += ri->BytesPerRow) {
17130 + unsigned long cols;
17131 +
17132 + for (cols = 0; cols < width; cols += 8) {
17133 + int k;
17134 + uae_u32 a = 0, b = 0;
17135 + unsigned int msk = 0xFF;
17136 + long tmp = cols + 8 - width;
17137 + if (tmp > 0) {
17138 + msk <<= tmp;
17139 + b = do_get_mem_long ((uae_u32 *) (image + cols + 4));
17140 + if (tmp < 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);
17145 + }
17146 + }
17147 + for (k = 0; k < Depth; k++) {
17148 + unsigned int data;
17149 + if (PLANAR[k] == &all_zeros_bitmap)
17150 + data = 0;
17151 + else if (PLANAR[k] == &all_ones_bitmap)
17152 + data = 0xFF;
17153 + else {
17154 + data = (uae_u8) (do_get_mem_word ((uae_u16 *) PLANAR[k]) >> (8 - bitoffset));
17155 + PLANAR[k]++;
17156 + }
17157 + data &= msk;
17158 + a |= p2ctab[data][0] << k;
17159 + b |= p2ctab[data][1] << k;
17160 + }
17161 + do_put_mem_long ((uae_u32 *) (image + cols), a);
17162 + do_put_mem_long ((uae_u32 *) (image + cols + 4), b);
17163 + }
17164 + for (j = 0; j < Depth; j++) {
17165 + if (PLANAR[j] != &all_zeros_bitmap && PLANAR[j] != &all_ones_bitmap) {
17166 + PLANAR[j] += eol_offset;
17167 + }
17168 + }
17169 + }
17170 +}
17171 +
17172 +/*
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
17177 + * d0.w: SrcX
17178 + * d1.w: SrcY
17179 + * d2.w: DstX
17180 + * d3.w: DstY
17181 + * d4.w: SizeX
17182 + * d5.w: SizeY
17183 + * d6.b: MinTerm - uh oh!
17184 + * d7.b: Mask - uh oh!
17185 + *
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").
17189 + */
17190 +uae_u32 picasso_BlitPlanar2Chunky (void)
17191 +{
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;
17204 +
17205 + wgfx_flushline ();
17206 +
17207 + if (minterm != 0x0C) {
17208 + write_log ("ERROR - BlitPlanar2Chunky() has minterm 0x%x, which I don't handle. Using fall-back routine.\n", minterm);
17209 + return 0;
17210 + }
17211 + if (!CopyRenderInfoStructureA2U (ri, &local_ri)
17212 + || !CopyBitMapStructureA2U (bm, &local_bm))
17213 + return 0;
17214 +
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);
17221 +
17222 + return 1;
17223 +}
17224 +
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)
17229 +{
17230 + int j;
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;
17236 + long eol_offset;
17237 +
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;
17243 + PLANAR[j] = p;
17244 + if ((mask & (1 << j)) == 0)
17245 + PLANAR[j] = &all_zeros_bitmap;
17246 + }
17247 +
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);
17253 + int i;
17254 +
17255 + for (cols = 0; cols < width; cols++) {
17256 + int v = 0, k;
17257 + for (k = 0; k < Depth; k++) {
17258 + if (PLANAR[k] == &all_ones_bitmap)
17259 + v |= 1 << k;
17260 + else if (PLANAR[k] != &all_zeros_bitmap) {
17261 + v |= ((*PLANAR[k] >> bitoffs) & 1) << k;
17262 + }
17263 + }
17264 +
17265 + switch (bpp) {
17266 + case 2:
17267 + do_put_mem_word ((uae_u16 *) image2, cim->Colors[v]);
17268 + image2 += 2;
17269 + break;
17270 + case 3:
17271 + do_put_mem_byte (image2++, cim->Colors[v] & 0x000000FF);
17272 + do_put_mem_word ((uae_u16 *) image2, (cim->Colors[v] & 0x00FFFF00) >> 8);
17273 + image2 += 2;
17274 + break;
17275 + case 4:
17276 + do_put_mem_long ((uae_u32 *) image2, cim->Colors[v]);
17277 + image2 += 4;
17278 + break;
17279 + }
17280 + bitoffs--;
17281 + bitoffs &= 7;
17282 + if (bitoffs == 7) {
17283 + int k;
17284 + for (k = 0; k < Depth; k++) {
17285 + if (PLANAR[k] != &all_zeros_bitmap && PLANAR[k] != &all_ones_bitmap) {
17286 + PLANAR[k]++;
17287 + }
17288 + }
17289 + }
17290 + }
17291 +
17292 + for (i = 0; i < Depth; i++) {
17293 + if (PLANAR[i] != &all_zeros_bitmap && PLANAR[i] != &all_ones_bitmap) {
17294 + PLANAR[i] += eol_offset;
17295 + }
17296 + }
17297 + }
17298 +}
17299 +
17300 +/*
17301 + * BlitPlanar2Direct:
17302 + *
17303 + * Synopsis:
17304 + * BlitPlanar2Direct(bi, bm, ri, cim, SrcX, SrcY, DstX, DstY, SizeX, SizeY, MinTerm, Mask);
17305 + * Inputs:
17306 + * a0:struct BoardInfo *bi
17307 + * a1:struct BitMap *bm
17308 + * a2:struct RenderInfo *ri
17309 + * a3:struct ColorIndexMapping *cmi
17310 + * d0.w:SrcX
17311 + * d1.w:SrcY
17312 + * d2.w:DstX
17313 + * d3.w:DstY
17314 + * d4.w:SizeX
17315 + * d5.w:SizeY
17316 + * d6.b:MinTerm
17317 + * d7.b:Mask
17318 + *
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().
17326 + */
17327 +uae_u32 picasso_BlitPlanar2Direct (void)
17328 +{
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;
17343 +
17344 + wgfx_flushline ();
17345 +
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);
17348 + return 0;
17349 + }
17350 + if (Mask != 0xFF) {
17351 + write_log ("ERROR - Unsupported Mask value 0x%x in BlitPlanar2Direct(), using fallback method.\n", Mask);
17352 + return 0;
17353 + }
17354 + if (!CopyRenderInfoStructureA2U (ri, &local_ri)
17355 + || !CopyBitMapStructureA2U (bm, &local_bm))
17356 + return 0;
17357 +
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);
17364 + return 1;
17365 +}
17366 +
17367 +/* @@@ - Work to be done here!
17368 + *
17369 + * The address is the offset into our Picasso96 frame-buffer (pointed to by gfxmem_start)
17370 + * where the value was put.
17371 + *
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!)
17375 + */
17376 +static void write_gfx_long (uaecptr addr, uae_u32 value)
17377 +{
17378 + uaecptr oldaddr = addr;
17379 + int x, xbytes, y;
17380 + uae_u8 *dst;
17381 +
17382 + if (!picasso_on)
17383 + return;
17384 +
17385 + /*
17386 + * Several writes to successive memory locations are a common access pattern.
17387 + * Try to optimize it.
17388 + */
17389 + if (addr >= wgfx_linestart && addr + 4 <= wgfx_lineend) {
17390 + if (addr < wgfx_min)
17391 + wgfx_min = addr;
17392 + if (addr + 4 > wgfx_max)
17393 + wgfx_max = addr + 4;
17394 + return;
17395 + } else
17396 + wgfx_flushline ();
17397 +
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)
17401 + return;
17402 +
17403 + addr -= picasso96_state.Address;
17404 + y = addr / picasso96_state.BytesPerRow;
17405 +
17406 + if (y >= picasso96_state.VirtualHeight)
17407 + return;
17408 + wgfx_linestart = picasso96_state.Address - gfxmem_start + y * picasso96_state.BytesPerRow;
17409 + wgfx_lineend = wgfx_linestart + picasso96_state.BytesPerRow;
17410 + wgfx_y = y;
17411 + wgfx_min = oldaddr;
17412 + wgfx_max = oldaddr + 4;
17413 +}
17414 +
17415 +static void write_gfx_word (uaecptr addr, uae_u16 value)
17416 +{
17417 + uaecptr oldaddr = addr;
17418 + int x, xbytes, y;
17419 + uae_u8 *dst;
17420 +
17421 + if (!picasso_on)
17422 + return;
17423 +
17424 + /*
17425 + * Several writes to successive memory locations are a common access pattern.
17426 + * Try to optimize it.
17427 + */
17428 + if (addr >= wgfx_linestart && addr + 2 <= wgfx_lineend) {
17429 + if (addr < wgfx_min)
17430 + wgfx_min = addr;
17431 + if (addr + 2 > wgfx_max)
17432 + wgfx_max = addr + 2;
17433 + return;
17434 + } else
17435 + wgfx_flushline ();
17436 +
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)
17440 + return;
17441 +
17442 + addr -= picasso96_state.Address;
17443 + y = addr / picasso96_state.BytesPerRow;
17444 +
17445 + if (y >= picasso96_state.VirtualHeight)
17446 + return;
17447 + wgfx_linestart = picasso96_state.Address - gfxmem_start + y * picasso96_state.BytesPerRow;
17448 + wgfx_lineend = wgfx_linestart + picasso96_state.BytesPerRow;
17449 + wgfx_y = y;
17450 + wgfx_min = oldaddr;
17451 + wgfx_max = oldaddr + 2;
17452 +}
17453 +
17454 +static void write_gfx_byte (uaecptr addr, uae_u8 value)
17455 +{
17456 + uaecptr oldaddr = addr;
17457 + int x, xbytes, y;
17458 + uae_u8 *dst;
17459 +
17460 + if (!picasso_on)
17461 + return;
17462 +
17463 + /*
17464 + * Several writes to successive memory locations are a common access pattern.
17465 + * Try to optimize it.
17466 + */
17467 + if (addr >= wgfx_linestart && addr + 4 <= wgfx_lineend) {
17468 + if (addr < wgfx_min)
17469 + wgfx_min = addr;
17470 + if (addr + 1 > wgfx_max)
17471 + wgfx_max = addr + 1;
17472 + return;
17473 + } else
17474 + wgfx_flushline ();
17475 +
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)
17479 + return;
17480 +
17481 + addr -= picasso96_state.Address;
17482 + y = addr / picasso96_state.BytesPerRow;
17483 +
17484 + if (y >= picasso96_state.VirtualHeight)
17485 + return;
17486 + wgfx_linestart = picasso96_state.Address - gfxmem_start + y * picasso96_state.BytesPerRow;
17487 + wgfx_lineend = wgfx_linestart + picasso96_state.BytesPerRow;
17488 + wgfx_y = y;
17489 + wgfx_min = oldaddr;
17490 + wgfx_max = oldaddr + 1;
17491 +}
17492 +
17493 +static uae_u32 REGPARAM2 gfxmem_lget (uaecptr addr)
17494 +{
17495 + uae_u32 *m;
17496 + addr -= gfxmem_start & gfxmem_mask;
17497 + addr &= gfxmem_mask;
17498 + m = (uae_u32 *) (gfxmemory + addr);
17499 + return do_get_mem_long (m);
17500 +}
17501 +
17502 +static uae_u32 REGPARAM2 gfxmem_wget (uaecptr addr)
17503 +{
17504 + uae_u16 *m;
17505 + addr -= gfxmem_start & gfxmem_mask;
17506 + addr &= gfxmem_mask;
17507 + m = (uae_u16 *) (gfxmemory + addr);
17508 + return do_get_mem_word (m);
17509 +}
17510 +
17511 +static uae_u32 REGPARAM2 gfxmem_bget (uaecptr addr)
17512 +{
17513 + addr -= gfxmem_start & gfxmem_mask;
17514 + addr &= gfxmem_mask;
17515 + return gfxmemory[addr];
17516 +}
17517 +
17518 +static void REGPARAM2 gfxmem_lput (uaecptr addr, uae_u32 l)
17519 +{
17520 + uae_u32 *m;
17521 + addr -= gfxmem_start & gfxmem_mask;
17522 + addr &= gfxmem_mask;
17523 + m = (uae_u32 *) (gfxmemory + addr);
17524 + do_put_mem_long (m, l);
17525 +
17526 + /* write the long-word to our displayable memory */
17527 + write_gfx_long (addr, l);
17528 +}
17529 +
17530 +static void REGPARAM2 gfxmem_wput (uaecptr addr, uae_u32 w)
17531 +{
17532 + uae_u16 *m;
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);
17537 +
17538 + /* write the word to our displayable memory */
17539 + write_gfx_word (addr, (uae_u16) w);
17540 +}
17541 +
17542 +static void REGPARAM2 gfxmem_bput (uaecptr addr, uae_u32 b)
17543 +{
17544 + addr -= gfxmem_start & gfxmem_mask;
17545 + addr &= gfxmem_mask;
17546 + gfxmemory[addr] = b;
17547 +
17548 + /* write the byte to our displayable memory */
17549 + write_gfx_byte (addr, (uae_u8) b);
17550 +}
17551 +
17552 +static int REGPARAM2 gfxmem_check (uaecptr addr, uae_u32 size)
17553 +{
17554 + addr -= gfxmem_start & gfxmem_mask;
17555 + addr &= gfxmem_mask;
17556 + return (addr + size) < allocated_gfxmem;
17557 +}
17558 +
17559 +static uae_u8 REGPARAM2 *gfxmem_xlate (uaecptr addr)
17560 +{
17561 + addr -= gfxmem_start & gfxmem_mask;
17562 + addr &= gfxmem_mask;
17563 + return gfxmemory + addr;
17564 +}
17565 +
17566 +addrbank gfxmem_bank = {
17567 + gfxmem_lget, gfxmem_wget, gfxmem_bget,
17568 + gfxmem_lput, gfxmem_wput, gfxmem_bput,
17569 + gfxmem_xlate, gfxmem_check, NULL
17570 +};
17571 +
17572 +int picasso_display_mode_index (uae_u32 x, uae_u32 y, uae_u32 d)
17573 +{
17574 + int i;
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)
17579 + break;
17580 + }
17581 + if (i == mode_count)
17582 + i = -1;
17583 + return i;
17584 +}
17585 +
17586 +static int resolution_compare (const void *a, const void *b)
17587 +{
17588 + struct PicassoResolution *ma = (struct PicassoResolution *) a;
17589 + struct PicassoResolution *mb = (struct PicassoResolution *) b;
17590 + if (ma->res.width > mb->res.width)
17591 + return -1;
17592 + if (ma->res.width < mb->res.width)
17593 + return 1;
17594 + if (ma->res.height > mb->res.height)
17595 + return -1;
17596 + if (ma->res.height < mb->res.height)
17597 + return 1;
17598 + return ma->depth - mb->depth;
17599 +}
17600 +
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)
17605 +{
17606 + static int first_time = 1;
17607 +
17608 + memset (&picasso96_state, 0, sizeof (struct picasso96_state_struct));
17609 +
17610 + if (first_time) {
17611 + int i;
17612 +
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));
17622 + }
17623 + mode_count = DX_FillResolutions (&picasso96_pixel_format);
17624 + qsort (DisplayModes, mode_count, sizeof (struct PicassoResolution), resolution_compare);
17625 +
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) {
17630 + case 1:
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;
17635 + break;
17636 + case 2:
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;
17641 + break;
17642 + case 3:
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;
17647 + break;
17648 + case 4:
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;
17653 + break;
17654 + }
17655 + }
17656 + ShowSupportedResolutions ();
17657 +
17658 + first_time = 0;
17659 + }
17660 +}
17661 +
17662 +#endif
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
17666 @@ -0,0 +1,1247 @@
17667 + /*
17668 + * UAE - The Un*x Amiga Emulator
17669 + *
17670 + * SDL interface
17671 + *
17672 + * Copyright 2001 Bernd Lachner (EMail: dev@lachner-net.de)
17673 + *
17674 + * Partialy based on the UAE X interface (xwin.c)
17675 + *
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
17681 + */
17682 +
17683 +#include "sysconfig.h"
17684 +#include "sysdeps.h"
17685 +
17686 +#include <unistd.h>
17687 +#include <signal.h>
17688 +
17689 +#include <SDL/SDL.h>
17690 +#include <SDL/SDL_endian.h>
17691 +
17692 +#include "config.h"
17693 +#include "options.h"
17694 +#include "uae.h"
17695 +#include "memory.h"
17696 +#include "xwin.h"
17697 +#include "custom.h"
17698 +#include "drawing.h"
17699 +#include "newcpu.h"
17700 +#include "keyboard.h"
17701 +#include "keybuf.h"
17702 +#include "gui.h"
17703 +#include "debug.h"
17704 +#include "picasso96.h"
17705 +
17706 +/* Uncomment for debugging output */
17707 +/* #define DEBUG */
17708 +
17709 +#ifdef __cplusplus
17710 +static RETSIGTYPE sigbrkhandler(...)
17711 +#else
17712 +static RETSIGTYPE sigbrkhandler (int foo)
17713 +#endif
17714 +{
17715 + activate_debugger();
17716 +#if !defined(__unix) || defined(__NeXT__)
17717 + signal (SIGINT, sigbrkhandler);
17718 +#endif
17719 +}
17720 +
17721 +void setup_brkhandler (void)
17722 +{
17723 +#if defined(__unix) && !defined(__NeXT__)
17724 + struct sigaction sa;
17725 + sa.sa_handler = sigbrkhandler;
17726 + sa.sa_flags = 0;
17727 +#ifdef SA_RESTART
17728 + sa.sa_flags = SA_RESTART;
17729 +#endif
17730 + sigemptyset (&sa.sa_mask);
17731 + sigaction (SIGINT, &sa, NULL);
17732 +#else
17733 + signal (SIGINT, sigbrkhandler);
17734 +#endif
17735 +}
17736 +
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};
17745 +
17746 +static int red_bits, green_bits, blue_bits;
17747 +static int red_shift, green_shift, blue_shift;
17748 +
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;
17754 +
17755 +static int bitdepth, bit_unit;
17756 +
17757 +static int current_width, current_height;
17758 +static SDL_Color arSDLColors[256];
17759 +static int ncolors = 0;
17760 +
17761 +/* Keyboard and mouse */
17762 +static int keystate[256];
17763 +
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)
17769 +{
17770 + SDL_WM_ToggleFullScreen(prSDLScreen);
17771 +};
17772 +
17773 +static void handle_interpol (void);
17774 +
17775 +struct SDLHotKey
17776 +{
17777 + SDLKey aHotKeys[2];
17778 + void (*pfHandler)(void);
17779 + long aPressedKeys[2];
17780 +};
17781 +
17782 +
17783 +static struct SDLHotKey arHotKeys[] =
17784 +{
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 */
17794 +};
17795 +
17796 +void flush_line (int y)
17797 +{
17798 + /* Not implemented for SDL output */
17799 +#ifdef DEBUG
17800 + fprintf(stderr, "Function: flush_line\n");
17801 +#endif
17802 +}
17803 +
17804 +void flush_block (int ystart, int ystop)
17805 +{
17806 +#ifdef DEBUG
17807 + fprintf(stderr, "Function: flush_block %d %d\n", ystart, ystop);
17808 +#endif
17809 + SDL_UnlockSurface (prSDLScreen);
17810 + SDL_UpdateRect(prSDLScreen, 0, ystart, current_width, ystop-ystart+1);
17811 + SDL_LockSurface (prSDLScreen);
17812 +}
17813 +
17814 +void flush_screen (int ystart, int ystop)
17815 +{
17816 +#ifdef DEBUG
17817 + fprintf(stderr, "Function: flush_screen\n");
17818 +#endif
17819 +
17820 +#if 0
17821 + SDL_UpdateRect(prSDLScreen, 0, 0, current_width, current_height);
17822 +#endif
17823 +}
17824 +
17825 +STATIC_INLINE int bitsInMask (unsigned long mask)
17826 +{
17827 + /* count bits in mask */
17828 + int n = 0;
17829 + while (mask)
17830 + {
17831 + n += mask & 1;
17832 + mask >>= 1;
17833 + }
17834 + return n;
17835 +}
17836 +
17837 +STATIC_INLINE int maskShift (unsigned long mask)
17838 +{
17839 + /* determine how far mask is shifted */
17840 + int n = 0;
17841 + while (!(mask & 1))
17842 + {
17843 + n++;
17844 + mask >>= 1;
17845 + }
17846 + return n;
17847 +}
17848 +
17849 +static int get_color (int r, int g, int b, xcolnr *cnp)
17850 +{
17851 +#ifdef DEBUG
17852 + fprintf(stderr, "Function: get_color\n");
17853 +#endif
17854 +
17855 + *cnp = SDL_MapRGB(prSDLScreen->format, r, g, b);
17856 + arSDLColors[ncolors].r = r;
17857 + arSDLColors[ncolors].g = g;
17858 + arSDLColors[ncolors].b = b;
17859 +
17860 + ncolors++;
17861 + return 1;
17862 +}
17863 +
17864 +static int init_colors (void)
17865 +{
17866 + int i;
17867 +
17868 +#ifdef DEBUG
17869 + fprintf(stderr, "Function: init_colors\n");
17870 +#endif
17871 +
17872 + if (bitdepth > 8)
17873 + {
17874 + /* Truecolor: */
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);
17882 + }
17883 + else
17884 + {
17885 + alloc_colors256 (get_color);
17886 + SDL_SetColors(prSDLScreen, arSDLColors, 0, 256);
17887 + }
17888 +
17889 + switch (gfxvidinfo.pixbytes)
17890 + {
17891 + case 2:
17892 + for (i = 0; i < 4096; i++)
17893 + xcolors[i] = xcolors[i] * 0x00010001;
17894 + gfxvidinfo.can_double = 1;
17895 + break;
17896 + case 1:
17897 + for (i = 0; i < 4096; i++)
17898 + xcolors[i] = xcolors[i] * 0x01010101;
17899 + gfxvidinfo.can_double = 1;
17900 + break;
17901 + default:
17902 + gfxvidinfo.can_double = 0;
17903 + break;
17904 + }
17905 + if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
17906 + {
17907 + switch (gfxvidinfo.pixbytes)
17908 + {
17909 + case 4:
17910 + for(i = 0; i < 4096; i++)
17911 + SDL_Swap32(xcolors[i]);
17912 + break;
17913 + case 2:
17914 + for (i = 0; i < 4096; i++)
17915 + SDL_Swap16(xcolors[i]);
17916 + break;
17917 + }
17918 + }
17919 + return 1;
17920 +}
17921 +
17922 +int graphics_setup (void)
17923 +{
17924 +#ifdef DEBUG
17925 + fprintf(stderr, "Function: graphics_setup\n");
17926 +#endif
17927 +
17928 + /* Initialize the SDL library */
17929 + if ( SDL_Init(SDL_INIT_VIDEO) < 0 )
17930 + {
17931 + fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
17932 + return 0;
17933 + }
17934 +
17935 + return 1;
17936 +}
17937 +
17938 +
17939 +static void graphics_subinit (void)
17940 +{
17941 + Uint32 uiSDLVidModFlags;
17942 +
17943 +#ifdef DEBUG
17944 + fprintf(stderr, "Function: graphics_subinit\n");
17945 +#endif
17946 +
17947 + /* Open SDL Window in current mode */
17948 + uiSDLVidModFlags = SDL_SWSURFACE;
17949 + if (bitdepth == 8)
17950 + {
17951 + uiSDLVidModFlags |= SDL_HWPALETTE;
17952 + }
17953 + if (currprefs.gfx_afullscreen || currprefs.gfx_pfullscreen)
17954 + {
17955 + uiSDLVidModFlags |= SDL_FULLSCREEN;
17956 + }
17957 + fprintf(stderr, "Resolution: %d x %d x %d\n", current_width, current_height, bitdepth);
17958 +
17959 + prSDLScreen = SDL_SetVideoMode(current_width, current_height, bitdepth, uiSDLVidModFlags);
17960 + if (prSDLScreen == NULL)
17961 + {
17962 + fprintf(stderr, "Unable to set video mode: %s\n", SDL_GetError());
17963 + return;
17964 + }
17965 + else
17966 + {
17967 +#ifdef DEBUG
17968 + fprintf(stderr, "Bytes per Pixel: %d\n", prSDLScreen->format->BytesPerPixel);
17969 + fprintf(stderr, "Bytes per Line: %d\n", prSDLScreen->pitch);
17970 +#endif
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);
17996 + }
17997 + lastmx = lastmy = 0;
17998 + newmousecounters = 0;
17999 +}
18000 +
18001 +
18002 +int graphics_init (void)
18003 +{
18004 + int i,j;
18005 +
18006 +#ifdef DEBUG
18007 + fprintf(stderr, "Function: graphics_init\n");
18008 +#endif
18009 +
18010 + if (currprefs.color_mode > 5)
18011 + fprintf (stderr, "Bad color mode selected. Using default.\n"), currprefs.color_mode = 0;
18012 +
18013 + screen_is_picasso = 0;
18014 +
18015 + fixup_prefs_dimensions (&currprefs);
18016 +
18017 +
18018 + gfxvidinfo.width = currprefs.gfx_width;
18019 + gfxvidinfo.height = currprefs.gfx_height;
18020 + current_width = currprefs.gfx_width;
18021 + current_height = currprefs.gfx_height;
18022 +
18023 + /* Find a SDL video mode with exact width and height */
18024 + for (i = 0; aScreenDepth[i] != 0; i++)
18025 + {
18026 + bitdepth = SDL_VideoModeOK(current_width, current_height, aScreenDepth[i], SDL_SWSURFACE);
18027 + if (bitdepth)
18028 + {
18029 + #ifdef DEBUG
18030 + fprintf(stderr, "Bit depth: %d\n", bitdepth);
18031 + #endif
18032 + break;
18033 + }
18034 + else
18035 + {
18036 + fprintf(stderr, "Video mode %dx%d@%d not available\n", current_width, current_height, aScreenDepth[i]);
18037 + }
18038 + }
18039 + if (bitdepth == 0)
18040 + {
18041 + /* Find a SDL video mode from standard resolutions */
18042 + for (j = 0; j < MAX_SCREEN_MODES && !bitdepth; j++)
18043 + {
18044 + if (x_size_table[j] < current_width || y_size_table[j] < current_height)
18045 + continue;
18046 + for (i = 0; aScreenDepth[i] != 0 && !bitdepth; i++)
18047 + {
18048 + bitdepth = SDL_VideoModeOK(x_size_table[j], y_size_table[j], aScreenDepth[i], SDL_SWSURFACE);
18049 + if (bitdepth)
18050 + {
18051 + #ifdef DEBUG
18052 + fprintf(stderr, "Bit depth: %d\n", bitdepth);
18053 + #endif
18054 + gfxvidinfo.width = current_width = x_size_table[j];
18055 + gfxvidinfo.height = current_height = y_size_table[j];
18056 + break;
18057 + }
18058 + else
18059 + {
18060 + fprintf(stderr, "Video mode %dx%d@%d not available\n", current_width, current_height, aScreenDepth[i]);
18061 + }
18062 + }
18063 + }
18064 + if (bitdepth == 0)
18065 + {
18066 + fprintf(stderr, "No video mode found!\n");
18067 + return 0;
18068 + }
18069 + }
18070 +
18071 + graphics_subinit ();
18072 +
18073 +
18074 + if (!init_colors ())
18075 + return 0;
18076 +
18077 + buttonstate[0] = buttonstate[1] = buttonstate[2] = 0;
18078 + for (i = 0; i < 256; i++)
18079 + keystate[i] = 0;
18080 +
18081 + return 1;
18082 +}
18083 +
18084 +static void graphics_subshutdown (void)
18085 +{
18086 +#ifdef DEBUG
18087 + fprintf(stderr, "Function: graphics_subshutdown\n");
18088 +#endif
18089 +
18090 + SDL_FreeSurface(prSDLScreen);
18091 +}
18092 +
18093 +void graphics_leave (void)
18094 +{
18095 +#ifdef DEBUG
18096 + fprintf(stderr, "Function: graphics_leave\n");
18097 +#endif
18098 +
18099 + graphics_subshutdown ();
18100 +
18101 + SDL_VideoQuit();
18102 +
18103 + dumpcustom ();
18104 +}
18105 +
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)
18109 +{
18110 + switch (prKeySym->sym)
18111 + {
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;
18132 +
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;
18143 +
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;
18160 +
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;
18171 +
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;
18186 +
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;
18191 +
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;
18196 +
18197 + case SDLK_PAGEUP: return AK_RAMI; /* PgUp mapped to right amiga */
18198 + case SDLK_PAGEDOWN: return AK_LAMI; /* PgDn mapped to left amiga */
18199 +
18200 + default: return -1;
18201 + }
18202 +}
18203 +
18204 +static int decode_fr (SDL_keysym *prKeySym)
18205 +{
18206 + switch(prKeySym->sym)
18207 + {
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;
18227 + }
18228 +}
18229 +
18230 +static int decode_us (SDL_keysym *prKeySym)
18231 +{
18232 + switch(prKeySym->sym)
18233 + {
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;
18254 + }
18255 +}
18256 +
18257 +static int decode_de (SDL_keysym *prKeySym)
18258 +{
18259 + switch(prKeySym->sym)
18260 + {
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;
18285 + }
18286 +}
18287 +
18288 +static int decode_se (SDL_keysym *prKeySym)
18289 +{
18290 + switch(prKeySym->sym)
18291 + {
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;
18312 + }
18313 +}
18314 +
18315 +static int decode_it (SDL_keysym *prKeySym)
18316 +{
18317 + switch(prKeySym->sym)
18318 + {
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;
18339 + }
18340 +}
18341 +
18342 +static int decode_es (SDL_keysym *prKeySym)
18343 +{
18344 + switch(prKeySym->sym)
18345 + {
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;
18364 + }
18365 +}
18366 +
18367 +static int keycode2amiga(SDL_keysym *prKeySym)
18368 +{
18369 + int iAmigaKeycode = kc_decode(prKeySym);
18370 + if (iAmigaKeycode == -1)
18371 + {
18372 + switch (currprefs.keyboard_lang)
18373 + {
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);
18386 + default:
18387 + return -1;
18388 + }
18389 + }
18390 + return iAmigaKeycode;
18391 +}
18392 +
18393 +static int refresh_necessary = 0;
18394 +
18395 +void handle_events (void)
18396 +{
18397 + SDL_Event rEvent;
18398 + int iAmigaKeyCode;
18399 + int i, j;
18400 + int iIsHotKey = 0;
18401 +#ifdef DEBUG
18402 + fprintf(stderr, "Function: handle_events\n");
18403 +#endif
18404 +
18405 + /* Handle GUI events */
18406 + gui_handle_events ();
18407 +
18408 + while (SDL_PollEvent(&rEvent))
18409 + {
18410 + switch (rEvent.type)
18411 + {
18412 + case SDL_QUIT:
18413 +#ifdef DEBUG
18414 + fprintf(stderr, "Event: quit\n");
18415 +#endif
18416 + uae_quit();
18417 + break;
18418 + case SDL_KEYDOWN:
18419 +#ifdef DEBUG
18420 + fprintf(stderr, "Event: key down\n");
18421 +#endif
18422 + /* Check for hotkey sequence */
18423 + i = 0;
18424 + while (arHotKeys[i].pfHandler != NULL)
18425 + {
18426 + if (rEvent.key.keysym.sym == arHotKeys[i].aHotKeys[0])
18427 + {
18428 + arHotKeys[i].aPressedKeys[0] = 1;
18429 + iIsHotKey = 1;
18430 + }
18431 + if (arHotKeys[i].aPressedKeys[0] == 1 &&
18432 + rEvent.key.keysym.sym == arHotKeys[i].aHotKeys[1])
18433 + {
18434 + arHotKeys[i].aPressedKeys[1] = 1;
18435 + arHotKeys[i].pfHandler();
18436 + iIsHotKey = 1;
18437 + }
18438 + i++;
18439 + }
18440 + if (iIsHotKey == 0)
18441 + {
18442 + /* No hotkey sequence */
18443 + iAmigaKeyCode = keycode2amiga(&(rEvent.key.keysym));
18444 + if (iAmigaKeyCode >= 0)
18445 + {
18446 + if (!keystate[iAmigaKeyCode])
18447 + {
18448 + keystate[iAmigaKeyCode] = 1;
18449 + record_key(iAmigaKeyCode << 1);
18450 + }
18451 + }
18452 + }
18453 + break;
18454 + case SDL_KEYUP:
18455 +#ifdef DEBUG
18456 + fprintf(stderr, "Event: key up\n");
18457 +#endif
18458 + /* Check for hotkey sequence */
18459 + i = 0;
18460 + while (arHotKeys[i].pfHandler != NULL)
18461 + {
18462 + for (j = 0; j < 2; j++)
18463 + {
18464 + if (rEvent.key.keysym.sym == arHotKeys[i].aHotKeys[j] &&
18465 + arHotKeys[i].aPressedKeys[j] == 1)
18466 + {
18467 + arHotKeys[i].aPressedKeys[j] = 0;
18468 + iIsHotKey = 1;
18469 + }
18470 + }
18471 + i++;
18472 + }
18473 + if (iIsHotKey == 0)
18474 + {
18475 + iAmigaKeyCode = keycode2amiga(&(rEvent.key.keysym));
18476 + if (iAmigaKeyCode >= 0)
18477 + {
18478 + keystate[iAmigaKeyCode] = 0;
18479 + record_key((iAmigaKeyCode << 1) | 1);
18480 + }
18481 + }
18482 + break;
18483 + case SDL_MOUSEBUTTONDOWN:
18484 +#ifdef DEBUG
18485 + fprintf(stderr, "Event: mouse button down\n");
18486 +#endif
18487 + buttonstate[rEvent.button.button-1] = 1;
18488 + break;
18489 + case SDL_MOUSEBUTTONUP:
18490 +#ifdef DEBUG
18491 + fprintf(stderr, "Event: mouse button up\n");
18492 +#endif
18493 + buttonstate[rEvent.button.button-1] = 0;
18494 + break;
18495 + case SDL_MOUSEMOTION:
18496 +#ifdef DEBUG
18497 + fprintf(stderr, "Event: mouse motion\n");
18498 +#endif
18499 + newmousecounters = 1;
18500 + lastmx += rEvent.motion.xrel;
18501 + lastmy += rEvent.motion.yrel;
18502 + break;
18503 + }
18504 + }
18505 +#if defined PICASSO96
18506 + if (screen_is_picasso && refresh_necessary)
18507 + {
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);
18511 + }
18512 + else if (screen_is_picasso && picasso_has_invalid_lines)
18513 + {
18514 + int i;
18515 + int strt = -1;
18516 + picasso_invalid_lines[picasso_vidinfo.height] = 0;
18517 + for (i = picasso_invalid_start; i < picasso_invalid_stop + 2; i++)
18518 + {
18519 + if (picasso_invalid_lines[i])
18520 + {
18521 + picasso_invalid_lines[i] = 0;
18522 + if (strt != -1)
18523 + continue;
18524 + strt = i;
18525 + }
18526 + else
18527 + {
18528 + if (strt == -1)
18529 + continue;
18530 + SDL_UpdateRect(prSDLScreen, 0, strt, picasso_vidinfo.width, i-strt);
18531 + strt = -1;
18532 + }
18533 + }
18534 + if (strt != -1)
18535 + abort ();
18536 + }
18537 + picasso_has_invalid_lines = 0;
18538 + picasso_invalid_start = picasso_vidinfo.height + 1;
18539 + picasso_invalid_stop = -1;
18540 +#endif
18541 +
18542 + /* Handle UAE reset */
18543 + if ((keystate[AK_CTRL] || keystate[AK_RCTRL]) && keystate[AK_LAMI] && keystate[AK_RAMI])
18544 + uae_reset ();
18545 +}
18546 +
18547 +int check_prefs_changed_gfx (void)
18548 +{
18549 +
18550 + if (changed_prefs.gfx_width != currprefs.gfx_width
18551 + || changed_prefs.gfx_height != currprefs.gfx_height)
18552 + {
18553 + fixup_prefs_dimensions (&changed_prefs);
18554 + }
18555 +
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)
18565 + {
18566 + return 0;
18567 + }
18568 +#ifdef DEBUG
18569 + fprintf(stderr, "Function: check_prefs_changed_gfx\n");
18570 +#endif
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;
18581 +
18582 + gui_update_gfx ();
18583 +
18584 + graphics_subinit ();
18585 +
18586 + /* if (! inwindow)
18587 + XWarpPointer (display, None, mywin, 0, 0, 0, 0,
18588 + current_width / 2, current_height / 2);
18589 + */
18590 + notice_screen_contents_lost ();
18591 + init_row_map ();
18592 + if (screen_is_picasso)
18593 + picasso_enablescreen (1);
18594 + return 0;
18595 +}
18596 +
18597 +int debuggable (void)
18598 +{
18599 + return 1;
18600 +}
18601 +
18602 +int needmousehack (void)
18603 +{
18604 + return 1;
18605 +}
18606 +
18607 +void LED (int on)
18608 +{
18609 +#if 0 /* Maybe that is responsible for the joystick emulation problems on SunOS? */
18610 + static int last_on = -1;
18611 + XKeyboardControl control;
18612 +
18613 + if (last_on == on)
18614 + return;
18615 + last_on = on;
18616 + control.led = 1; /* implementation defined */
18617 + control.led_mode = on ? LedModeOn : LedModeOff;
18618 + XChangeKeyboardControl(display, KBLed | KBLedMode, &control);
18619 +#endif
18620 +}
18621 +
18622 +#ifdef PICASSO96
18623 +
18624 +void DX_Invalidate (int first, int last)
18625 +{
18626 +#ifdef DEBUG
18627 + fprintf(stderr, "Function: DX_Invalidate %i - %i\n", first, last);
18628 +#endif
18629 +
18630 + if (first > last)
18631 + return;
18632 +
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;
18638 +
18639 + while (first <= last)
18640 + {
18641 + picasso_invalid_lines[first] = 1;
18642 + first++;
18643 + }
18644 +}
18645 +
18646 +int DX_BitsPerCannon (void)
18647 +{
18648 + return 8;
18649 +}
18650 +
18651 +static int palette_update_start=256;
18652 +static int palette_update_end=0;
18653 +
18654 +void DX_SetPalette (int start, int count)
18655 +{
18656 +#ifdef DEBUG
18657 + fprintf(stderr, "Function: DX_SetPalette_real\n");
18658 +#endif
18659 +
18660 + if (! screen_is_picasso || picasso96_state.RGBFormat != RGBFB_CHUNKY)
18661 + return;
18662 +
18663 + if (picasso_vidinfo.pixbytes != 1)
18664 + {
18665 + /* This is the case when we're emulating a 256 color display. */
18666 + while (count-- > 0)
18667 + {
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));
18674 + }
18675 + return;
18676 + }
18677 +
18678 + while (count-- > 0)
18679 + {
18680 +#if 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);
18686 +#endif
18687 + start++;
18688 + }
18689 +}
18690 +
18691 +int DX_FillResolutions (uae_u16 *ppixel_format)
18692 +{
18693 + int i, count = 0;
18694 + int w = 0;
18695 + int h = 0;
18696 + int emulate_chunky = 0;
18697 +
18698 +#ifdef DEBUG
18699 + fprintf(stderr, "Function: DX_FillResolutions\n");
18700 +#endif
18701 +
18702 + /* Find out, which is the highest resolution the SDL can offer */
18703 + for (i = MAX_SCREEN_MODES-1; i>=0; i--)
18704 + {
18705 + if (bitdepth == SDL_VideoModeOK(x_size_table[i], y_size_table[i], bitdepth, SDL_SWSURFACE))
18706 + {
18707 + w = x_size_table[i];
18708 + h = y_size_table[i];
18709 + break;
18710 + }
18711 + }
18712 +
18713 +#ifdef DEBUG
18714 + fprintf(stderr, "Max. Picasso screen size: %d x %d\n", w, h);
18715 +#endif
18716 +
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
18722 + : RGBFB_NONE);
18723 +
18724 + *ppixel_format = 1 << picasso_vidinfo.rgbformat;
18725 + if (bit_unit == 16 || bit_unit == 32)
18726 + {
18727 + *ppixel_format |= RGBFF_CHUNKY;
18728 + emulate_chunky = 1;
18729 + }
18730 +
18731 + for (i = 0; i < MAX_SCREEN_MODES && count < MAX_PICASSO_MODES; i++)
18732 + {
18733 + int j;
18734 + for (j = 0; j <= emulate_chunky && count < MAX_PICASSO_MODES; j++)
18735 + {
18736 + if (x_size_table[i] <= w && y_size_table[i] <= h)
18737 + {
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;
18746 +#ifdef DEBUG
18747 + fprintf(stderr, "Picasso resolution %d x %d @ %d allowed\n", DisplayModes[count].res.width, DisplayModes[count].res.height, DisplayModes[count].depth);
18748 +#endif
18749 +
18750 + count++;
18751 + }
18752 + }
18753 + }
18754 +#ifdef DEBUG
18755 + fprintf(stderr, "Max. Picasso screen size: %d x %d\n", picasso_maxw, picasso_maxh);
18756 +#endif
18757 + return count;
18758 +}
18759 +
18760 +static void set_window_for_picasso (void)
18761 +{
18762 +#ifdef DEBUG
18763 + fprintf(stderr, "Function: set_window_for_picasso\n");
18764 +#endif
18765 +
18766 + if (current_width == picasso_vidinfo.width && current_height == picasso_vidinfo.height)
18767 + return;
18768 +
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);
18774 +}
18775 +
18776 +void gfx_set_picasso_modeinfo (int w, int h, int depth, int rgbfmt)
18777 +{
18778 +#ifdef DEBUG
18779 + fprintf(stderr, "Function: gfx_set_picasso_modeinfo w: %i h: %i depth: %i rgbfmt: %i\n",w, h, depth, rgbfmt);
18780 +#endif
18781 +
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();
18788 +}
18789 +
18790 +void gfx_set_picasso_baseaddr (uaecptr a)
18791 +{
18792 +}
18793 +
18794 +void gfx_set_picasso_state (int on)
18795 +{
18796 +#ifdef DEBUG
18797 + fprintf(stderr, "Function: gfx_set_picasso_state\n");
18798 +#endif
18799 +
18800 + if (on == screen_is_picasso)
18801 + return;
18802 + graphics_subshutdown ();
18803 + screen_is_picasso = on;
18804 + if (on)
18805 + {
18806 + // Set height, width for Picasso gfx
18807 + current_width = picasso_vidinfo.width;
18808 + current_height = picasso_vidinfo.height;
18809 + }
18810 + else
18811 + {
18812 + // Set height, width for Amiga gfx
18813 + current_width = gfxvidinfo.width;
18814 + current_height = gfxvidinfo.height;
18815 + }
18816 + graphics_subinit ();
18817 + if (on)
18818 + DX_SetPalette (0, 256);
18819 +}
18820 +
18821 +uae_u8 *gfx_lock_picasso (void)
18822 +{
18823 +#ifdef DEBUG
18824 + fprintf(stderr, "Function: gfx_lock_picasso\n");
18825 +#endif
18826 + SDL_LockSurface(prSDLScreen);
18827 + return prSDLScreen->pixels;
18828 +}
18829 +
18830 +void gfx_unlock_picasso (void)
18831 +{
18832 +#ifdef DEBUG
18833 + fprintf(stderr, "Function: gfx_unlock_picasso\n");
18834 +#endif
18835 + SDL_UnlockSurface(prSDLScreen);
18836 +}
18837 +#endif
18838 +
18839 +int lockscr (void)
18840 +{
18841 +#ifdef DEBUG
18842 + fprintf(stderr, "Function: lockscr\n");
18843 +#endif
18844 + SDL_LockSurface(prSDLScreen);
18845 + return 1;
18846 +}
18847 +
18848 +void unlockscr (void)
18849 +{
18850 +#ifdef DEBUG
18851 + fprintf(stderr, "Function: unlockscr\n");
18852 +#endif
18853 + SDL_UnlockSurface(prSDLScreen);
18854 +}
18855 +
18856 +static void handle_mousegrab (void)
18857 +{
18858 + if (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF)
18859 + {
18860 + SDL_WM_GrabInput(SDL_GRAB_ON);
18861 + SDL_WarpMouse(0, 0);
18862 + }
18863 + else
18864 + {
18865 + SDL_WM_GrabInput(SDL_GRAB_OFF);
18866 + }
18867 +}
18868 +
18869 +static void handle_inhibit (void)
18870 +{
18871 + toggle_inhibit_frame (IHF_SCROLLLOCK);
18872 +}
18873 +
18874 +
18875 +static void handle_interpol (void)
18876 +{
18877 + if (currprefs.sound_interpol == 0)
18878 + {
18879 + currprefs.sound_interpol = 1;
18880 + printf ("Interpol on: rh\n");
18881 + }
18882 + else if (currprefs.sound_interpol == 1)
18883 + {
18884 + currprefs.sound_interpol = 2;
18885 + printf ("Interpol on: crux\n");
18886 + }
18887 + else
18888 + {
18889 + currprefs.sound_interpol = 0;
18890 + printf ("Interpol off\n");
18891 + }
18892 +}
18893 +
18894 +static void framerate_up (void)
18895 +{
18896 + if (currprefs.gfx_framerate < 20)
18897 + changed_prefs.gfx_framerate = currprefs.gfx_framerate + 1;
18898 +}
18899 +
18900 +static void framerate_down (void)
18901 +{
18902 + if (currprefs.gfx_framerate > 1)
18903 + changed_prefs.gfx_framerate = currprefs.gfx_framerate - 1;
18904 +}
18905 +
18906 +void target_save_options (FILE *f, struct uae_prefs *p)
18907 +{
18908 +}
18909 +
18910 +int target_parse_option (struct uae_prefs *p, char *option, char *value)
18911 +{
18912 + return 0;
18913 +}
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
18917 @@ -43,7 +43,7 @@
18918 #define O_NONBLOCK O_NDELAY
18919 #endif
18920
18921 -#define SERIALDEBUG 1 /* 0, 1, 2 3 */
18922 +#define SERIALDEBUG 0 /* 0, 1, 2 3 */
18923 #define MODEMTEST 0 /* 0 or 1 */
18924
18925 void serial_open (void);
18926 @@ -80,18 +80,25 @@
18927
18928 int sd = -1;
18929
18930 +static int ser_log = 0;
18931 +
18932 #ifdef POSIX_SERIAL
18933 struct termios tios;
18934 #endif
18935
18936 -uae_u16 serper=0,serdat;
18937 +uae_u16 serper=0, serdat = 0;
18938
18939 void SERPER (uae_u16 w)
18940 {
18941 int baud=0, pspeed;
18942
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);
18948 +#endif
18949 return;
18950 + }
18951
18952 #if defined POSIX_SERIAL
18953 if (serper == w) /* don't set baudrate if it's already ok */
18954 @@ -178,12 +185,9 @@
18955 {
18956 unsigned char z;
18957
18958 - if (!currprefs.use_serial)
18959 - return;
18960 -
18961 z = (unsigned char)(w&0xff);
18962
18963 - if (currprefs.serial_demand && !dtr) {
18964 + if (currprefs.serial_demand && !dtr && !ser_log) {
18965 if (!isbaeh) {
18966 write_log("SERDAT: Baeh.. Your software needs SERIAL_ALWAYS to work properly.\n");
18967 isbaeh=1;
18968 @@ -206,8 +210,6 @@
18969
18970 uae_u16 SERDATR (void)
18971 {
18972 - if (!currprefs.use_serial)
18973 - return 0;
18974 #if SERIALDEBUG > 2
18975 write_log ("SERDATR: read 0x%04x\n", serdat);
18976 #endif
18977 @@ -284,10 +286,14 @@
18978
18979 void serial_flush_buffer(void)
18980 {
18981 - if (serdev == 1) {
18982 - if (outlast) {
18983 + if (serdev == 1 || ser_log) {
18984 + if (outlast) {
18985 if (sd != 0) {
18986 - write (sd, outbuf, outlast);
18987 + write (sd, outbuf, outlast);
18988 + }
18989 + if (ser_log) {
18990 + outbuf[outlast] = 0;
18991 + write_log("SER: %s\n", outbuf);
18992 }
18993 }
18994 outlast = 0;
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
18998 @@ -0,0 +1,419 @@
18999 + /*
19000 + * UAE - The Un*x Amiga Emulator
19001 + *
19002 + * Serial Line Emulation
19003 + *
19004 + * (c) 1996, 1997 Stefan Reinauer <stepan@linux.de>
19005 + * (c) 1997 Christian Schmitt <schmitt@freiburg.linux.de>
19006 + *
19007 + */
19008 +
19009 +#include "sysconfig.h"
19010 +#include "sysdeps.h"
19011 +
19012 +#include "config.h"
19013 +#include "options.h"
19014 +#include "uae.h"
19015 +#include "memory.h"
19016 +#include "custom.h"
19017 +#include "newcpu.h"
19018 +#include "cia.h"
19019 +
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
19025 +#endif
19026 +
19027 +#ifdef POSIX_SERIAL
19028 +#include <termios.h>
19029 +#include <unistd.h>
19030 +#include <sys/ioctl.h>
19031 +#endif
19032 +
19033 +#if !defined B300 || !defined B1200 || !defined B2400 || !defined B4800 || !defined B9600
19034 +#undef POSIX_SERIAL
19035 +#endif
19036 +#if !defined B19200 || !defined B57600 || !defined B115200 || !defined B230400
19037 +#undef POSIX_SERIAL
19038 +#endif
19039 +
19040 +#ifndef O_NONBLOCK
19041 +#define O_NONBLOCK O_NDELAY
19042 +#endif
19043 +
19044 +#define SERIALDEBUG 0 /* 0, 1, 2 3 */
19045 +#define MODEMTEST 0 /* 0 or 1 */
19046 +
19047 +void serial_open (void);
19048 +void serial_close (void);
19049 +void serial_init (void);
19050 +void serial_exit (void);
19051 +
19052 +void serial_dtr_on (void);
19053 +void serial_dtr_off (void);
19054 +
19055 +void serial_flush_buffer (void);
19056 +static int serial_read (char *buffer);
19057 +
19058 +int serial_readstatus (void);
19059 +uae_u16 serial_writestatus (int, int);
19060 +
19061 +uae_u16 SERDATR (void);
19062 +
19063 +int SERDATS (void);
19064 +void SERPER (uae_u16 w);
19065 +void SERDAT (uae_u16 w);
19066 +
19067 +static char inbuf[1024], outbuf[1024];
19068 +static int inptr, inlast, outlast;
19069 +
19070 +int waitqueue=0,
19071 + carrier=0,
19072 + serdev=0,
19073 + dsr=0,
19074 + dtr=0,
19075 + isbaeh=0,
19076 + doreadser=0,
19077 + serstat=-1;
19078 +
19079 +int sd = -1;
19080 +
19081 +static int ser_log = 0;
19082 +
19083 +#ifdef POSIX_SERIAL
19084 + struct termios tios;
19085 +#endif
19086 +
19087 +uae_u16 serper=0, serdat = 0;
19088 +
19089 +void SERPER (uae_u16 w)
19090 +{
19091 + int baud=0, pspeed;
19092 +
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);
19097 +#endif
19098 + return;
19099 + }
19100 +
19101 +#if defined POSIX_SERIAL
19102 + if (serper == w) /* don't set baudrate if it's already ok */
19103 + return;
19104 + serper=w;
19105 +
19106 + if (w&0x8000)
19107 + write_log ("SERPER: 9bit transmission not implemented.\n");
19108 +
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.
19113 + */
19114 +
19115 + case 0x2e9b:
19116 + case 0x2e14: baud=300; pspeed=B300; break;
19117 + case 0x170a:
19118 + case 0x0b85: baud=1200; pspeed=B1200; break;
19119 + case 0x05c2:
19120 + case 0x05b9: baud=2400; pspeed=B2400; break;
19121 + case 0x02e9:
19122 + case 0x02e1: baud=4800; pspeed=B4800; break;
19123 + case 0x0174:
19124 + case 0x0170: baud=9600; pspeed=B9600; break;
19125 + case 0x00b9:
19126 + case 0x00b8: baud=19200; pspeed=B19200; break;
19127 + case 0x005c:
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;
19132 + default:
19133 + write_log ("SERPER: unsupported baudrate (0x%04x) %d\n",w&0x7fff,
19134 + (unsigned int)(3579546.471/(double)((w&0x7fff)+1))); return;
19135 + }
19136 +
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");
19141 + return;
19142 + }
19143 +
19144 + if (cfsetispeed (&tios, pspeed) < 0) { /* set serial input speed */
19145 + write_log ("SERPER: CFSETISPEED (%d bps) failed\n", baud);
19146 + return;
19147 + }
19148 + if (cfsetospeed (&tios, pspeed) < 0) { /* set serial output speed */
19149 + write_log ("SERPER: CFSETOSPEED (%d bps) failed\n", baud);
19150 + return;
19151 + }
19152 +
19153 + if (tcsetattr (sd, TCSADRAIN, &tios) < 0) {
19154 + write_log ("SERPER: TCSETATTR failed\n");
19155 + return;
19156 + }
19157 + }
19158 +#endif
19159 +
19160 +#if SERIALDEBUG > 0
19161 + if (serdev == 1)
19162 + write_log ("SERPER: baudrate set to %d bit/sec\n", baud);
19163 +#endif
19164 +}
19165 +
19166 +/* Not (fully) implemented yet:
19167 + *
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 :-< )
19173 + *
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
19177 + *
19178 + * - ADCON-Register ($9e write, $10 read) Bit 11 (UARTBRK)
19179 + * (see "Amiga Intern", pg 246)
19180 + */
19181 +
19182 +void SERDAT (uae_u16 w)
19183 +{
19184 + unsigned char z;
19185 +
19186 + z = (unsigned char)(w&0xff);
19187 +
19188 + if (currprefs.serial_demand && !dtr && !ser_log) {
19189 + if (!isbaeh) {
19190 + write_log("SERDAT: Baeh.. Your software needs SERIAL_ALWAYS to work properly.\n");
19191 + isbaeh=1;
19192 + }
19193 + return;
19194 + } else {
19195 + outbuf[outlast++] = z;
19196 + if (outlast == sizeof outbuf)
19197 + serial_flush_buffer();
19198 + }
19199 +
19200 +#if SERIALDEBUG > 2
19201 + write_log ("SERDAT: wrote 0x%04x\n", w);
19202 +#endif
19203 +
19204 + serdat|=0x2000; /* Set TBE in the SERDATR ... */
19205 + intreq|=1; /* ... and in INTREQ register */
19206 + return;
19207 +}
19208 +
19209 +uae_u16 SERDATR (void)
19210 +{
19211 +#if SERIALDEBUG > 2
19212 + write_log ("SERDATR: read 0x%04x\n", serdat);
19213 +#endif
19214 + waitqueue = 0;
19215 + return serdat;
19216 +}
19217 +
19218 +int SERDATS (void)
19219 +{
19220 + unsigned char z;
19221 +
19222 + if (!serdev) /* || (serdat&0x4000)) */
19223 + return 0;
19224 +
19225 + if (waitqueue == 1) {
19226 + intreq |= 0x0800;
19227 + return 1;
19228 + }
19229 +
19230 + if ((serial_read ((char *)&z)) == 1) {
19231 + waitqueue = 1;
19232 + serdat = 0x4100; /* RBF and STP set! */
19233 + serdat |= ((unsigned int)z) & 0xff;
19234 + intreq |= 0x0800; /* Set RBF flag (Receive Buffer full) */
19235 +
19236 +#if SERIALDEBUG > 1
19237 + write_log ("SERDATS: received 0x%02x --> serdat==0x%04x\n",
19238 + (unsigned int)z, (unsigned int)serdat);
19239 +#endif
19240 + return 1;
19241 + }
19242 + return 0;
19243 +}
19244 +
19245 +void serial_dtr_on(void)
19246 +{
19247 +#if SERIALDEBUG > 0
19248 + write_log ("DTR on.\n");
19249 +#endif
19250 + dtr=1;
19251 +
19252 + if (currprefs.serial_demand)
19253 + serial_open ();
19254 +}
19255 +
19256 +void serial_dtr_off(void)
19257 +{
19258 +#if SERIALDEBUG > 0
19259 + write_log ("DTR off.\n");
19260 +#endif
19261 + dtr=0;
19262 + if (currprefs.serial_demand)
19263 + serial_close ();
19264 +}
19265 +
19266 +static int serial_read (char *buffer)
19267 +{
19268 + if (inptr < inlast) {
19269 + *buffer = inbuf[inptr++];
19270 + return 1;
19271 + }
19272 +
19273 + if (serdev == 1) {
19274 + inlast = read (sd, inbuf, sizeof inbuf);
19275 + inptr = 0;
19276 + if (inptr < inlast) {
19277 + *buffer = inbuf[inptr++];
19278 + return 1;
19279 + }
19280 + }
19281 +
19282 + return 0;
19283 +}
19284 +
19285 +void serial_flush_buffer(void)
19286 +{
19287 + if (serdev == 1 || ser_log) {
19288 + if (outlast) {
19289 + if (sd != 0) {
19290 + write (sd, outbuf, outlast);
19291 + }
19292 + if (ser_log) {
19293 + outbuf[outlast] = 0;
19294 + write_log("SER: %s\n", outbuf);
19295 + }
19296 + }
19297 + outlast = 0;
19298 + } else {
19299 + outlast = 0;
19300 + inptr = 0;
19301 + inlast = 0;
19302 + }
19303 +}
19304 +
19305 +int serial_readstatus(void)
19306 +{
19307 + int status = 0;
19308 +
19309 +#ifdef POSIX_SERIAL
19310 + ioctl (sd, TIOCMGET, &status);
19311 +
19312 + if (status & TIOCM_CAR) {
19313 + if (!carrier) {
19314 + ciabpra |= 0x20; /* Push up Carrier Detect line */
19315 + carrier = 1;
19316 +#if SERIALDEBUG > 0
19317 + write_log ("Carrier detect.\n");
19318 +#endif
19319 + }
19320 + } else {
19321 + if (carrier) {
19322 + ciabpra &= ~0x20;
19323 + carrier = 0;
19324 +#if SERIALDEBUG > 0
19325 + write_log ("Carrier lost.\n");
19326 +#endif
19327 + }
19328 + }
19329 +
19330 + if (status & TIOCM_DSR) {
19331 + if (!dsr) {
19332 + ciabpra |= 0x08; /* DSR ON */
19333 + dsr = 1;
19334 + }
19335 + } else {
19336 + if (dsr) {
19337 + ciabpra &= ~0x08;
19338 + dsr = 0;
19339 + }
19340 + }
19341 +#endif
19342 + return status;
19343 +}
19344 +
19345 +uae_u16 serial_writestatus (int old, int nw)
19346 +{
19347 + if ((old & 0x80) == 0x80 && (nw & 0x80) == 0x00)
19348 + serial_dtr_on();
19349 + if ((old & 0x80) == 0x00 && (nw & 0x80) == 0x80)
19350 + serial_dtr_off();
19351 +
19352 + if ((old & 0x40) != (nw & 0x40))
19353 + write_log ("RTS %s.\n", ((nw & 0x40) == 0x40) ? "set" : "cleared");
19354 +
19355 + if ((old & 0x10) != (nw & 0x10))
19356 + write_log ("CTS %s.\n", ((nw & 0x10) == 0x10) ? "set" : "cleared");
19357 +
19358 + return nw; /* This value could also be changed here */
19359 +}
19360 +
19361 +void serial_open(void)
19362 +{
19363 + if (serdev == 1)
19364 + return;
19365 +
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);
19368 + return;
19369 + }
19370 +
19371 + serdev = 1;
19372 +
19373 +#ifdef POSIX_SERIAL
19374 + if (tcgetattr (sd, &tios) < 0) { /* Initialize Serial tty */
19375 + write_log ("Serial: TCGETATTR failed\n");
19376 + return;
19377 + }
19378 + cfmakeraw (&tios);
19379 +
19380 +#ifndef MODEMTEST
19381 + tios.c_cflag &= ~CRTSCTS; /* Disable RTS/CTS */
19382 +#else
19383 + tios.c_cflag |= CRTSCTS; /* Enabled for testing modems */
19384 +#endif
19385 +
19386 + if (tcsetattr (sd, TCSADRAIN, &tios) < 0) {
19387 + write_log ("Serial: TCSETATTR failed\n");
19388 + return;
19389 + }
19390 +#endif
19391 +}
19392 +
19393 +void serial_close (void)
19394 +{
19395 + if (sd >= 0)
19396 + close (sd);
19397 + serdev = 0;
19398 +}
19399 +
19400 +void serial_init (void)
19401 +{
19402 + if (!currprefs.use_serial)
19403 + return;
19404 +
19405 + if (!currprefs.serial_demand)
19406 + serial_open ();
19407 +
19408 + serdat = 0x2000;
19409 + return;
19410 +}
19411 +
19412 +void serial_exit (void)
19413 +{
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. */
19417 +}